/* Copyright 2006 by Sean Luke and George Mason University Licensed under the Academic Free License version 3.0 See the file "LICENSE" for more information */ package ec.rule; import ec.*; import ec.util.*; import java.io.*; /* * RuleSet.java * * Created: Tue Feb 20 13:19:00 2001 * By: Liviu Panait and Sean Luke */ /** * RuleSet is a set of Rules, implemented straightforwardly as an arbitrary-length array of Rules. * A RuleIndividual is simply a list of RuleSets. Most typically, a RuleIndividual contains a * single RuleSet, containing a variety of Rules. * RuleSets contain many useful subsetting and modification functions which you can use * in breeding operators which modify RuleSets and Rules. * *

Besides the Rules themselves, the only thing else a RuleSet contains is a pointer to a * corresponding RuleSetConstraints object, which holds all of its modification parameters. * See RuleSetConstraints for a description of these parameters. *

In addition to serialization for checkpointing, RuleSets may read and write themselves to streams in three ways. * *

Parameters
base.constraints
string
(name of the rule set constraints)

Default Base
rule.ruleset * @author Liviu Panait and Sean Luke * @version 1.0 */ public class RuleSet implements Prototype { /** The message to appear when printing the rule set */ public final static String N_RULES = "Num: "; public final static String P_RULESET = "ruleset"; /** The constraint for the rule set */ public static final String P_CONSTRAINTS = "constraints"; /** An index to a RuleSetConstraints */ public byte constraints; /* Returns the RuleSet's constraints. A good JIT compiler should inline this. */ public final RuleSetConstraints constraints(RuleInitializer initializer) { return initializer.ruleSetConstraints[constraints]; } /** The rules in the rule set */ public Rule[] rules = new Rule[0]; /** How many rules are there used in the rules array */ public int numRules = 0; public Object clone() { try { RuleSet newRuleSet = (RuleSet)(super.clone()); // copy the rules over if( rules != null ) { newRuleSet.rules = (Rule[])(rules.clone()); } else { newRuleSet.rules = null; } for(int x=0;x constraints(initializer).minSize ) { removeRandomRule( state, thread ); } while( state.random[thread].nextBoolean( constraints(initializer).p_add ) && numRules < constraints(initializer).maxSize ) { addRandomRule( state, thread ); } if( state.random[thread].nextBoolean( constraints(initializer).p_randorder ) ) { randomizeRulesOrder( state, thread ); } } /** Should be called by pipelines to "fix up" the rulesets before they have been mutated or crossed over. Override this method to do so. */ public void preprocessRules(final EvolutionState state, final int thread) { } /** Should be called by pipelines to "fix up" the rulesets after they have been mutated or crossed over. Override this method to do so. */ public void postprocessRules(final EvolutionState state, final int thread) { } /** Randomizes the order of the rules in the rule set. It is helpful when the order of rule is important for the conflict resolution. */ public void randomizeRulesOrder(final EvolutionState state, final int thread) { Rule temp; for( int i = numRules-1 ; i > 0 ; i-- ) { int j = state.random[thread].nextInt( i+1 ); temp = rules[i]; rules[i] = rules[j]; rules[j] = temp; } } /** Add a random rule to the rule set */ public void addRandomRule(final EvolutionState state, final int thread) { Rule newRule = (Rule)(constraints(((RuleInitializer)state.initializer)).rulePrototype.clone()); newRule.reset(state,thread); addRule(newRule); } /** Add a rule directly to the rule set. Does not copy the rule. */ public void addRule( Rule rule ) { if( ( rules == null && numRules == 0 ) || ( numRules == rules.length ) ) { Rule[] tempRules; if( rules == null ) { tempRules = new Rule[2]; } else { tempRules = new Rule[ (rules.length + 1 ) * 2 ]; } if( rules != null ) System.arraycopy( rules, 0, tempRules, 0, rules.length ); rules = tempRules; } // add the rule and increase the counter rules[ numRules++ ] = rule; } /** Removes a rule from the rule set and returns it. If index is out of bounds, then this method returns null. The rules are shifted down --- thus this is O(n). */ public Rule removeRule( int index ) { if (index >= numRules || index < 0 ) return null; Rule myrule = rules[index]; System.arraycopy(rules, index + 1, rules, index, numRules - index + 1); /* // swap to the top Rule myrule = rules[index]; rules[index] = rules[numRules-1]; */ numRules--; return myrule; } /** Removes a randomly-chosen rule from the rule set and returns it. If there are no rules to remove, this method returns null. */ public Rule removeRandomRule( final EvolutionState state, final int thread ) { if (numRules <= 0) return null; else return removeRule(state.random[thread].nextInt(numRules)); } /** Makes a copy of the rules in another RuleSet and adds the rule copies. */ public void join( final RuleSet other ) { // if there's not enough place to store the new rules, increase space if( rules.length <= numRules + other.numRules ) { Rule[] tempRules = new Rule[ rules.length + other.rules.length ]; System.arraycopy( rules, 0, tempRules, 0, numRules ); rules = tempRules; } // copy in the new rules System.arraycopy( other.rules, 0, rules, numRules, other.numRules ); // clone the rules for(int x=numRules;xsets. */ public RuleSet[] split( int[] points, RuleSet[] sets ) { // Do the first chunk or the whole thing for(int i=0; i < (points.length > 0 ? points[0] : rules.length); i++) sets[0].addRule((Rule)(rules[i].clone()) ); if (points.length > 0) { // do the in-between chunks for(int p = 1; p < points.length; p++) for(int i= points[p-1]; i < points[p]; i++) sets[p].addRule((Rule)(rules[i].clone()) ); // do the final chunk for(int i=points[points.length - 1]; i < rules.length; i++) sets[points.length].addRule((Rule)(rules[i].clone()) ); } return sets; } /** Splits the rule set into a number of disjoint rule sets, copying the rules and adding them to the sets as appropriate. Each rule independently throws a die to determine which ruleset it will go into. Sets must be already allocated. Comment: This function appends the split rulesets to the existing rulesets already in sets. */ public RuleSet[] split( final EvolutionState state, final int thread, RuleSet[] sets ) { for( int i = 0 ; i < numRules ; i++ ) sets[ state.random[ thread ].nextInt( sets.length ) ].addRule( (Rule)(rules[i].clone()) ); return sets; } /** Splits the rule set into a two disjoint rule sets, copying the rules and adding them to the sets as appropriate. The value prob is the probability that an element will land in the first set. Sets must be already allocated. Comment: This function appends the split rulesets to the existing rulesets already in sets. */ public RuleSet[] splitIntoTwo( final EvolutionState state, final int thread, RuleSet[] sets, float prob ) { for( int i = 0 ; i < numRules ; i++ ) if (state.random[thread].nextBoolean(prob)) sets[0].addRule((Rule)(rules[i].clone()) ); else sets[1].addRule((Rule)(rules[i].clone()) ); return sets; } /** Prints out the rule set in a readable fashion. */ public void printRuleSetForHumans(final EvolutionState state, final int log) { printRuleSetForHumans(state, log, Output.V_VERBOSE); } /** Prints out the rule set in a readable fashion. @deprecated Verbosity no longer has an effect */ public void printRuleSetForHumans(final EvolutionState state, final int log, final int verbosity) { state.output.println( "Ruleset contains " + numRules + " rules", log ); for( int i = 0 ; i < numRules ; i ++ ) { state.output.println( "Rule " + i + ":", log ); rules[i].printRuleForHumans( state, log ); } } /** Prints the rule set such that the computer can read it later */ public void printRuleSet(final EvolutionState state, final int log) { printRuleSet(state, log, Output.V_VERBOSE); } /** Prints the rule set such that the computer can read it later @deprecated Verbosity no longer has an effect */ public void printRuleSet(final EvolutionState state, final int log, final int verbosity) { state.output.println(N_RULES + Code.encode(numRules), log); for( int i = 0 ; i < numRules ; i ++ ) rules[i].printRule(state,log); } /** Prints the rule set such that the computer can read it later */ public void printRuleSet(final EvolutionState state, final PrintWriter writer) { writer.println( N_RULES + Code.encode(numRules) ); for( int i = 0 ; i < numRules ; i ++ ) rules[i].printRule(state,writer); } /** Reads the rule set */ public void readRuleSet(final EvolutionState state, final LineNumberReader reader) throws IOException { numRules = Code.readIntegerWithPreamble(N_RULES, state, reader); rules = new Rule[ numRules ]; for(int x=0;x