I’ve been working on an artificial intelligence system of late which has proved rather insightful into the workings of various rule systems. Of particular note I began to realise the simplicity that can programmed when you begin to use counteractive rules.
Counteractive Rules may, to the first look, seem rather silly, why write a rule in the first place if you must counter it later – doesn’t that tell you that the initial rule is weak?
Well, no, it doesn’t.
The specific rule based system I have been developing is based on Fuzzy Sets and Logic, and seeks to simulate the landing of Harrier aircraft onto a very small point. The problem at first glance seems immense. How can you factor in wind, ship speed, ground effect etc. into a simple program? That is where the beauty of Fuzzy systems comes into its own.
Rather than seeking to write a comprehensive rule set, I began to experiment with default rules, and counteractive rules. To begin with, asking the question, "What is the state I would want the plane when nothing else is firing". Once I had the default rules up I began to counter balance them.
So, the defaults said, I want the thrusters to be aimed down, and a large thrust to be provided for them to lightly counteract (although not totally counteract) its descent.
With that in hand I began to explore what else I would need. The problem seemed complicated in that I was working with two output variables, but as I explored more I realised that I didn’t need to constantly adjust all the outputs – in fact, doing so would cause the system to fail because I would be firing thrusters etc. in ways that would counteract the more important rules.
So, for example, I had a rule that said, once the Harrier gets too low, put the thrust up to full. If I had adjusted the directional vector then it could have counteracted the directional movement, and since the default and all subsequent vectors were aimed roughly downwards, increasing the thrust would always produce a upward force.
We, of course, are landing the aircraft, for our simulation, it was within reason to assume that the only reason the aircraft would move up is corrective. So I made a rule that if the aircraft was moving up, the thrusters should be turned off.
Now, if you are thinking in terms of standard boolean rules where either they are completely true, or completely false, then you are calling me stupid right now… for, if we want to move upward if we get too low, and we refuse to allow the aircraft to move up, then the two rules completely nullify each other… That is true!
However, we are not using boolean rules, we are using rules based on fuzzy sets.
As the aircraft gets lower, it begins to have greater membership within the set of "Low". This set, if we were to graph it, is not False, and at some arbitary point, instantly becomes True. Instead we say ,well, starting at this point, the aircrafts height begins to be low, it may only be slightly low (eg. a membership of 0.1). As it moves further into the set it more fully realises its "lowness". Now, when we go to apply the operation of full thrusters, the thrusters are scaled according to the degree of membership. As the aircraft becomes more fully in the range of our "Low" set, the full thrusters become more dominant, this becomes important when we have counteractive fuzzy rules.
Once it reaches a certain point, the set of full thrusters becomes so dominant that the aircraft begins to slow and then to go upwards. As it starts to move upwards it starts to move into our fuzzy set of "Up". This set is 0 at 0 m/s up and 1 at 1 m/s up, and has varying degrees of membership in between those two speeds. (eg. at 0.5 m/s, it is 0.5 in the set of Up)
As we move further into the Up set, our membership becomes bigger, and the dominance of our "No Thrusters" that we want to apply becomes greater.
What happens when these two rules fire at the same time? They counteract each other, but not in a dramatic way. Because they are acting on the same output (thrusters) we have the two sets outputing into the same set. To get our thruster power, we take the center of gravity of our set. If the Full Thrusters is the only rule firing then the thrusters go to full, if the No Thrusters is the only rule that is firing, then the thrusters turn off, if they fire equally then the thrusters have a middle value. What happens is the sets balance each other. As one increases the Center of Gravity moves towards it and so it gains dominance. This balances until an optimal movement is achieved, or until the circumstances change. Because the Up set is not fully 1 as soon as it goes up, it depends on the dominance of the other rule, it is still possible to travel up slowly for corrective purposes.
Then comes another interesting point… if we fire our thrusters full when we get too low, how do we land?
We have another counteractive rule. Over the space of 3 meters (of the optimal landing point) we have a triangular set defined. Where 1 meter to the left is 0 in terms of the landing space, and 1 meter to the right is 0, and right on top is 1. When the aircraft hovers over the landing site we kill the thrusters. If it is moving to the left or the right we fire the thrusters at a light angle.
Now, there are some rules which counteract these defaults… We actually want the aircraft to be within the safe landing speeds, so we have a rule that says, when in the landing site, if the aircraft is going any faster than the safe speeds we fire the thrusters full. With our fuzzy sets we can define these in such a way that as they move into the sets they gradually increase in power and dominance so that we don’t have an eccelectic firing sequence.
Furthermore, we define a couple of sets to the left and the right of the landing site so that we can provide some directional thrust to counteract and added movement and to let the aircraft know when we begin to get too close to the sides.
Then we just need a few more base rules, these being, if you are to the left of the pad then angle the thrusters to direct the aircraft towards the landing pad, and if you are to the right of the pad then you do the same.
I also add a few emergency parameters. Seeing as we are landing, we don’t need to be travelling fast, so if the speed goes over a certain limit to the left or right then the ship fires the thrusters in an angle to counteract it, and if it is going too fast down then thrusters go to full.
Whilst the overlap of rules seems a bit sloppy at first, it is essential to the safe and effective working of the system. It allows simplicity which makes the system easy to tweak and to understand. It is interesting in that functional decomposition (the breaking of a problem into smaller bite sized function bites) is very similar in thought to the way you need to approach a fuzzy system. By first dealing with the extremes and by knowing where you don’t need to worry about different outputs, and where you definitely need to override them, you can build your system with a flexibility that is unachievable in a traditional rule based system.
I have just come to note a very important concept when building a system based on fuzzy sets.
When one uses and AND operator on two fuzzy sets, it means that the output membership can be alot smoother and alot less dramatic then when you are making a rule dependant on simply one input. Say for example, you want a rule to fire when our aircraft is low and fast… As the aircraft begins to move into the fuzzy set “fast” it gains membership, yet it is not until it moves into the region of “low” that it begins to input.
As it moves into the set of low, our existing fast rule begins to become more powerful.
If you are using a min approach to the AND, the lower membership is the one the system focuses on to achieve its output.
If we had our membership in set “Low” as 0.5, and our membership in set “Fast” as 0.3, 0.3 would be taken as our scaling factor… as the ship gets faster, the membership gets higher, so maybe it overtakes the membership in low. As our membership moves faster, Low caps our rule firing, thus creating a more even situation.
If we were to use (instead of minimums) alternate weightings on each set (such as an accumulative method using multiplication of the sets) we would find our fuzzy system would get even smoother, rather than capping at max, the two variables both have a moderate impact, and so both are seen quite evidently when the rule fired (as opposed to just the smaller of the two memberships.)