/*
* Copyright (c) 2006 Thomas Weise
*
* E-Mail : tweise@gmx.de
* Creation Date : 2006-04-10 15:46:38
* Original Filename: org.search.algorithms.dgpf.ga.selection.RoundRobinSelection.java
* Version : 2.0.4
* Last modification: 2006-06-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.algorithms.ga.selection;
import java.io.Serializable;
import org.dgpf.search.algorithms.ga.SelectionAlgorithm;
import org.dgpf.search.algorithms.ga.SortingAlgorithm;
import org.dgpf.search.api.Individual;
import org.dgpf.search.api.SearchState;
import org.dgpf.search.api.adaptation.DefaultSearchAdapter;
import org.sfc.math.stochastic.Randomizer;
/**
* This selection algorithm performs basically a round robin of other
* selection algorithms it's hosting.
*
*
* @author Thomas Weise
*/
public final class RoundRobinSelection extends SelectionAlgorithm
{
/**
* The serial version uid.
*/
private static final long serialVersionUID = 1;
/**
* The selection algorithms used internally.
*/
private static final SelectionAlgorithm[] CONFIG =
new SelectionAlgorithm[] { new TournamentSelection(7),
RankedSelection.DEFAULT_INSTANCE,
new OrderedSelection(5.0d) };
/**
* The default modulo.
*/
private static final int DEFAULT_MODULO =
((int)(Math.max(
((DefaultSearchAdapter.DEFAULT_UPDATE_THRESHOLD/
(3*CONFIG.length))), 10)));
/**
* The index of the selection algorithm currently used.
*/
private volatile int m_index ;
/**
* The modulo for changing the selection algorithm.
*/
private volatile int m_modulo ;
/**
* The selection algorithms to be used.
*/
private SelectionAlgorithm[] m_select ;
/**
* The base modulo.
*/
private final int m_base_modulo ;
/**
* The current selection algorithm.
*/
private volatile SelectionAlgorithm m_sa;
/**
* Create a new instance of the round robin selection.
*/
public RoundRobinSelection()
{
this(-1, null);
}
/**
* Create a new instance of the round robin selection.
* @param p_modulo The modulo to use for the round robin selection.
* @param p_selection The selection algorithms to alternate between.
*/
public RoundRobinSelection(final int p_modulo,
final SelectionAlgorithm[] p_selection)
{
super(null);
this.m_select = (((p_selection != null) && (p_selection.length > 0)) ?
p_selection : CONFIG);
this.m_modulo = ((p_modulo > 0) ? p_modulo : DEFAULT_MODULO);
this.m_base_modulo = this.m_modulo;
this.m_sa = p_selection[0];
}
/**
* This method will be called by the search engine whenever it feels like
* it is time to adapt the current search parameters to the current search
* state. If you override this method, you must also declare your class
* as instance of ICloneable
.
* @param p_state The current state of the search.
* @return true
if and only if the update level should be
* resetted, false
if everything should continue
* normal.
*/
@Override
protected final boolean adapt (final SearchState> p_state)
{
long l_i;
if(super.adapt(p_state)) return true;
l_i = p_state.get_update_level();
if( (l_i % this.m_modulo) == 0 )
{
this.m_index++;
if(this.m_index >= this.m_select.length)
{
this.m_modulo++;
this.m_index = 0;
}
this.m_sa = this.m_select[this.m_index];
}
return false;
}
/**
* This method will be called whenever the search parameters perform a
* reset, meaning that the search level is set back to 0.
*/
@Override
protected final void reset ()
{
super.reset();
this.m_modulo = this.m_base_modulo;
this.m_index = 0;
}
/**
* Select one individual out of the population for reproduction (crossover
* or mutation). The individuals in the array are ordered by the search's
* current comparator, with the fittest individual at index 0
* and the worst at index p_count-1
.
* @param p_random The randomizer to be used for the selection.
* @param p_individuals The population of individuals after being
* preprocessed.
* @param p_count The count of valid items inside the population
* array.
* @param The genotype of the individuals to select.
* @return An individual to reproduce.
*/
@Override
public final Individual
select(final Randomizer p_random,
final Individual[] p_individuals,
final int p_count)
{
return this.m_sa.select(p_random, p_individuals, p_count);
}
/**
* Returns unique, textual identifier of this genetic selection algorithm.
* @return The unique, textual identifier of this genetic selection
* algorithm.
*/
@Override
public final String toString ()
{
return super.toString() + '(' + this.m_sa.toString() + ')';
}
/**
* Obtain the sorting algorithm to be applied before selecting.
* @return The sorting algorithm to be applied before selecting.
*/
@Override
public final SortingAlgorithm get_sorting_algorithm()
{
return this.m_sa.get_sorting_algorithm();
}
/**
* Check whether this object equals another one. This method is internally
* invoked by equals()
.
* @param p_object The object to compare with.
* @return true
if and only if this object equals to the other
* one.
*/
@Override
protected final boolean is_equal (final Object p_object)
{
RoundRobinSelection l_r;
SelectionAlgorithm[] l_a, l_b;
int l_i;
if(p_object instanceof RoundRobinSelection)
{
l_r = ((RoundRobinSelection)p_object);
if( (l_r.m_index == this.m_index) &&
(l_r.m_modulo == this.m_modulo) &&
(l_r.m_base_modulo == this.m_base_modulo) )
{
l_a = this.m_select;
l_b = l_r.m_select;
l_i = l_a.length;
if(l_i == l_b.length)
{
for(--l_i; l_i >= 0; l_i--)
{
if(!(l_a[l_i].equals(l_b[l_i])))
{
return false;
}
}
return true;
}
}
}
return false;
}
}