001    package net.sf.cpsolver.ifs.constant;
002    
003    
004    import java.util.ArrayList;
005    import java.util.List;
006    
007    import net.sf.cpsolver.ifs.model.Model;
008    import net.sf.cpsolver.ifs.model.Value;
009    import 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 Tomas Muller<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    
041    public 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    }