001 package net.sf.cpsolver.ifs.heuristics; 002 003 import java.lang.reflect.Constructor; 004 import java.util.Enumeration; 005 006 import net.sf.cpsolver.ifs.model.Neighbour; 007 import net.sf.cpsolver.ifs.model.SimpleNeighbour; 008 import net.sf.cpsolver.ifs.model.Value; 009 import net.sf.cpsolver.ifs.model.Variable; 010 import net.sf.cpsolver.ifs.solution.Solution; 011 import net.sf.cpsolver.ifs.solver.Solver; 012 import net.sf.cpsolver.ifs.solver.SolverListener; 013 import net.sf.cpsolver.ifs.util.DataProperties; 014 015 /** 016 * Standard neighbour selection criterion. 017 * <br><br> 018 * This criterion is using the provided variable and value selection criteria. 019 * In each step, a variable is selected first using the {@link VariableSelection}. 020 * Then, a value is selected to the selected variable, using the {@link ValueSelection}. 021 * A {@link SimpleNeighbour} containing the selected value is returned. 022 * <br><br> 023 * Note: the use of neighbour select criteria extends the former implementation 024 * of the IFS algorithm which was only able to use variable and value selection criteria 025 * and therefore only one value was assigned in each iteration. 026 * <br><br> 027 * Parameters: 028 * <br> 029 * <table border='1'><tr><th>Parameter</th><th>Type</th><th>Comment</th></tr> 030 * <tr><td>Value.Class</td><td>{@link String}</td><td>Fully qualified class name of the value selection criterion (see {@link ValueSelection}, e.g. {@link GeneralValueSelection})</td></tr> 031 * <tr><td>Variable.Class</td><td>{@link String}</td><td>Fully qualified class name of the variable selection criterion (see {@link VariableSelection}, e.g. {@link GeneralVariableSelection})</td></tr> 032 * </table> 033 * @see Solver 034 * 035 * @version 036 * IFS 1.1 (Iterative Forward Search)<br> 037 * Copyright (C) 2006 Tomáš Müller<br> 038 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 039 * Lazenska 391, 76314 Zlin, Czech Republic<br> 040 * <br> 041 * This library is free software; you can redistribute it and/or 042 * modify it under the terms of the GNU Lesser General Public 043 * License as published by the Free Software Foundation; either 044 * version 2.1 of the License, or (at your option) any later version. 045 * <br><br> 046 * This library is distributed in the hope that it will be useful, 047 * but WITHOUT ANY WARRANTY; without even the implied warranty of 048 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 049 * Lesser General Public License for more details. 050 * <br><br> 051 * You should have received a copy of the GNU Lesser General Public 052 * License along with this library; if not, write to the Free Software 053 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 054 **/ 055 public class StandardNeighbourSelection implements NeighbourSelection { 056 protected static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger.getLogger(StandardNeighbourSelection.class); 057 058 private ValueSelection iValueSelection = null; 059 private VariableSelection iVariableSelection = null; 060 private Solver iSolver = null; 061 062 /** Sets value selection criterion */ 063 public void setValueSelection(ValueSelection valueSelection) { iValueSelection = valueSelection; } 064 /** Sets variable selection criterion */ 065 public void setVariableSelection(VariableSelection variableSelection) { iVariableSelection = variableSelection; } 066 067 /** Returns values selection criterion */ 068 public ValueSelection getValueSelection() { return iValueSelection; } 069 /** Returns variable selection criterion */ 070 public VariableSelection getVariableSelection() { return iVariableSelection; } 071 072 /** 073 * Constructor 074 * @param properties configuration 075 * @throws Exception 076 */ 077 public StandardNeighbourSelection(DataProperties properties) throws Exception { 078 String valueSelectionClassName = properties.getProperty("Value.Class","net.sf.cpsolver.ifs.heuristics.GeneralValueSelection"); 079 sLogger.info("Using "+valueSelectionClassName); 080 Class valueSelectionClass = Class.forName(valueSelectionClassName); 081 Constructor valueSelectionConstructor = valueSelectionClass.getConstructor(new Class[]{DataProperties.class}); 082 setValueSelection((ValueSelection)valueSelectionConstructor.newInstance(new Object[] {properties})); 083 084 String variableSelectionClassName = properties.getProperty("Variable.Class","net.sf.cpsolver.ifs.heuristics.GeneralVariableSelection"); 085 sLogger.info("Using "+variableSelectionClassName); 086 Class variableSelectionClass = Class.forName(variableSelectionClassName); 087 Constructor variableSelectionConstructor = variableSelectionClass.getConstructor(new Class[]{DataProperties.class}); 088 setVariableSelection((VariableSelection)variableSelectionConstructor.newInstance(new Object[] {properties})); 089 } 090 091 092 /** 093 * Initialization -- methods {@link net.sf.cpsolver.ifs.heuristics.VariableSelection#init(Solver)} and {@link net.sf.cpsolver.ifs.heuristics.ValueSelection#init(Solver)} are called. 094 */ 095 public void init(Solver solver) { 096 getValueSelection().init(solver); 097 getVariableSelection().init(solver); 098 iSolver = solver; 099 } 100 101 /** Use the provided variable selection criterion to select a variable */ 102 public Variable selectVariable(Solution solution) { 103 // Variable selection 104 Variable variable = getVariableSelection().selectVariable(solution); 105 for (Enumeration i=iSolver.getSolverListeners().elements();i.hasMoreElements();) 106 if (!((SolverListener)i.nextElement()).variableSelected(solution.getIteration(), variable)) return null; 107 if (variable == null) sLogger.debug("No variable selected."); 108 109 if (variable != null && !variable.hasValues()) { 110 sLogger.debug("Variable "+variable.getName()+" has no values."); 111 return null; 112 } 113 return variable; 114 } 115 116 /** Use the provided value selection criterion to select a value to the selected variable */ 117 public Value selectValue(Solution solution, Variable variable) { 118 // Value selection 119 Value value = getValueSelection().selectValue(solution, variable); 120 for (Enumeration i=iSolver.getSolverListeners().elements();i.hasMoreElements();) 121 if (!((SolverListener)i.nextElement()).valueSelected(solution.getIteration(), variable, value)) return null; 122 123 if (value == null) { 124 sLogger.debug("No value selected for variable "+variable+"."); 125 } 126 return value; 127 } 128 129 /** 130 * Select neighbour. A value is selected to the selected variable. 131 */ 132 public Neighbour selectNeighbour(Solution solution) { 133 Variable variable = selectVariable(solution); 134 if (variable==null) return null; 135 Value value = selectValue(solution, variable); 136 if (value==null) return null; 137 return new SimpleNeighbour(variable, value); 138 } 139 }