
org.cpsolver.ifs.dbt.DbtPropagation Maven / Gradle / Ivy
package org.cpsolver.ifs.dbt;
import java.util.HashSet;
import java.util.Set;
import org.cpsolver.ifs.assignment.Assignment;
import org.cpsolver.ifs.extension.MacPropagation;
import org.cpsolver.ifs.model.Neighbour;
import org.cpsolver.ifs.model.Value;
import org.cpsolver.ifs.model.Variable;
import org.cpsolver.ifs.solution.Solution;
import org.cpsolver.ifs.solver.Solver;
import org.cpsolver.ifs.solver.SolverListener;
import org.cpsolver.ifs.util.DataProperties;
/**
* Maintenance of arc consistency in dynamic backtracking.
*
* The difference between {@link MacPropagation} and this DBT propagation is
* that all not-assigned values of an assigned variable are marked as nogood.
* Also, when a dead end is reached, unassignment or failure takes place.
*
* This IFS solver extension is to be used only in case of dynamic backtracking
* and it has no parameters.
*
*
* @author Tomas Muller
* @version IFS 1.3 (Iterative Forward Search)
* Copyright (C) 2006 - 2014 Tomas Muller
* [email protected]
* http://muller.unitime.org
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not see http://www.gnu.org/licenses.
* @param Variable
* @param Value
*
*/
public class DbtPropagation, T extends Value> extends MacPropagation implements SolverListener {
private static org.apache.logging.log4j.Logger sLogger = org.apache.logging.log4j.LogManager.getLogger(DbtPropagation.class);
/**
* Constructor. No parameter is taken from properties.
* @param solver current solver
* @param properties solver configuration
*/
public DbtPropagation(Solver solver, DataProperties properties) {
super(solver, properties);
solver.addSolverListener(this);
}
/**
* Propagation takes place every time a value is assigned to a variable.
*
*
* - Prints a warning if the value is nogood (should not never happen),
*
- sets all other values of the variable to nogood (explanation is the assigned value itself),
*
- runs propagation.
*
*
* @see MacPropagation#propagate(Assignment, Variable)
*/
@Override
public void afterAssigned(Assignment assignment, long iteration, T value) {
iIteration = iteration;
if (!isGood(assignment, value)) {
sLogger.warn(value.variable().getName() + " = " + value.getName() + " -- not good value assigned (noGood:" + noGood(assignment, value) + ")");
setGood(assignment, value);
}
Set noGood = new HashSet(1);
noGood.add(value);
for (T anotherValue : value.variable().values(assignment)) {
if (anotherValue.equals(value) || !isGood(assignment, anotherValue))
continue;
setNoGood(assignment, anotherValue, noGood);
}
propagate(assignment, value.variable());
}
/**
* Undo propagation when a value is unassigned.
*
*
* - Prints an error if the value is nogood (should not never happen),
*
- runs propagation undo.
*
*
* @see MacPropagation#undoPropagate(Assignment, Variable)
*/
@Override
public void afterUnassigned(Assignment assignment, long iteration, T value) {
iIteration = iteration;
if (!isGood(assignment, value)) {
sLogger.error(value.variable().getName() + " = " + value.getName()
+ " -- not good value unassigned (noGood:" + noGood(assignment, value) + ")");
}
undoPropagate(assignment, value.variable());
}
/**
* If no variable is selected (all variables are assinged), unassign the
* last assigned variable.
*
* Do not allow to select an assigned variable.
*
* If no variable is selected (because all variables are assigned, see
* {@link DbtVariableSelection}):
*
* - find the last assigned variable and
*
- unassign it (explanation is a union of assignments of all other
* variables).
*
*
* @see DbtVariableSelection#selectVariable(Solution)
*/
@Override
public boolean variableSelected(Assignment assignment, long iteration, V variable) {
if (variable == null) {
sLogger.debug("No variable selected -> backtrack.");
V lastVariable = null;
for (V var : assignment.assignedVariables()) {
if (lastVariable == null || assignment.getIteration(lastVariable) < assignment.getIteration(var)) {
lastVariable = var;
}
}
if (lastVariable == null) {
sLogger.error("No assignment -> fail");
getSolver().stopSolver();
return false;
}
sLogger.debug("Unassign:" + lastVariable.getName());
Set noGoods = new HashSet();
for (V var : assignment.assignedVariables()) {
if (!var.equals(lastVariable)) {
noGoods.add(assignment.getValue(var));
}
}
T value = assignment.getValue(lastVariable);
assignment.unassign(iteration, lastVariable);
setNoGood(assignment, value, noGoods);
return false;
}
if (assignment.getValue(variable) != null) {
sLogger.error("Assigned value selected -- not supported by DBT.");
return false;
}
return true;
}
/**
* If no value is selected (because of a dead end), make some unassignments.
*
* If no value is selected (e.g., because the selected variable has all
* values marked as nogood, see {@link DbtValueSelection}),
*
* - compute a union of explanations of all values,
*
* - if it is empty fail (inconsistency is found),
*
* - otherwise pick the last assigned variable from the computed union of
* explanation and unassign it
*
* (explanation for that is the computed union of explanations without the last assignment).
*
*
*
* @see DbtVariableSelection#selectVariable(Solution)
*/
@Override
public boolean valueSelected(Assignment assignment, long iteration, V variable, T value) {
if (variable != null && value == null) {
Set noGoods = new HashSet();
for (T val : variable.values(assignment)) {
if (noGood(assignment, val) != null) {
noGoods.addAll(noGood(assignment, val));
}
}
if (noGoods.isEmpty()) {
sLogger.debug("Fail");
getSolver().stopSolver();
return false;
}
V lastVariable = null;
for (T val : noGoods) {
V var = val.variable();
if (lastVariable == null || assignment.getIteration(lastVariable) < assignment.getIteration(var)) {
lastVariable = var;
}
}
T current = assignment.getValue(lastVariable);
noGoods.remove(current);
assignment.unassign(iteration, lastVariable);
setNoGood(assignment, current, noGoods);
}
return true;
}
@Override
public boolean neighbourSelected(Assignment assignment, long iteration, Neighbour neighbour) {
return true;
}
@Override
public void neighbourFailed(Assignment assignment, long iteration, Neighbour neighbour) {
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy