001package net.sf.cpsolver.ifs.extension; 002 003import java.util.Collection; 004import java.util.Map; 005 006import net.sf.cpsolver.ifs.model.Model; 007import net.sf.cpsolver.ifs.model.Value; 008import net.sf.cpsolver.ifs.model.Variable; 009import net.sf.cpsolver.ifs.solution.Solution; 010import net.sf.cpsolver.ifs.solution.SolutionListener; 011import net.sf.cpsolver.ifs.solver.Solver; 012import net.sf.cpsolver.ifs.util.DataProperties; 013 014/** 015 * Go back to the best known solution when no better solution is found within 016 * the given amount of iterations. 017 * 018 * @version IFS 1.2 (Iterative Forward Search)<br> 019 * Copyright (C) 2006 - 2010 Tomáš Müller<br> 020 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 021 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 022 * <br> 023 * This library is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU Lesser General Public License as 025 * published by the Free Software Foundation; either version 3 of the 026 * License, or (at your option) any later version. <br> 027 * <br> 028 * This library is distributed in the hope that it will be useful, but 029 * WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 031 * Lesser General Public License for more details. <br> 032 * <br> 033 * You should have received a copy of the GNU Lesser General Public 034 * License along with this library; if not see 035 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 036 */ 037public class SearchIntensification<V extends Variable<V, T>, T extends Value<V, T>> extends Extension<V, T> implements 038 SolutionListener<V, T> { 039 private static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger.getLogger(SearchIntensification.class); 040 private long iInitialIterationLimit = 100; 041 private long iIterationLimit = 100; 042 private long iLastReturn = 0; 043 private ConflictStatistics<V, T> iCBS = null; 044 private int iResetInterval = 5; 045 private int iResetCounter = 0; 046 private int iMux = 2; 047 private int iMuxInterval = 2; 048 private int iMuxCounter = 0; 049 050 public SearchIntensification(Solver<V, T> solver, DataProperties properties) { 051 super(solver, properties); 052 iInitialIterationLimit = properties.getPropertyLong("SearchIntensification.IterationLimit", 053 iInitialIterationLimit); 054 iResetInterval = properties.getPropertyInt("SearchIntensification.ResetInterval", iResetInterval); 055 iMuxInterval = properties.getPropertyInt("SearchIntensification.MultiplyInterval", iMuxInterval); 056 iMux = properties.getPropertyInt("SearchIntensification.Multiply", iMux); 057 } 058 059 @Override 060 public boolean init(Solver<V, T> solver) { 061 if (iResetInterval > 0) { 062 for (Extension<V, T> ex : solver.getExtensions()) { 063 if (ConflictStatistics.class.isInstance(ex)) { 064 iCBS = (ConflictStatistics<V, T>) ex; 065 break; 066 } 067 } 068 } 069 return super.init(solver); 070 } 071 072 @Override 073 public void register(Model<V, T> model) { 074 super.register(model); 075 getSolver().currentSolution().addSolutionListener(this); 076 } 077 078 @Override 079 public void unregister(Model<V, T> model) { 080 super.unregister(model); 081 getSolver().currentSolution().removeSolutionListener(this); 082 } 083 084 @Override 085 public void afterAssigned(long iteration, T value) { 086 if (iIterationLimit > 0 && iteration > 0) { 087 Solution<V, T> solution = getSolver().currentSolution(); 088 if (solution.getBestIteration() < 0 || !solution.isBestComplete()) 089 return; 090 long bestIt = Math.max(solution.getBestIteration(), iLastReturn); 091 long currIt = solution.getIteration(); 092 if (currIt - bestIt > iIterationLimit) { 093 iLastReturn = currIt; 094 iResetCounter++; 095 iMuxCounter++; 096 sLogger.debug("Going back to the best known solution..."); 097 solution.restoreBest(); 098 sLogger.debug("Reset counter set to " + iResetCounter); 099 if (iMuxInterval > 0 && (iMuxCounter % iMuxInterval) == 0) { 100 iIterationLimit *= iMux; 101 sLogger.debug("Iteration limit increased to " + iIterationLimit); 102 } 103 if (iCBS != null && iResetInterval > 0 && (iResetCounter % iResetInterval) == 0) { 104 sLogger.debug("Reseting CBS..."); 105 iCBS.reset(); 106 } 107 } 108 } 109 } 110 111 @Override 112 public void bestSaved(Solution<V, T> solution) { 113 if (iResetCounter > 0) 114 sLogger.debug("Reset counter set to zero."); 115 iResetCounter = 0; 116 iMuxCounter = 0; 117 iIterationLimit = iInitialIterationLimit; 118 } 119 120 @Override 121 public void solutionUpdated(Solution<V, T> solution) { 122 } 123 124 @Override 125 public void bestCleared(Solution<V, T> solution) { 126 } 127 128 @Override 129 public void bestRestored(Solution<V, T> solution) { 130 } 131 132 @Override 133 public void getInfo(Solution<V, T> solution, Map<String, String> info) { 134 } 135 136 @Override 137 public void getInfo(Solution<V, T> solution, Map<String, String> info, Collection<V> variables) { 138 } 139}