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    }