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