Print

Print


Gagh!  Found two more bugs.  I think this version is correct.

Sean


/*
  Copyright 2014 by Sean Luke
  Licensed under the Academic Free License version 3.0
  See the file "LICENSE" for more information
*/


package ec.breed;
import ec.*;
import ec.util.*;

/* 
 * CheckingPipeline.java
 * 
 * Created: Tue Feb 25 08:33:02 EST 2014
 * By: Sean Luke
 */

/**
 * CheckingPipeline is a BreedingPipeline which just passes through the
 * individuals it receives from its source 0, but only if those individuals
 * ALL pass a validation check (the method allValid(), which you must override).
 * It tries to find valid individuals some num-times times, and if it cannot, it
 * instead reproduces individuals from its source 1 and returns them instead.
 *
 * <p>In some cases you may wish instead to produce individuals which
 * are individually checked for validity, rather than together.  The easiest way
 * to do this is to add the CheckingPipeline as a child to a ForceBreedingPipeline
 * which has been set with num-inds=1.
 *
 <p><b>Typical Number of Individuals Produced Per <tt>produce(...)</tt> call</b><br>
 ...as many as either child produces

 <p><b>Number of Sources</b><br>
 2

 <p><b>Parameters</b><br>
 <table>
 <tr><td valign=top><i>base.</i><tt>num-times</tt><br>
 <font size=-1>int >= 1</font></td>
 <td valign=top>(number of times we try to get children from source 0 before giving up and using source 1)</td></tr>

 </table>
 <p><b>Default Base</b><br>
 breed.check

 * @author Sean Luke
 * @version 1.0 
 */

public class CheckingPipeline extends BreedingPipeline
    {
    public static final String P_CHECK = "check";
    public static final String P_NUMTIMES = "num-times";
    public static final int NUM_SOURCES = 2;
    
    public Parameter defaultBase() { return BreedDefaults.base().push(P_CHECK); }

    public int numSources() { return NUM_SOURCES; }

	int numTimes = 0;

    public void setup(final EvolutionState state, final Parameter base)
        {
        super.setup(state,base);
        Parameter def = defaultBase();
        numTimes = state.parameters.getInt(base.push(P_NUMTIMES), def.push(P_NUMTIMES),1);
        if (numTimes < 1)
        	state.output.fatal("CheckingPipeline must have a num-times value >= 1.", 
        		base.push(P_NUMTIMES),
        		def.push(P_NUMTIMES));
        if (likelihood != 1.0)
            state.output.warning("CheckingPipeline given a likelihood other than 1.0.  This is nonsensical and will be ignored.",
                base.push(P_LIKELIHOOD),
                def.push(P_LIKELIHOOD));
        }
    
    public boolean allValid(Individual[] inds, int numInds, int subpopulation, EvolutionState state, int thread)
    	{
    	return true;
    	}
    	
    public int produce(
        final int min, 
        final int max, 
        final int start,
        final int subpopulation,
        final Individual[] inds,
        final EvolutionState state,
        final int thread) 
        {
        Individual[] inds2 = new Individual[max];
        
        for(int i = 0; i < numTimes; i++)
        	{
			// grab individuals from our source and stick 'em into inds2 at position 0
			int n = sources[0].produce(min,max,0,subpopulation,inds2,state,thread);
			
			// check for validity
			if (!allValid(inds2, n, subpopulation, state, thread))
				continue;  // failure, try again
				
			// success!  Copy to inds and possibly clone
			System.arraycopy(inds2, 0, inds, start, n);
			if (sources[0] instanceof SelectionMethod)
				for(int q=start; q < n+start; q++)
					inds[q] = (Individual)(inds[q].clone());
			return n;
			}
			
		// big-time failure!  Grab from the other source
		int n = sources[1].produce(min,max,start,subpopulation,inds,state,thread);
		if (sources[0] instanceof SelectionMethod)
			for(int q=start; q < n+start; q++)
				inds[q] = (Individual)(inds[q].clone());
		return n;
        }
    }