    001package net.sf.cpsolver.ifs.constant;
    002
    003
    004import java.util.ArrayList;
    005import java.util.List;
    006
    007import net.sf.cpsolver.ifs.model.Model;
    008import net.sf.cpsolver.ifs.model.Value;
    009import net.sf.cpsolver.ifs.model.Variable;
    010
    011/**
    012 * Extension of the model with constant variables.
    013 *
    014 * Such variables are excluded from the solver process, however, they can be
    015 * included in constraints. Such model can allow us to build a solution on top
    016 * of another solution (e.g., committed classes in the course timetabling).
    017 *
    018 * Constant variable has to implement interface {@link ConstantVariable},
    019 * returning {@link ConstantVariable#isConstant()} true.
    020 *
    021 * @version IFS 1.2 (Iterative Forward Search)<br>
    022 *          Copyright (C) 2006 - 2010 Tomáš Müller<br>
    023 *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
    024 *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
    025 * <br>
    026 *          This library is free software; you can redistribute it and/or modify
    027 *          it under the terms of the GNU Lesser General Public License as
    028 *          published by the Free Software Foundation; either version 3 of the
    029 *          License, or (at your option) any later version. <br>
    030 * <br>
    031 *          This library is distributed in the hope that it will be useful, but
    032 *          WITHOUT ANY WARRANTY; without even the implied warranty of
    033 *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    034 *          Lesser General Public License for more details. <br>
    035 * <br>
    036 *          You should have received a copy of the GNU Lesser General Public
    037 *          License along with this library; if not see <http://www.gnu.org/licenses/>.
    038 *
    039 */
    040
    041public class ConstantModel<V extends Variable<V, T>, T extends Value<V, T>> extends Model<V, T> {
    042    private List<V> iConstantVariables = null;
    043
    044    /** List of constant variables */
    045    public List<V> constantVariables() {
    046        return iConstantVariables;
    047    }
    048
    049    /** True, if the model contains at least one constant variable. */
    050    public boolean hasConstantVariables() {
    051        return iConstantVariables != null && !iConstantVariables.isEmpty();
    052    }
    053
    054    /** True, if the given variable is constant. */
    055    public boolean isConstant(V variable) {
    056        return (iConstantVariables != null && variable instanceof ConstantVariable && ((ConstantVariable) variable)
    057                .isConstant());
    058    }
    059
    060    /** Adds a variable to the model */
    061    @Override
    062    public void addVariable(V variable) {
    063        if (variable instanceof ConstantVariable && ((ConstantVariable) variable).isConstant()) {
    064            if (iConstantVariables == null)
    065                iConstantVariables = new ArrayList<V>();
    066            variable.setModel(this);
    067            iConstantVariables.add(variable);
    068            if (variable.getAssignment() != null)
    069                variable.assign(0L, variable.getAssignment());
    070        } else
    071            super.addVariable(variable);
    072    }
    073
    074    /** Removes a variable from the model */
    075    @Override
    076    public void removeVariable(V variable) {
    077        if (isConstant(variable)) {
    078            variable.setModel(null);
    079            iConstantVariables.remove(variable);
    080        } else
    081            super.removeVariable(variable);
    082    }
    083
    084    /**
    085     * Called before a value is assigned to its variable. Constant variables are
    086     * excluded from (re)assignment.
    087     */
    088    @Override
    089    public void beforeAssigned(long iteration, T value) {
    090        if (!isConstant(value.variable()))
    091            super.beforeAssigned(iteration, value);
    092    }
    093
    094    /**
    095     * Called before a value is unassigned from its variable. Constant variables
    096     * are excluded from (re)assignment.
    097     */
    098    @Override
    099    public void beforeUnassigned(long iteration, T value) {
    100        if (!isConstant(value.variable()))
    101            super.beforeUnassigned(iteration, value);
    102    }
    103
    104    /**
    105     * Called after a value is assigned to its variable. Constant variables are
    106     * excluded from (re)assignment.
    107     */
    108    @Override
    109    public void afterAssigned(long iteration, T value) {
    110        if (!isConstant(value.variable()))
    111            super.afterAssigned(iteration, value);
    112    }
    113
    114    /**
    115     * Called after a value is unassigned from its variable. Constant variables
    116     * are excluded from (re)assignment.
    117     */
    118    @Override
    119    public void afterUnassigned(long iteration, T value) {
    120        if (!isConstant(value.variable()))
    121            super.afterUnassigned(iteration, value);
    122    }
    123}