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 }