Logo
Distributed Genetic Programming Framework
print print

File org.dgpf.search.api.SearchContext.java

Here you can find all the information about the file org.dgpf.search.api.SearchContext.java. You may explore it here or download it onto your local disk.
/*
 * Copyright (c) 2006 Thomas Weise
 * 
 * E-Mail           : tweise@gmx.de
 * Creation Date    : 2006-03-30 11:11:21
 * Original Filename: org.dgpf.search.api.SearchContext.java
 * Version          : 2.0.6
 * Last modification: 2006-08-03
 *                by: Thomas Weise
 * 
 * License          : GNU LESSER GENERAL PUBLIC LICENSE
 *                    Version 2.1, February 1999
 *                    You should have received a copy of this license along
 *                    with this library; if not, write to the Free Software
 *                    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *                    MA 02111-1307, USA or download the license under
 *                    http://www.gnu.org/copyleft/lesser.html.
 *                    
 * Warranty         : This software is provided "as is" without any
 *                    warranty; without even the implied warranty of
 *                    merchantability or fitness for a particular purpose.
 *                    See the Gnu Lesser General Public License for more
 *                    details.
 */

 
package org.dgpf.search.api;

import java.io.Serializable;

import org.sfc.collections.Arrays;
import org.sfc.events.ErrorEvent;
import org.sfc.events.IEventListener;
import org.sfc.math.stochastic.Randomizer;
import org.sfc.math.stochastic.statistics.StatisticInfoBag;
import org.sfc.math.stochastic.statistics.ValueExtractor;
import org.sfc.parallel.IAbortable;
import org.sfc.utils.MultiBuffer;
import org.sfc.utils.Typesafe;

/**
 * A <code>SearchContext</code> is the base class to hold the dynamic
 * information used by searching algorithms.
 * 
 * @param <Genotype>    The sort of genotype used to represent individuals.
 *                      This must be a serializable type.
 *
 * @author Thomas Weise
 */

public abstract class       SearchContext<Genotype extends Serializable>
                extends     SearchData3<Genotype>
                implements  IAbortable
  {
/**
 * The serial version uid.
 */

  private static final long serialVersionUID = 1;
  
/**
 * The internal fitness data value extractor.
 */

  private static  final ValueExtractor<FitnessData<?>[]> EXTR =
    new ValueExtractor<FitnessData<?>[]>()
    {
    @Override
    protected final double  get_value(final FitnessData<?>[] p_collection,
                                      final int              p_index)
      {
      return p_collection[p_index].get_fitness();
      }
    };
    
/**
 * An internal instance of <code>MultiBuffer</code> that might be used for
 * random purposes.
 * @see #get_buffer()
 */

  private final     MultiBuffer                   m_buffer  ;
  
/**
 * The randomizer used by this search context.
 * @see #get_randomizer()
 */

  private final     Randomizer                    m_random  ;
  
/**
 * The cache used internally to prevent equal genotypes from being created
 * twice. 
 */

  private final     SearchCache                     m_cache   ;
  
/**
 * The current individual.
 * @see #get_current()
 */

  private           Genotype                      m_current ;

/**
 * The internal fitness data record.
 */

  private           FitnessData<Genotype>[][]     m_data    ;
///**
// * The index of the current simulation.
// */

//  private           int                           m_simulation  ;
/**
 * The fitness static bags.
 */

  private final     StatisticInfoBag              m_fitnesses   ;
/**
 * The internal individual buffer.
 */

  private final     Individual<Genotype>          m_ind_buf     ;
/**
 * The internal running state of the context.
 */

  private volatile  boolean                       m_is_running ;
  
/**
 * The event propagator to be used to propagate error events, if needed.
 */

  private final     IEventListener               m_events     ;
  
  
/**
 * Create a new search context.
 * @param p_definition  The search definition to use as blueprint for the
 *                      internally stored data.
 * @param p_events      The event listener to be used to propagate
 *                      error events, if needed.
 */

  protected SearchContext (final SearchDefinition<Genotype> p_definition,
                           final IEventListener             p_events) 
    {
    super(p_definition);
        
    FitnessData<Genotype>[][]       l_d;
    int                             l_i, l_j, l_k;
    FitnessFunction<Genotype, ?>    l_ff;
//    StatisticInfoBag[]              l_fs;
    FitnessFunction<Genotype, ?>[]  l_fx;

    l_fx              = this.m_functions;
    l_i               = l_fx.length;
    l_j               = this.get_simulation_count();
    l_d               = Arrays.create(FitnessData[].class, l_i);
//    l_fs              = new StatisticInfoBag[l_i];
    this.m_ind_buf    = new Individual<Genotype>(l_i);

    for(--l_i; l_i >= 0; l_i--)
      {
      l_ff     = l_fx[l_i];
      l_d[l_i] = Arrays.create(FitnessData.class, l_j);

      for(l_k = (l_j-1); l_k >= 0; l_k--)
        {
        l_d[l_i][l_k] = l_ff.create_fitness_data();
        }

//      l_fs[l_i] = new StatisticInfoBag();
      }

    this.m_data       = l_d;
    this.m_fitnesses  = new StatisticInfoBag();    
    
    this.m_buffer     = new MultiBuffer();
    this.m_random     = new Randomizer();
    this.m_cache      = CacheManager.INSTANCE.get_cache(this.getClass(),
                                                        p_definition);  
    this.m_is_running = true;
    this.m_events     = p_events;
    }

/**
 * Obtain the instance of <code>MultiBuffer</code> used by this context.
 * A multi buffer is a useful tool if you need data buffers for a short-
 * term use.
 * @return The <code>MultiBuffer</code>-instance of this class.
 */

  public  final MultiBuffer     get_buffer  ()
    {
    return this.m_buffer;
    }
  
/**
 * Obtain the randomizer provided by this search context.
 * @return The randomizer provided by this search context.
 */

  public  final Randomizer      get_randomizer()
    {
    return this.m_random;
    }

/**
 * Obtain the individual currently being tested.
 * @return The individual currently being investiaged.
 * @see #begin_individual(Serializable)
 */

  public  final Genotype  get_current ()
    {
    return this.m_current;
    }

/**
 * <p>
 * Set the size of the internal cache preventing individuals from being
 * created twice. </p><p><i>Warning:</i> Since the cache is usually shared,
 * calling this method will also influence the performance of the other
 * contexts that use the same internal cache.</p>
 * @param p_size  The size of the internal cache that holds individuals
 *                already created.
 */

  @Override
  public synchronized  final void  set_cache_size  (final int p_size)
    {
    super.set_cache_size(p_size);
    if(this.m_cache != null) this.m_cache.set_size(this.get_cache_size());
    }
  
/**
 * Set the count of simulations to be performed for every individual
 * (genotype) to determine a stable fitness value.
 * @param p_simulation_count  How many simulations will be needed
 *                            per individual.
 */

  @Override
  public  synchronized /*final*/  void  set_simulation_count 
                                          (final int p_simulation_count)
    {
    FitnessData[][]                 l_d;
    FitnessData[]                   l_q;
    int                             l_i, l_z, l_j, l_k;
    FitnessFunction<Genotype, ?>    l_ff;
    FitnessFunction<Genotype, ?>[]  l_fx;
    
    super.set_simulation_count(p_simulation_count);
    
    l_d = this.m_data;
    if(l_d != null)
      {
      l_j   = this.get_simulation_count();      
      l_z   = l_d[0].length;
      l_fx  = this.m_functions;

      if(l_j > l_z)
        {
        for(l_i = (l_d.length-1); l_i >= 0; l_i--)
          {
          l_ff = l_fx[l_i];
          l_q  = new FitnessData[l_j];
  
          System.arraycopy(l_d[l_i], 0, l_q, 0, l_z);
          for(l_k = (l_j-1); l_k >= l_z; l_k--)
            {
            l_q[l_k] = l_ff.create_fitness_data();
            }
  
          l_d[l_i] = l_q;
          }
        }
      else
        {
        if(l_j < (l_z/3))
          {
          for(l_i = (l_d.length-1); l_i >= 0; l_i--)
            {
            l_q  = new FitnessData[l_j];
            System.arraycopy(l_d[l_i], 0, l_q, 0, l_j);
            l_d[l_i] = l_q;
            }
          }
        }
      }
    }
  
/**
 * Prepare the context for the given individual. This method is called
 * before any simulation concerning the given individual is done. It
 * provides the context the opportunity to prepare some information or
 * other data. This function also invokes the sanity checking of the
 * fitness functions.
 * @param p_individual  The individual to prepare for.
 * @return  <code>true</code> if everything is ok and we cal begin the
 *          simulations, <code>false/<code> if something is wrong and no
 *          simulations should be performed.
 * @see #get_current()
 * @see #end_individual()
 * @see FitnessFunction#should_simulate(Serializable)
 */

  protected boolean begin_individual(final Genotype p_individual)
    {
    int                             l_i;
    FitnessFunction<Genotype, ?>[]  l_ff;
    
    l_ff  = this.m_functions;

    for(l_i = (l_ff.length-1); l_i >= 0; l_i--)
      {
      if(!(l_ff[l_i].should_simulate(p_individual)))
        {
        return false;
        }
      }
    
    this.m_fitnesses.clear();
    
    return this.m_is_running;
    }
  

/**
 * Tells the context that the individual introduced with
 * <code>begin_individual</code> has now been tested enough and we're
 * finished with it. You can perform some cleanup now.
 * @see #begin_individual(Serializable)
 * @see #fill_in_fitness(Individual, int, int)
 */

  protected void    end_individual  ()
    {
    //
    }
  
  
/**
 * This method is called right before a simulation starts. It allows you
 * to perform some simulation-specific initialization.
 * The simulation-setup of the fitness functions will also be invoked here.
 * @param p_index   The index number of the current simulation. The first
 *                  simulation will have index 0, the second will have
 *                  index 1 and so on.
 * @see #end_simulation(int)
 * @see FitnessFunction#begin_simulation(FitnessData, SearchContext)
 */

  protected void begin_simulation  (final int p_index)
    {
    int                                               l_i;//, l_j;
    FitnessData<Genotype>[][]                         l_dd;
    FitnessData<Genotype>                             l_d;
    FitnessFunction<Genotype, FitnessData<Genotype>>  l_f;
    FitnessFunction<Genotype, ?>[]                    l_ff;

//    l_j               = this.m_simulation;
//    this.m_simulation = (l_j+1);
    l_dd              = this.m_data;
    l_ff              = this.m_functions;

    for(l_i = (l_dd.length-1); l_i >= 0; l_i--)
      {
      l_d = l_dd[l_i][p_index];
      l_d.begin_simulation(this);

      l_f = Typesafe.cast(l_ff[l_i]);
      l_f.begin_simulation(l_d, this);
      }
    }

/**
 * This method is called right when a simulation has finished.
 * It performs some simulation-based cleanup.
 * @param p_index   The index number of the current simulation. The first
 *                  simulation will have index 0, the second will have
 *                  index 1 and so on.
 * @see #begin_simulation(int)
 */

  protected void    end_simulation    (final int p_index)
    {
    int                                               l_i;//, l_j;
    FitnessData<Genotype>[][]                         l_dd;
    FitnessData<Genotype>                             l_d;
    FitnessFunction<Genotype, FitnessData<Genotype>>  l_f;
    FitnessFunction<Genotype, ?>[]                    l_ff;

//    l_j   = (this.m_simulation-1);
    l_dd  = this.m_data;
    l_ff  = this.m_functions;

    for(l_i = (l_dd.length-1); l_i >= 0; l_i--)
      {
      l_d = l_dd[l_i][p_index];

      l_f = Typesafe.cast(l_ff[l_i]);
      l_f.end_simulation(l_d, this);

      l_d.end_simulation(this);
      }
    }
  
/**
 * Perform some simulation steps. This method is used to simulate the
 * current individual.
 * @param p_steps       The count of stepps suggested to run now in a row.
 * @return  <code>true</code> if everything went ok, <code>false</code> if
 *          something failed.
 */

  protected boolean  simulate  (final long p_steps)
    {
    return true;
    }
  
/**
 * Format a double fitness values.
 * @param p_f   The value to be formatted.
 * @return  The formatted value.
 */

  private static  final double  format  (final double p_f)
    {
    long q;
    
    if(p_f <= 0.0d) return 0L;
    
    q = Math.round(p_f);
    if((q > 0) && (Math.abs(p_f - q) <= 1e-13))
      {
      return q;
      }
    
    return p_f;
    }
  
/**
 * Calculate and fill in the fitness values computed.
 * @param p_individual  The individual to store the fitness values into.
 * @param p_index       The index of the first simulation fitness record.
 * @param p_count       The count of simulations performed.
 */

  private final void fill_in_fitness(final Individual<Genotype> p_individual,
                                     final int                  p_index,
                                     final int                  p_count)
    {
    FitnessData[][]                 l_fd;
    FitnessData[]                   l_fd2;
    int                             l_i;//, l_k;
    StatisticInfoBag                l_b;
    FitnessFunction<Genotype, ?>[]  l_ff;

//    l_k               = this.m_simulation;
//    this.m_simulation = 0;

    p_individual.clear_fitness();
    if(p_count <= 0) return;
    
    l_fd              = this.m_data;
    l_b               = this.m_fitnesses;
    l_ff              = this.m_functions;

    for(l_i = (this.m_functions.length-1); l_i >= 0; l_i--)
      {
      l_fd2 = l_fd[l_i];
      Arrays.sort(l_fd2, p_index, p_count);
      l_b.clear();
      l_b.gather_info_sorted(l_fd2, EXTR, p_index, p_count);
      p_individual.set_fitness(l_i, format(l_ff[l_i].do_calculate_fitness(
                                           l_b.unpack())));      
      }  
    }
  
/**
 * Perform the complete evaluation of one individual.
 * @param p_individual  The individual to evaluate.
 */

  public final void  evaluate
                        (final Individual<Genotype>         p_individual)
    {
    final Genotype                                          l_id;
          int                                               l_sims, l_sc,
                                                            l_j;
          long                                              l_steps, l_q;
    final long                                              l_ms, l_s;
    final FitnessFunction<Genotype, ?>[]                    l_ff;
    final FitnessData<Genotype>[][]                         l_fd;
    final long[]                                            l_iv;
    final int                                               l_fs;
          FitnessFunction<Genotype, FitnessData<Genotype>>  l_f;

          
    if(p_individual != null)
      {
      try
        {
        p_individual.clear_fitness();
        l_id = p_individual.get_individual();      
        if(l_id != null)
          {
          this.m_current = l_id;
          l_sc           = this.get_simulation_count();
          l_sims         = (l_sc-1);
          if(this.begin_individual(l_id))
            {
            try
              {
              l_ms    = this.get_steps_per_simulation();
              l_ff    = this.m_functions;
              l_fd    = this.m_data;
              l_fs    = (l_ff.length-1);
              l_iv    = this.m_invoke;
      
              l_steps = this.m_gcd;
              if(l_steps < 0) l_s = l_ms;
              else            l_s = Math.max(1, l_steps);
      
              for(; (l_sims >= 0) && this.m_is_running; l_sims--)
                {
                try
                  {
                  this.begin_simulation(l_sims);
                  
                  l_steps = 0;               
                  while( (l_steps < l_ms) && this.m_is_running ) 
                    {
                    if(!(this.simulate(l_s))) break;
                    l_steps += l_s;
      
                    for(l_j = l_fs; l_j >= 0; l_j--)
                      {
                      l_q = l_iv[l_j];
                      if( (l_q > 0) && ((l_steps % l_q) == 0) )
                        {
                        l_f = Typesafe.cast(l_ff[l_j]);
                        l_f.inspect( l_fd[l_j][l_sims], this, l_steps) ;
                        }
                      }
                    }
      
                  }
                finally
                  {
                  this.end_simulation(l_sims);
                  }
                }
               
              }
            finally
              {
              this.end_individual();
              }            
            
            l_sims++;
            this.fill_in_fitness(p_individual, l_sims, l_sc-l_sims);
            }
          this.m_current = null;
          }
        }
      catch(Throwable l_t)
        {
        if(this.m_events != null)
          {
          this.m_events.receive(new ErrorEvent(this, l_t));
          }
        else
          {
          throw new RuntimeException(l_t);
          }
        }
      }
    }
  
/**
 * <p>
 * Create a new instance of the genotype. The new instance will be created
 * totally randomly, with all its contents based on the internal random
 * number generator.
 * </p><p>
 * The new instance will be completely evaluated and its fitness will be
 * determined and stored in the individual record.</p>
 * 
 * @param p_dest  The destination individual. You can use this parameter to
 *                pass in an instance of individual that should be used to
 *                store the individual data. If this instance is
 *                <code>null</code>, a new individual record will be
 *                created.
 * 
 * @return  The new, random instance of the genotype. <code>p_dest</code>
 *          will be used to store the individual and its fitness values
 *          if it was not <code>null</code>. If <code>p_dest</code> is
 *          <code>null</code>, a new individual record will automatically
 *          be created to hold the data. 
 */

  public synchronized final Individual<Genotype> 
                              create  (Individual<Genotype> p_dest)
    {
          int                   l_i;
    final IndividualComparator  l_ic;
    final boolean               l_rf;
    final Individual<Genotype>  l_b;
          boolean               l_f;
    
    if(p_dest == null)
      {
      p_dest = new Individual<Genotype>(this.m_functions.length); 
      }
    else p_dest.clear_fitness();
    
    l_i  = this.get_max_improvement_trials();
    l_ic = this.get_comparator();
    l_rf = this.get_return_first_improvement();    
    l_b  = this.m_ind_buf;
    l_f  = true;
    
    do
      {
      l_b.clear();
      l_b.set_individual(this.create2(true));
      this.evaluate(l_b);
      
      if(l_f || (l_ic.compare(l_b, p_dest) < 0))
        {
        l_f = false;
        p_dest.assign(l_b);
        if(l_rf && (!(l_ic.is_useless(p_dest))))
          {
          l_b.clear();
          return p_dest;
          }
        }
      
      } while ( ((--l_i) > 0) && this.m_is_running );
    
    
    l_b.clear();
//    p_dest.clear_fitness();
    return p_dest;
    }
  
/**
 * Internally create a new, random genotype.
 * @param p_allow_amb <code>true</code> if and only if ambiguous individual
 *                    creation is allowed, <code>false</code> otherwise.
 * @return  The new, random instance of the genotype. Or <code>null</code>,
 *          if no new instance could be created successfully.
 */

  private final Genotype  create2 (final boolean p_allow_amb)
    {
    int       l_i;
    Genotype  l_gt, l_gp;
    
    l_i  = this.get_max_creation_trials();
    l_gp = null;
    
    do
      {
      l_gt = this.do_create();
      if(l_gt != null)
        {
        l_gp = l_gt;
        l_gt = this.postprocess(l_gt);
        if(l_gt != null)
          {
          return l_gt;
          }
        }
      } while( ( (--l_i) > 0) && this.m_is_running );
    
    if(p_allow_amb)
      {
      return l_gp;
      }
    return null;
    }
  
/**
 * This method is used by <code>create()</code> to obtain new, random
 * instances of the genotype.
 * The new instance returned by this method should be created totally
 * randomly, with all its contents based on the internal random number
 * generator. No postprocessing must be done here, all will be performed
 * in the <code>create()</code>-routine. 
 * @return  The new, random instance of the genotype.
 */

  protected abstract  Genotype  do_create  ();
  
  
  

/**
 * <p>
 * Create a new instance of the genotype by mutating an existing one.
 * The new instance will be created basing on the one passed it. It will
 * not be equal to it though - small changes will randomly be performed.
 * </p><p>
 * The new instance will be completely evaluated and its fitness will be
 * determined and stored in the individual record.</p>
 * 
 * @param p_parent  The parent genotype which should be mutated a bit.
 * @param p_dest    The destination individual. You can use this parameter
 *                  to pass in an instance of individual that should be
 *                  used to store the individual data. If this instance is
 *                  <code>null</code>, a new individual record will be
 *                  created.
 *                
 * @return  The new, mutated instance of the genotype. 
 *          <code>p_dest</code> will be used to store the individual and
 *          its fitness values if it was not <code>null</code>. If
 *          <code>p_dest</code> is <code>null</code>, a new individual
 *          record will automatically be created to hold the data. 
 */

  public  synchronized final Individual<Genotype>  mutate 
                                  (final Individual<Genotype> p_parent,
                                         Individual<Genotype> p_dest)
    {
          int                   l_i;
    final IndividualComparator  l_ic;
    final boolean               l_rf;
    final Individual<Genotype>  l_b;
    final Genotype              l_g;
          boolean               l_f, l_pc;
    
    if(  (p_parent == null) ||
        ((l_g      =  p_parent.get_individual()) == null) )
      {
      return this.create(p_dest);
      }    
    
    if(p_dest == null)
      {
      p_dest = new Individual<Genotype>(this.m_functions.length); 
      }
    else p_dest.clear_fitness();
    
    l_i  = this.get_max_improvement_trials();
    l_ic = this.get_comparator();
    l_rf = this.get_return_first_improvement();    
    l_pc = this.get_challenge_parent();
    l_b  = this.m_ind_buf;
    l_f  = true;
        
    do
      {
      l_b.clear();
      l_b.set_individual(this.mutate2(l_g, null, true));      
      this.evaluate(l_b);
      
      if(l_f || (l_ic.compare(l_b, p_dest) < 0))
        {
        l_f = false;
        p_dest.assign(l_b);
        if(l_rf && (l_ic.compare(p_dest, p_parent) < 0))
          {
          l_b.clear();
          return p_dest;
          }
        }
      
      } while ( ((--l_i) > 0) && this.m_is_running ); 
        
    l_b.clear();
    
    if(l_pc && (l_ic.compare(l_b, p_parent) > 0))
      {
      p_dest.assign(p_parent);
      }
    
//    p_dest.clear_fitness();
    return p_dest;    
    }
  
/**
 * Create a new instance of the genotype by mutating an existing one.
 * The new instance will be created basing on the one passed it. It will
 * not be equal to it though - small changes will randomly be performed.
 * @param p_parent_1  The parent genotype which should be mutated a bit.
 * @param p_parent_2  An additional parent, if not <code>null</code>.
 * @param p_allow_amb <code>true</code> if and only if ambiguous individual
 *                    creation is allowed, <code>false</code> otherwise.
 * @return  The new, mutated instance of the genotype. Or <code>null</code>,
 *          if no new instance could be created successfully.
 */

  private final Genotype  mutate2 (final Genotype p_parent_1,
                                   final Genotype p_parent_2,
                                   final boolean  p_allow_amb)
    {
    int       l_i;
    Genotype  l_gt, l_gp;
    
    l_i  = this.get_max_creation_trials();
    l_gp = null;
    
    do
      {
      l_gt = this.do_mutate(p_parent_1);
      if(l_gt != null)
        {
        if(!(l_gt.equals(p_parent_1) ||
             ((p_parent_2 != null) && l_gt.equals(p_parent_2)) ))
          {                
          l_gp = l_gt;        
          l_gt = this.postprocess(l_gt);
          if(l_gt != null)
            {
            return l_gt;
            }
          }
        }
      } while( ( (--l_i) > 0)  && this.m_is_running );
        
    if(p_allow_amb)
      {
      l_gt = this.do_create();
      
      if(l_gt != null)
        {
        l_gt = this.postprocess(l_gt);
        if(l_gt != null)
          {
          return l_gt;
          }
        }
      
      if(l_gp != null)
        {
        return l_gp;
        }
      
      l_gt = this.create2(true);
      return ((l_gt != null) ? l_gt : p_parent_1);
      }
    
    return null;
    }
  
/**
 * This method is used by <code>mutate()</code> to create a new instance of
 * the genotype by mutating an existing one.
 * The new instance will be created basing on the one passed it. It will
 * not be equal to it though - small changes will randomly be performed.
 * No postprocessing must be done here, all will be performed in the
 * <code>mutate()</code>-routine.
 * 
 * @param p_parent  The parent genotype which should be mutated a bit.
 * @return  <p>
 *          The new, mutated instance of the genotype. Or <code>null</code>,
 *          if no new instance could be created successfully.</p><p>
 *          <i>Warning:</i> This method currently always returns
 *          <code>null</code>, you must override it in order to provide a
 *          proper mutation operator.</p>.
 */

  protected Genotype  do_mutate  (final Genotype p_parent)
    {
    return null;
    }
  

  
  
/**
 * <p>
 * Create a new individual by merging two other individuals. This method
 * instanciates the genotype by emulating the biological crossover
 * operation.</p><p>
 * The new instance will be completely evaluated and its fitness will be
 * determined and stored in the individual record.</p>
 * 
 * @param p_parent_1  The first parent individual.
 * @param p_parent_2  The second parent individual.
 * @param p_dest      The destination individual. You can use this
 *                    parameter to pass in an instance of individual that
 *                    should be used to store the individual data. If this
 *                    instance is <code>null</code>, a new individual
 *                    record will be created.
 * 
 * @return  The new genotype instance (individual) which is a combination
 *          of both parents. <code>p_dest</code> will be used to
 *          store the individual and its fitness values if it was not
 *          <code>null</code>. If <code>p_dest</code> is <code>null</code>,
 *          a new individual record will automatically be created to hold
 *          the data. 
 */

  public  synchronized final Individual<Genotype>  crossover
                        (final Individual<Genotype> p_parent_1,
                         final Individual<Genotype> p_parent_2,
                               Individual<Genotype> p_dest)
    {
    
          int                   l_i;
    final IndividualComparator  l_ic;
    final boolean               l_rf;
    final Individual<Genotype>  l_b, l_bp;
    final Genotype              l_g_1, l_g_2;
          boolean               l_f, l_pc;
    
    if(  (p_parent_1 == null)                                 ||
        ((l_g_1      =  p_parent_1.get_individual()) == null) )
      {
      return this.mutate(p_parent_2, p_dest);
      }
    
    if(  (p_parent_2 == null)                                 ||
        ((l_g_2      =  p_parent_2.get_individual()) == null))
      {
      return this.mutate(p_parent_1, p_dest);
      }    
    
    if(p_dest == null)
      {
      p_dest = new Individual<Genotype>(this.m_functions.length); 
      }
    else p_dest.clear_fitness();
    
    l_i  = this.get_max_improvement_trials();
    l_ic = this.get_comparator();
    l_rf = this.get_return_first_improvement();    
    l_pc = this.get_challenge_parent();
    l_b  = this.m_ind_buf;
    l_f  = true;    
    l_bp = ((l_ic.compare(p_parent_1, p_parent_2) < 0) ? p_parent_1
                                                       : p_parent_2);
        
    do
      {
      l_b.clear();
      l_b.set_individual(this.crossover2(l_g_1, l_g_2));
      this.evaluate(l_b);
      
      if(l_f || (l_ic.compare(l_b, p_dest) < 0))
        {
        l_f = false;
        p_dest.assign(l_b);
        if(l_rf && (l_ic.compare(p_dest, l_bp) < 0))
          {
          l_b.clear();
          return p_dest;
          }
        }
      
      } while ( ((--l_i) > 0) && this.m_is_running );
        
    l_b.clear();
    
    if(l_pc && (l_ic.compare(l_b, l_bp/*((l_bp == p_parent_1) ? p_parent_2
                                                        : p_parent_1)*/
) > 0))
      {
      p_dest.assign(l_bp);
      }
    
//    p_dest.clear_fitness();
    return p_dest;    
    }
  
/**
 * Create a new individual by merging two other individuals. This method
 * instanciates the genotype by emulating the biological crossover
 * operation.
 * 
 * @param p_parent_1    The first parent individual.
 * @param p_parent_2    The second parent individual.
 * 
 * @return  The new genotype instance (individual) which is a combination
 *          of both parents.
 */

  private final Genotype  crossover2 (final Genotype p_parent_1,
                                      final Genotype p_parent_2)
    {
    int       l_c;
    Genotype  l_gt, l_gp;
            
    l_c  = this.get_max_creation_trials();
    l_gp = null;
    
    do
      {
      l_gt = this.do_crossover(p_parent_1, p_parent_2);
      if(l_gt != null)
        {
        l_gp = l_gt;
        l_gt = this.postprocess(l_gt);
        if(l_gt != null)
          {
          return l_gt;
          }
        }
      } while ( ( (--l_c) >= 0 ) && this.m_is_running );
    
    l_gt = this.mutate2(p_parent_1, p_parent_2, false);
    if(l_gt != null) return l_gt;
    
    l_gt = this.mutate2(p_parent_2, p_parent_1, false);
    if(l_gt != null) return l_gt;
    
    l_gt = this.do_create();    
    if(l_gt != null)
      {
      l_gt = this.postprocess(l_gt);
      if(l_gt != null)
        {
        return l_gt;
        }
      }
      
    if(l_gp != null)
      {
      return l_gp;
      }
    
    l_gt = this.create2(true);
    return ((l_gt != null) ? l_gt :
            (this.m_random.nextBoolean() ? p_parent_1 : p_parent_2));
    }
  

/**
 * Create a new individual by merging two other individuals. This method
 * instanciates the genotype by emulating the biological crossover
 * operation.
 * No postprocessing must be done here, all will be performed in the
 * <code>crossover()</code>-routine.
 * 
 * @param p_parent_1    The first parent individual.
 * @param p_parent_2    The second parent individual.
 * 
 * @return  <p>The new genotype instance (individual) which is a
 *          combination of both parents, or <code>null</code>, if no new
 *          instance could be created successfully.</p><p>
 *          <i>Warning:</i> This method currently always returns
 *          <code>null</code>, you must override it in order to provide a
 *          proper crossover operator.</p>.
 */

  protected Genotype  do_crossover (final Genotype p_parent_1,
                                    final Genotype p_parent_2)
    {
    return null;
    }
  
  
  
/**
 * Postprocess a genotype newly created. Whenever the internal creation
 * routines create or derive a new instance of the genotype, it will not
 * be returned directly. Instead, it will be postprocessed first. The post-
 * production may return <code>null</code> if the individual passed in is
 * invalid or should not be investigated any further.
 * @param p_new The newly created or derived individual which now should be
 *              postprocessed.
 * @return  A postprocessed version of <code>p_new</code>, or
 *          <code>null</code>
 */

  protected Genotype  postprocess (final Genotype p_new)
    {
    if(this.m_cache.check(p_new)) return p_new;
    return null;
    }
  

/**
 * Abort this activity.
 * This method does not block.
 */

  public  final void  abort ()
    {
    this.m_is_running = false;
    CacheManager.INSTANCE.drop_cache(this.m_cache);
    }

/**
 * Tells the activity to stop its actions. This is the proper method to
 * allow the activity to terminate itself.
 * This method does block until the activity has finished.
 * @see #abort()
 */

  public  final void  abort_and_wait  ()
    {
    this.abort();
    }
  
/**
 * Finalize this search context.
 * @throws  Throwable If something goes wrong.
 */

  @Override
  protected void  finalize() throws Throwable
    {
    CacheManager.INSTANCE.drop_cache(this.m_cache);
    super.finalize();
    }

  }

File Information:

file name:SearchContext.java
package:org.dgpf.search.api
qualified name:org.dgpf.search.api.SearchContext.java
file type:Java Source File
download location:download http://dgpf.sourceforge.net/source/org/dgpf/search/api/SearchContext.java
size:33.678 KB (34487 B)
uploaded: 2015-07-22 04:11:00 GMT+0000
last update: 2006-08-22 15:22:42 GMT+0000
last access: 2017-11-18 06:38:53 GMT+0000

statistics online since 2006-01-02.   RSS Feed
Contact us by sending an email to tweise@gmx.de to receive further information, to report errors, or to join our project.
All content on this site (http://dgpf.sourceforge.net/) is LGPL-licensed.
http://dgpf.sourceforge.net/scripts/source/source.php last modified at 2015-07-22 04:10:53 GMT+0000 served at 2017-11-18 06:38:53 GMT+0000.
Valid CSS Valid XHTML 1.1
Valid RSS SourceForge.net Logo