001 /*
002 * SimuCS - Simulator to use with Classifier Systems
003 * MSc project - Oxford University
004 * by Benoit Isaac - Summer 2005
005 */
006
007 package simuLCS;
008
009 /**
010 * A Classifier is a rule: if CONDITION then ACTION.
011 * @author Benoit
012 *
013 */
014 public class Classifier {
015
016 public static final int PART_CONDITION = 0;
017 public static final int PART_ACTION = 1;
018 protected String condition;
019 protected String action;
020 protected String name;
021
022 public static final int COND_ALL = 0;
023 public static final int COND_MATCH = 1;
024 public static final int COND_EXACT = 2;
025
026 public static final int ACT_ALL = 0;
027 public static final int ACT_EXACT = 2;
028
029 public Classifier() {
030 name = "";
031 }
032
033 /**
034 * Creates a Classifier with the given condition and action.
035 * @param c
036 * @param a
037 */
038 public Classifier(String c, String a) {
039 condition = c;
040 action = a;
041 name = "";
042 }
043
044 public Classifier(String c, String a, String n) {
045 this(c, a);
046 setName(n);
047 }
048
049 /**
050 * Create a unique instance of a classifier shared by several Agents
051 * so that the user has to modify only this classifier to affect the
052 * behaviour of all the Agents
053 * @param c
054 * @param ag
055 * @return
056 */
057 public static int createSharedClassifier(Classifier c, Agent[] ag) {
058 if (c != null) {
059 for (int i = 0; i < ag.length; i++) {
060 if (ag[i].getBehaviour() != null) // agent using Classifiers
061 ag[i].getBehaviour().addClassifier(c);
062 }
063 return 0;
064 } else {
065 System.out.println("No classifier given.");
066 return -1;
067 }
068 }
069
070 public static int removeSharedClassifier(Classifier c, Agent[] ag) {
071 if (c != null) {
072 for (int i = 0; i < ag.length; i++) {
073 if (ag[i].getBehaviour() != null) // agent using Classifiers
074 ag[i].getBehaviour().removeClassifier(c);
075 }
076 return 0;
077 } else {
078 System.out.println("No classifier given.");
079 return -1;
080 }
081 }
082
083 /**
084 * Returns a Classifier object from a string "XXX->YYYY [cccc]"
085 * where X,Y = {0,1,#}
086 * XXX is the condition part, YYYY is the action part
087 * cccc is the name to put between square brackets (optional)
088 * @param s the String describing the classifier
089 * @param t the Template which describes the number of bits for cond/action
090 * @return a Classifier if the String is correct, null otherwise
091 */
092 public static Classifier fromString(String s, Template t) {
093 Classifier result;
094 // first bits : the condition part (XXX)
095 System.out.println("String:" + s + " | Template:" + t);
096 String condFromString = s.substring(0, t.getNbBitsCondition());
097 System.out.println("Condition:" + condFromString);
098 condFromString = getBits(condFromString);
099 if (condFromString == Config.PROBLEM) {
100 return null;
101 }
102 // after the symbols "->", there is the Action part (YYYY)
103 String actionFromString =
104 s.substring(
105 t.getNbBitsCondition() + 2,
106 t.getNbBitsCondition() + 2 + t.getNbBitsAction());
107 System.out.println("Action:" + condFromString);
108 actionFromString = getBits(actionFromString);
109 if (actionFromString == Config.PROBLEM) {
110 return null;
111 }
112 // TODO get the name between [ and ]
113
114 return (new Classifier(condFromString, actionFromString));
115 }
116
117 /**
118 * If a String contains only 0s and 1s, returns that string.
119 * Otherwise return a String indicating an Error
120 * @param s
121 * @see Config#PROBLEM
122 * @return
123 */
124 public static String getBits(String s) {
125 boolean isOK = true;
126 String toCheck;
127 for (int i = 0; i < s.length(); i++) {
128 toCheck = s.substring(i, i + 1);
129 // System.out.println("To Check:"+toCheck);
130 if (!toCheck.equals("1")
131 && !toCheck.equals("0")
132 && !toCheck.equals(String.valueOf(ZCSConfig.dontCare))) {
133 isOK = false;
134 // System.out.println("Incorrect bit.");
135 }
136 }
137 if (isOK) {
138 return s;
139 } else {
140 return Config.PROBLEM;
141 }
142 }
143
144 public String getAction() {
145 return action;
146 }
147
148 public String getBitsAction(int position, int length) {
149 return action.substring(position, position + length);
150 }
151
152 public String getCondition() {
153 return condition;
154 }
155
156 public String getBitsCondition(int position, int length) {
157 return condition.substring(position, position + length);
158 }
159
160 /**
161 * Get the bits from position <code>position</code> to <code>position + length</code>
162 * for the either the Condition or the Action, depending on <code>whichpart</code>
163 * @param position
164 * @param length
165 * @param whichpart @see Classifier#PART_ACTION @see Classifier#PART_CONDITION
166 * @return
167 */
168 public String getBits(int position, int length, int whichpart) {
169 switch (whichpart) {
170 case PART_CONDITION : // for the condition part (0)
171 return getBitsCondition(position, length);
172 case PART_ACTION : // for the action part (1)
173 return getBitsAction(position, length);
174 default : // do nothing
175 System.out.println(
176 whichpart + "->part unknown. Should be 0 or 1");
177 return "";
178 }
179 }
180
181 public void setAction(String string) {
182 action = string;
183 }
184
185 public void setCondition(String string) {
186 condition = string;
187 }
188
189 public void setBitsAction(String s, int position) {
190 //System.out.println("Action before : " + action);
191 StringBuffer newCond = new StringBuffer("");
192 // beginning of the action is the same
193 newCond.append(action.substring(0, position));
194 // changing the specified bit(s)
195 newCond.append(s);
196 // end of the action is the same, if there are still some bits
197 if (action.length() != newCond.length()) {
198 newCond.append(
199 action.substring(position + s.length(), action.length()));
200 }
201 action = newCond.toString();
202 //System.out.println("Action after : " + action);
203 }
204
205 public void setBitsCondition(String s, int position) {
206 //System.out.println("Condition before : " + condition);
207 StringBuffer newCond = new StringBuffer("");
208 // beginning of the condition is the same
209 newCond.append(condition.substring(0, position));
210 // changing the specified bit(s)
211 newCond.append(s);
212 // end of the condition is the same, if there are still some bits
213 if (condition.length() != newCond.length()) {
214 newCond.append(
215 condition.substring(position + s.length(), condition.length()));
216 }
217 condition = newCond.toString();
218 //System.out.println("Condition after : " + condition);
219 }
220
221 public void setBits(String s, int position, int whichpart) {
222 // System.out.println("Set bits from "+position+" with["+s+"] in "+whichpart);
223 switch (whichpart) {
224 case PART_CONDITION : // for the condition part
225 setBitsCondition(s, position);
226 break;
227 case PART_ACTION : // for the action part
228 setBitsAction(s, position);
229 break;
230 default : // do nothing
231 System.out.println("Part unknown. Should be 0 or 1");
232 }
233 }
234
235 /**
236 * Returns a string representing the classifier (ie. "Condition->Action")
237 */
238 public String toString() {
239 return (condition + "->" + action + " [" + name + "]");
240 }
241
242 public String getName() {
243 return name;
244 }
245
246 public void setName(String string) {
247 name = string;
248 }
249
250 /**
251 * Returns true if the classifier matches in the current situation.
252 *
253 * @param state The current situation which is the description of an external
254 * agent by a bit of strings.
255 */
256 public boolean match(String state) {
257 if (condition.length() != state.length())
258 return false;
259 for (int i = 0; i < condition.length(); i++) {
260 if (condition.charAt(i) != ZCSConfig.dontCare // not a #, check value
261 && condition.charAt(i) != state.charAt(i))
262 return false;
263 }
264 return true;
265 }
266
267 /**
268 * Returns true if the classifier satisfies the properties described by
269 * <code>CondMatch</code> and <code>ActMatch</code>
270 * @param c
271 * @param CondMatch
272 * @param ActMatch
273 * @return
274 */
275
276 public boolean match(Classifier c, int CondMatch, int ActMatch)
277 {
278 if(CondMatch == COND_MATCH && !this.match(c.getCondition()))
279 return false;
280 if(CondMatch == COND_EXACT && !this.getCondition().equals(c.getCondition()))
281 return false;
282 if(ActMatch == ACT_EXACT && !this.getAction().equals(c.getAction()))
283 return false;
284 // System.out.println("match : cond-"+CondMatch+" - act "+ActMatch);
285 return true;
286 }
287
288 /**
289 * Gives the "value" of this classifier to be plotted.
290 * Should be overriden by subclasses, depending on their implementation of the
291 * Classifiers (it could be strength, accuracy, fitness,...)
292 * @return A value of the Classifier
293 */
294 public double getValue()
295 {
296 return 0.;
297 }
298
299 }