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 Tomáš Müller<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 = new AssignmentContext[CanHoldContext.sMaxSize]; 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 @Override 071 public C getContext(Assignment<V, T> assignment) { 072 if (iContextOverride != null) 073 return iContextOverride; 074 return AssignmentContextHelper.getContext(this, assignment); 075 } 076 077 @Override 078 public AssignmentContextReference<V, T, C> getAssignmentContextReference() { return iContextReference; } 079 080 @Override 081 public void setAssignmentContextReference(AssignmentContextReference<V, T, C> reference) { iContextReference = reference; } 082 083 @Override 084 public AssignmentContext[] getContext() { return iContext; } 085 086 /** 087 * Has context override 088 * @return true if all threads are using the same context 089 */ 090 public boolean hasContextOverride() { 091 return iContextOverride != null; 092 } 093}