Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OKBJavaConnector/ECJClient/src/ec/rule/RuleSet.java @ 13229

Last change on this file since 13229 was 6152, checked in by bfarka, 14 years ago

added ecj and custom statistics to communicate with the okb services #1441

File size: 18.1 KB
Line 
1/*
2  Copyright 2006 by Sean Luke and George Mason University
3  Licensed under the Academic Free License version 3.0
4  See the file "LICENSE" for more information
5*/
6
7
8package ec.rule;
9import ec.*;
10import ec.util.*;
11import java.io.*;
12
13/*
14 * RuleSet.java
15 *
16 * Created: Tue Feb 20 13:19:00 2001
17 * By: Liviu Panait and Sean Luke
18 */
19
20/**
21 * RuleSet is a set of Rules, implemented straightforwardly as an arbitrary-length array of Rules.
22 * A RuleIndividual is simply a list of RuleSets.  Most typically, a RuleIndividual contains a
23 * single RuleSet, containing a variety of Rules.
24 * RuleSets contain many useful subsetting and modification functions which you can use
25 * in breeding operators which modify RuleSets and Rules.
26 *
27 * <p> Besides the Rules themselves, the only thing else a RuleSet contains is a pointer to a
28 * corresponding RuleSetConstraints object, which holds all of its modification parameters.
29 * See RuleSetConstraints for a description of these parameters.
30
31 * <p>In addition to serialization for checkpointing, RuleSets may read and write themselves to streams in three ways.
32 *
33 * <ul>
34 * <li><b>writeRuleSet(...,DataOutput)/readRuleSet(...,DataInput)</b>&nbsp;&nbsp;&nbsp;This method
35 * transmits or receives a RuleSet in binary.  It is the most efficient approach to sending
36 * RuleSets over networks, etc.  The default versions of writeRuleSet/readRuleSet reads/writes out the number
37 * of rules, then calls read/writeRule(...) on each Rule.  Override this if you need more functionality.
38 *
39 * <li><b>printRuleSet(...,PrintWriter)/readRuleSet(...,LineNumberReader)</b>&nbsp;&nbsp;&nbsp;This
40 * approach transmits or receives a RuleSet in text encoded such that the RuleSet is largely readable
41 * by humans but can be read back in 100% by ECJ as well.  To do this, these methods will typically encode numbers
42 * using the <tt>ec.util.Code</tt> class.  These methods are mostly used to write out populations to
43 * files for inspection, slight modification, then reading back in later on.  <b>readRuleSet</b>
44 * reads in the number of rules, then calls readRule(...) on each new Rule.  <b>printRuleSet</b> writes
45 * out the number of rules, then calls printrule(...) on each new Rule.  Again, override this if you need more
46 * functionality.
47 *
48 * <li><b>printRuleSetForHumans(...,PrintWriter)</b>&nbsp;&nbsp;&nbsp;This
49 * approach prints a RuleSet in a fashion intended for human consumption only.
50 * <b>printRuleSetForHumans</b> prints out the number of rules, then calles <b>printRuleForHumans</b>
51 * on each Rule in turn.  You may wish to override this to provide more information instead.
52 * You should handle one of these methods properly
53 * to ensure RuleSets can be printed by ECJ.
54 * </ul>
55
56 <p><b>Parameters</b><br>
57 <table>
58 <tr><td valign=top><i>base</i>.<tt>constraints</tt><br>
59 <font size=-1>string</font></td>
60 <td valign=top>(name of the rule set constraints)</td></tr>
61 </table>
62 
63 <p><b>Default Base</b><br>
64 rule.ruleset
65
66
67 * @author Liviu Panait and Sean Luke
68 * @version 1.0
69 */
70public class RuleSet implements Prototype
71    {
72
73    /**
74       The message to appear when printing the rule set
75    */
76    public final static String N_RULES = "Num: ";
77    public final static String P_RULESET = "ruleset";
78    /**
79       The constraint for the rule set
80    */
81    public static final String P_CONSTRAINTS = "constraints";
82    /**
83       An index to a RuleSetConstraints
84    */
85    public byte constraints;
86
87    /* Returns the RuleSet's constraints.  A good JIT compiler should inline this. */
88    public final RuleSetConstraints constraints(RuleInitializer initializer)
89        {
90        return initializer.ruleSetConstraints[constraints];
91        }
92
93    /**
94       The rules in the rule set
95    */
96    public Rule[] rules = new Rule[0];
97    /**
98       How many rules are there used in the rules array
99    */
100    public int numRules = 0;
101
102
103    public Object clone()
104        {
105        try
106            {
107            RuleSet newRuleSet = (RuleSet)(super.clone());
108            // copy the rules over
109            if( rules != null )
110                {
111                newRuleSet.rules = (Rule[])(rules.clone());
112                }
113            else
114                {
115                newRuleSet.rules = null;
116                }
117            for(int x=0;x<numRules;x++)
118                newRuleSet.rules[x] = (Rule)(rules[x].clone());
119            return newRuleSet;
120            }
121        catch (CloneNotSupportedException e)
122            { throw new InternalError(); } // never happens
123        }
124
125
126
127    /**
128       How many rules are there used in the rules array
129    */
130   
131    public int numRules() { return numRules; }
132    /**
133       A reset method for randomly reinitializing the RuleSet
134    */
135    public void reset(final EvolutionState state, final int thread)
136        {
137        // reinitialize the array of rules
138        RuleInitializer initializer = ((RuleInitializer)state.initializer);
139        numRules = constraints(initializer).numRulesForReset(this,state,thread);
140
141        rules = new Rule[ numRules ];
142
143        for( int i = 0 ; i < rules.length ; i++ )
144            {
145            rules[i] = (Rule)(constraints(initializer).rulePrototype.clone());
146            rules[i].reset(state,thread);
147            }
148        }
149
150    /**
151       Mutates rules in the RuleSet independently with the given probability.
152    */
153    public void mutate( final EvolutionState state, final int thread)
154        {
155        RuleInitializer initializer = ((RuleInitializer)state.initializer);
156       
157        for( int i = 0 ; i < numRules ; i++ )
158            {
159            rules[i].mutate(state,thread);
160            }
161        while( state.random[thread].nextBoolean( constraints(initializer).p_del ) && numRules > constraints(initializer).minSize )
162            {
163            removeRandomRule( state, thread );
164            }
165        while( state.random[thread].nextBoolean( constraints(initializer).p_add ) && numRules < constraints(initializer).maxSize )
166            {
167            addRandomRule( state, thread );
168            }
169        if( state.random[thread].nextBoolean( constraints(initializer).p_randorder ) )
170            {
171            randomizeRulesOrder( state, thread );
172            }
173        }
174       
175    /**
176       Should be called by pipelines to "fix up" the rulesets before they have been
177       mutated or crossed over.  Override this method to do so.
178    */
179    public void preprocessRules(final EvolutionState state, final int thread)
180        {
181        }
182
183    /**
184       Should be called by pipelines to "fix up" the rulesets after they have been
185       mutated or crossed over.  Override this method to do so.
186    */
187    public void postprocessRules(final EvolutionState state, final int thread)
188        {
189        }
190       
191    /**
192       Randomizes the order of the rules in the rule set. It is helpful when the
193       order of rule is important for the conflict resolution.
194    */
195    public void randomizeRulesOrder(final EvolutionState state, final int thread)
196        {
197        Rule temp;
198        for( int i = numRules-1 ; i > 0 ; i-- )
199            {
200            int j = state.random[thread].nextInt( i+1 );
201            temp = rules[i];
202            rules[i] = rules[j];
203            rules[j] = temp;
204            }
205        }
206
207    /**
208       Add a random rule to the rule set
209    */
210    public void addRandomRule(final EvolutionState state, final int thread)
211        {
212        Rule newRule = (Rule)(constraints(((RuleInitializer)state.initializer)).rulePrototype.clone());
213        newRule.reset(state,thread);
214        addRule(newRule);
215        }
216
217    /**
218       Add a rule directly to the rule set.  Does not copy the rule.
219    */
220    public void addRule( Rule rule )
221        {
222        if( ( rules == null && numRules == 0 ) || ( numRules == rules.length ) )
223            {
224            Rule[] tempRules;
225            if( rules == null )
226                {
227                tempRules = new Rule[2];
228                }
229            else
230                {
231                tempRules = new Rule[ (rules.length + 1 ) * 2 ];
232                }
233            if( rules != null )
234                System.arraycopy( rules, 0, tempRules, 0, rules.length );
235            rules = tempRules;
236            }
237
238        // add the rule and increase the counter
239        rules[ numRules++ ] = rule;
240        }
241
242    /**
243       Removes a rule from the rule set and returns it.  If index is out of bounds, then
244       this method returns null.  The rules are shifted down --- thus this is O(n).
245    */
246    public Rule removeRule( int index )
247        {
248        if (index >= numRules || index < 0 ) return null;
249        Rule myrule = rules[index];
250        System.arraycopy(rules, index + 1, rules, index, numRules - index + 1);
251               
252        /*
253        // swap to the top
254        Rule myrule = rules[index];
255        rules[index] = rules[numRules-1];
256        */
257
258        numRules--;
259        return myrule;
260        }
261
262    /**
263       Removes a randomly-chosen rule from the rule set and returns it.  If there are no rules to remove,
264       this method returns null.
265    */
266    public Rule removeRandomRule( final EvolutionState state, final int thread )
267        {
268        if (numRules <= 0) return null;
269        else return removeRule(state.random[thread].nextInt(numRules));
270        }
271
272    /**
273       Makes a copy of the rules in another RuleSet and adds the rule copies.
274    */
275    public void join( final RuleSet other )
276        {
277        // if there's not enough place to store the new rules, increase space
278        if( rules.length <= numRules + other.numRules )
279            {
280            Rule[] tempRules = new Rule[ rules.length + other.rules.length ];
281            System.arraycopy( rules, 0, tempRules, 0, numRules );
282            rules = tempRules;
283            }
284        // copy in the new rules
285        System.arraycopy( other.rules, 0, rules, numRules, other.numRules );
286        // clone the rules
287        for(int x=numRules;x<numRules+other.numRules;x++)
288            rules[x] = (Rule)(rules[x].clone());
289        numRules += other.numRules;
290        }
291       
292    /**
293       Clears out existing rules, and loads the rules from the other ruleset without cloning them.
294       Mostly for use if you create temporary rulesets (see for example RuleCrossoverPipeline)
295    */
296    public void copyNoClone( final RuleSet other )
297        {
298        // if there's not enough place to store the new rules, increase space
299        if( rules.length <= other.numRules )
300            {
301            rules = new Rule[ other.numRules ];
302            }
303        // copy in the new rules
304        // System.out.println(other.rules);
305        System.arraycopy( other.rules, 0, rules, 0, other.numRules );
306        numRules = other.numRules;
307        }
308       
309    /**
310       Splits the rule set into n pieces, according to points, which *must* be sorted.
311       The rules in each piece are cloned and added to the equivalent set.  Sets must be already allocated.
312       sets.length must be 1+ points.length. 
313       Comment: This function appends the split rulesets to the existing rulesets already in <i>sets</i>.
314    */
315    public RuleSet[] split( int[] points, RuleSet[] sets )
316        {
317        // Do the first chunk or the whole thing
318        for(int i=0; i < (points.length > 0 ? points[0] : rules.length); i++)
319            sets[0].addRule((Rule)(rules[i].clone()) );
320               
321        if (points.length > 0)
322            {
323            // do the in-between chunks
324            for(int p = 1; p < points.length; p++)
325                for(int i= points[p-1]; i < points[p]; i++)
326                    sets[p].addRule((Rule)(rules[i].clone()) );
327               
328            // do the final chunk
329            for(int i=points[points.length - 1]; i < rules.length; i++)
330                sets[points.length].addRule((Rule)(rules[i].clone()) );
331            }
332        return sets;
333        }
334   
335    /**
336       Splits the rule set into a number of disjoint rule sets, copying the rules and adding
337       them to the sets as appropriate.  Each rule independently
338       throws a die to determine which ruleset it will go into.  Sets must be already allocated.
339       Comment: This function appends the split rulesets to the existing rulesets already in <i>sets</i>.
340    */
341    public RuleSet[] split( final EvolutionState state, final int thread, RuleSet[] sets )
342        {
343        for( int i = 0 ; i < numRules ; i++ )
344            sets[ state.random[ thread ].nextInt( sets.length ) ].addRule(
345                (Rule)(rules[i].clone()) );
346        return sets;
347        }
348   
349    /**
350       Splits the rule set into a two disjoint rule sets, copying the rules and adding
351       them to the sets as appropriate.  The value <i>prob</i> is the probability that an element will
352       land in the first set.  Sets must be already allocated.
353       Comment: This function appends the split rulesets to the existing rulesets already in <i>sets</i>.
354    */
355    public RuleSet[] splitIntoTwo( final EvolutionState state, final int thread, RuleSet[] sets, float prob )
356        {
357        for( int i = 0 ; i < numRules ; i++ )
358            if (state.random[thread].nextBoolean(prob))
359                sets[0].addRule((Rule)(rules[i].clone()) );
360            else
361                sets[1].addRule((Rule)(rules[i].clone()) );
362        return sets;
363        }
364   
365    /**
366       Prints out the rule set in a readable fashion.
367    */
368    public void printRuleSetForHumans(final EvolutionState state, final int log)
369        {
370        printRuleSetForHumans(state, log, Output.V_VERBOSE);
371        }
372               
373    /**
374       Prints out the rule set in a readable fashion.
375       @deprecated Verbosity no longer has an effect
376    */
377    public void printRuleSetForHumans(final EvolutionState state, final int log,
378        final int verbosity)
379        {
380        state.output.println( "Ruleset contains " + numRules + " rules",
381            log );
382        for( int i = 0 ; i < numRules ; i ++ )
383            {
384            state.output.println( "Rule " + i + ":", log );
385            rules[i].printRuleForHumans( state, log );
386            }
387        }
388
389    /**
390       Prints the rule set such that the computer can read it later
391    */
392    public void printRuleSet(final EvolutionState state, final int log)
393        {
394        printRuleSet(state, log, Output.V_VERBOSE);
395        }
396               
397    /**
398       Prints the rule set such that the computer can read it later
399       @deprecated Verbosity no longer has an effect
400    */
401    public void printRuleSet(final EvolutionState state,
402        final int log, final int verbosity)
403        {
404        state.output.println(N_RULES + Code.encode(numRules), log);
405        for( int i = 0 ; i < numRules ; i ++ )
406            rules[i].printRule(state,log);
407        }
408
409    /**
410       Prints the rule set such that the computer can read it later
411    */
412    public void printRuleSet(final EvolutionState state,
413        final PrintWriter writer)
414        {
415        writer.println( N_RULES + Code.encode(numRules) );
416        for( int i = 0 ; i < numRules ; i ++ )
417            rules[i].printRule(state,writer);
418        }
419
420    /**
421       Reads the rule set
422    */
423    public void readRuleSet(final EvolutionState state,
424        final LineNumberReader reader)
425        throws IOException
426        {
427        numRules = Code.readIntegerWithPreamble(N_RULES, state, reader);
428
429        rules = new Rule[ numRules ];
430        for(int x=0;x<numRules;x++)
431            {
432            rules[x] = (Rule)(constraints(((RuleInitializer)state.initializer)).rulePrototype.clone());
433            rules[x].readRule(state,reader);
434            }
435        }
436
437    /** Writes RuleSets out to a binary stream */
438    public void writeRuleSet(final EvolutionState state,
439        final DataOutput dataOutput) throws IOException
440        {
441        dataOutput.writeInt(numRules);
442        for(int x=0;x<numRules;x++)
443            rules[x].writeRule(state,dataOutput);
444        }
445
446    /** Reads RuleSets in from a binary stream */
447    public void readRuleSet(final EvolutionState state,
448        final DataInput dataInput) throws IOException
449        {
450        int ruleCount = dataInput.readInt();
451        if (rules==null || rules.length != ruleCount)
452            rules = new Rule[ruleCount];
453        for(int x=0;x<ruleCount;x++)
454            {
455            rules[x] = (Rule)(constraints((RuleInitializer)state.initializer).rulePrototype.clone());
456            rules[x].readRule(state,dataInput);
457            }
458        }
459
460
461    public Parameter defaultBase()
462        {
463        return RuleDefaults.base().push(P_RULESET);
464        }
465
466    public void setup(EvolutionState state, Parameter base)
467        {       
468        String constraintname = state.parameters.getString(
469            base.push( P_CONSTRAINTS ),defaultBase().push(P_CONSTRAINTS));
470        if (constraintname == null)
471            state.output.fatal("No RuleSetConstraints name given",
472                base.push( P_CONSTRAINTS ),defaultBase().push(P_CONSTRAINTS));
473
474        constraints = RuleSetConstraints.constraintsFor(constraintname,state).constraintNumber;
475        state.output.exitIfErrors();
476        }
477
478    /**
479       The hash code for the rule set.  This isn't a very good hash code,
480       but it has the benefit of not being O(n lg n) -- otherwise, we'd have
481       to do something like sort the rules in the individual first and then
482       do an ordered hash code of some sort, ick.
483    */
484    public int hashCode()
485        {
486        int hash = this.getClass().hashCode();
487        for(int x=0;x<rules.length;x++)
488            if (rules[x] !=null)
489                hash += rules[x].hashCode();
490        return hash;
491        }
492
493    public boolean equals( final Object _other )
494        {
495        if (!getClass().equals(_other.getClass()))  // not the same class, I'm conservative that way
496            return false;
497           
498        RuleSet other = (RuleSet)_other;
499        if( numRules != other.numRules )
500            return false;  // quick and dirty
501        if (numRules == 0 && other.numRules==0)
502            return true;  // quick and dirty
503           
504        // we need to sort the rulesets.  First, let's clone
505        // the rule arrays
506
507        Rule[] srules = (Rule[])(rules.clone());
508        Rule[] orules = (Rule[])(other.rules.clone());
509
510        java.util.Arrays.sort(srules);
511        java.util.Arrays.sort(orules);
512       
513        // Now march down and see if the rules are the same
514        for(int x=0;x<numRules;x++)
515            if (!(srules[x].equals(orules[x])))
516                return false;
517
518        return true;
519        }
520
521    }
Note: See TracBrowser for help on using the repository browser.