001package org.cpsolver.ifs.assignment.context; 002 003import org.cpsolver.ifs.assignment.Assignment; 004import org.cpsolver.ifs.heuristics.NeighbourSelection; 005import org.cpsolver.ifs.model.Value; 006import org.cpsolver.ifs.model.Variable; 007import org.cpsolver.ifs.solver.Solver; 008 009/** 010 * A neighborhood selection with an assignment context. In order to be able to hold multiple assignments in memory 011 * it is desired for all the assignment dependent data a selection may need (to keep its current state), 012 * to store these data in a separate class (implementing the 013 * {@link AssignmentContext} interface). This context is created by calling 014 * {@link ConstraintWithContext#createAssignmentContext(Assignment)} and accessed by 015 * {@link ConstraintWithContext#getContext(Assignment)}. 016 * 017 * 018 * @see AssignmentContext 019 * 020 * @version IFS 1.3 (Iterative Forward Search)<br> 021 * Copyright (C) 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 <a href='http://www.gnu.org/licenses'>http://www.gnu.org/licenses</a>. 037 * @param <V> Variable 038 * @param <T> Value 039 * @param <C> Assignment Context 040 **/ 041public abstract class NeighbourSelectionWithContext<V extends Variable<V, T>, T extends Value<V, T>, C extends AssignmentContext> implements NeighbourSelection<V, T>, HasAssignmentContext<V, T, C>, CanHoldContext { 042 private AssignmentContextReference<V, T, C> iContextReference = null; 043 private AssignmentContext[] iContext = null; 044 protected C iContextOverride = null; 045 046 @Override 047 public void init(Solver<V, T> solver) { 048 iContextReference = solver.currentSolution().getModel().createReference(this); 049 if (isSingleContextSolver(solver)) 050 iContextOverride = createAssignmentContext(solver.currentSolution().getAssignment()); 051 } 052 053 /** 054 * Returns true if there should be only one context for this neighbourhood selection. 055 * @param solver current solver 056 * @return {@link Solver#hasSingleSolution()} 057 */ 058 protected boolean isSingleContextSolver(Solver<V, T> solver) { 059 return solver.hasSingleSolution(); 060 } 061 062 /** 063 * Returns an assignment context associated with this selection. If there is no 064 * assignment context associated with this selection yet, one is created using the 065 * {@link ConstraintWithContext#createAssignmentContext(Assignment)} method. From that time on, 066 * this context is kept with the assignment. 067 * @param assignment given assignment 068 * @return assignment context associated with this selection and the given assignment 069 */ 070 @SuppressWarnings("unchecked") 071 @Override 072 public C getContext(Assignment<V, T> assignment) { 073 if (iContextOverride != null) 074 return iContextOverride; 075 if (iContext != null && assignment.getIndex() >= 0 && assignment.getIndex() < iContext.length) { 076 AssignmentContext c = iContext[assignment.getIndex()]; 077 if (c != null) return (C)c; 078 } 079 return assignment.getAssignmentContext(getAssignmentContextReference()); 080 } 081 082 @Override 083 public AssignmentContextReference<V, T, C> getAssignmentContextReference() { return iContextReference; } 084 085 @Override 086 public void setAssignmentContextReference(AssignmentContextReference<V, T, C> reference) { iContextReference = reference; } 087 088 @Override 089 public AssignmentContext[] getContext() { return iContext; } 090 091 @Override 092 public void setContext(AssignmentContext[] context) { iContext = context; } 093 094}