001 package net.sf.cpsolver.ifs.heuristics;
002
003 import java.util.Vector;
004
005 import org.apache.log4j.Logger;
006
007 import net.sf.cpsolver.ifs.model.Neighbour;
008 import net.sf.cpsolver.ifs.solution.Solution;
009 import net.sf.cpsolver.ifs.solver.Solver;
010 import net.sf.cpsolver.ifs.util.DataProperties;
011
012 /**
013 * A round robin neighbour selection.
014 * Two or more {@link NeighbourSelection} needs to be registered within the selection.
015 * This selection criterion takes the registered neighbour selections one by one and
016 * performs {@link NeighbourSelection#init(Solver)} and then it is using
017 * {@link NeighbourSelection#selectNeighbour(Solution)} to select a neighbour.
018 * When null is returned by the underlaying selection, next registered neighbour selection
019 * is initialized and used for the following selection(s). If the last registered
020 * selection returns null, the selection is returned to the first registered
021 * neighbour selection (it is initialized before used again).
022 *
023 * <br><br>
024 *
025 * @version
026 * StudentSct 1.1 (Student Sectioning)<br>
027 * Copyright (C) 2007 Tomáš Müller<br>
028 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
029 * Lazenska 391, 76314 Zlin, Czech Republic<br>
030 * <br>
031 * This library is free software; you can redistribute it and/or
032 * modify it under the terms of the GNU Lesser General Public
033 * License as published by the Free Software Foundation; either
034 * version 2.1 of the License, or (at your option) any later version.
035 * <br><br>
036 * This library is distributed in the hope that it will be useful,
037 * but WITHOUT ANY WARRANTY; without even the implied warranty of
038 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
039 * Lesser General Public License for more details.
040 * <br><br>
041 * You should have received a copy of the GNU Lesser General Public
042 * License along with this library; if not, write to the Free Software
043 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
044 */
045
046 public class RoundRobinNeighbourSelection extends StandardNeighbourSelection {
047 private static Logger sLogger = Logger.getLogger(RoundRobinNeighbourSelection.class);
048 private int iSelectionIdx = -1;
049 private Vector iSelections = new Vector();
050 private Solver iSolver = null;
051
052 /**
053 * Constructor
054 * @param properties configuration
055 * @throws Exception
056 */
057 public RoundRobinNeighbourSelection(DataProperties properties) throws Exception {
058 super(properties);
059 }
060
061 /** Register a neighbour selection */
062 public void registerSelection(NeighbourSelection selection) {
063 iSelections.add(selection);
064 }
065
066 /** Initialization */
067 public void init(Solver solver) {
068 super.init(solver);
069 iSolver = solver;
070 }
071
072 /** Select neighbour. A first registered selections is initialized and used until it
073 * returns null, then the second registered selections is initialized and used and vice versa.
074 */
075 public Neighbour selectNeighbour(Solution solution) {
076 if (iSelectionIdx==-1) {
077 iSelectionIdx = 0;
078 ((NeighbourSelection)iSelections.elementAt(iSelectionIdx)).init(iSolver);
079 }
080 while (true) {
081 NeighbourSelection selection = (NeighbourSelection)iSelections.elementAt(iSelectionIdx);
082 Neighbour neighbour = selection.selectNeighbour(solution);
083 if (neighbour!=null) return neighbour;
084 changeSelection(solution);
085 }
086 }
087
088 /** Change selection */
089 public void changeSelection(Solution solution) {
090 iSelectionIdx = (1+iSelectionIdx) % iSelections.size();
091 sLogger.debug("Phase changed to "+(iSelectionIdx+1));
092 ((NeighbourSelection)iSelections.elementAt(iSelectionIdx)).init(iSolver);
093 }
094 }