001    package net.sf.cpsolver.ifs.multi;
002    
003    import java.util.Enumeration;
004    import java.util.Vector;
005    
006    import net.sf.cpsolver.ifs.model.Value;
007    import net.sf.cpsolver.ifs.model.Variable;
008    import net.sf.cpsolver.ifs.model.VariableListener;
009    
010    /**
011     * A variable containing multiple "normal" variables.
012     *
013     * @version
014     * IFS 1.1 (Iterative Forward Search)<br>
015     * Copyright (C) 2006 Tomáš Müller<br>
016     * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
017     * Lazenska 391, 76314 Zlin, Czech Republic<br>
018     * <br>
019     * This library is free software; you can redistribute it and/or
020     * modify it under the terms of the GNU Lesser General Public
021     * License as published by the Free Software Foundation; either
022     * version 2.1 of the License, or (at your option) any later version.
023     * <br><br>
024     * This library is distributed in the hope that it will be useful,
025     * but WITHOUT ANY WARRANTY; without even the implied warranty of
026     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
027     * Lesser General Public License for more details.
028     * <br><br>
029     * You should have received a copy of the GNU Lesser General Public
030     * License along with this library; if not, write to the Free Software
031     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
032     *  
033     */
034    
035    public class MultiVariable extends Variable implements VariableListener {
036            private Vector iVariables;
037            public static boolean sCacheValues = false;
038            
039            /** Constructor
040             * @param variables list of "normal" variables
041             */
042            public MultiVariable(Vector variables) {
043                    super();
044                    iVariables = variables;
045                    setValues(null);
046            }
047            public MultiVariable() {
048                    this(new Vector());
049            }
050            
051            /** Add "normal" variable */
052            public void addVariable(Variable variable) { variables().add(variable); setValues(null); }
053            /** Remove "normal" variable */
054            public void removeVariable(Variable variable) { variables().remove(variable); setValues(null); }
055            /** List of "normal" variables */
056            public Vector variables() { return iVariables; }
057            /** Number of "normal" variables */
058            public int size() { return variables().size(); }
059            
060            private void computeValues(Vector ret, Value[] values, int idx) {
061                    if (idx==ret.size()) {
062                            ret.addElement(new MultiValue(this, (Value[])values.clone()));
063                            return;
064                    }
065                    Variable var = (Variable)variables().elementAt(idx);
066                    for (Enumeration e=var.values().elements();e.hasMoreElements();) {
067                            Value value = (Value)e.nextElement();
068                            boolean inConflict = false;
069                            for (int f=0;f<idx;f++) {
070                                    if (values[f]!=null && !values[f].isConsistent(value)) {
071                                            inConflict = true; break;
072                                    }
073                            }
074                            if (inConflict) continue;
075                            values[idx]=value;
076                            computeValues(ret, values, idx+1);
077                            values[idx]=null;
078                    }
079            }
080    
081            /** Variable domain -- Cartesian product of the domains of the "normal" variables */ 
082            public Vector computeValues() {
083                    Vector values = new Vector();
084                    computeValues(values, new Value[size()], 0);
085                    return values;
086            }
087            
088            public Vector values() {
089                    if (sCacheValues) {
090                            Vector ret = super.values();
091                            if (ret==null) {
092                                    ret = computeValues();
093                                    setValues(ret);
094                            }
095                            return ret;
096                    } else
097                            return computeValues();
098            }
099            
100            public void assign(long iteration, Value value) {
101                    MultiValue m = (MultiValue)value;
102                    for (int i=0;i<size();i++) {
103                            Variable var = (Variable)variables().elementAt(i);
104                            if (var.getAssignment()!=null) var.unassign(iteration);
105                    }
106                    for (int i=0;i<size();i++) {
107                            Variable var = (Variable)variables().elementAt(i);
108                            if (m.values()[i]!=null)
109                                    var.assign(iteration, m.values()[i]);
110                    }
111                    super.assign(iteration, m);
112            }
113            
114            public void unassign(long iteration) {
115                    for (Enumeration e=variables().elements();e.hasMoreElements();) {
116                            Variable var = (Variable)e.nextElement();
117                            if (var.getAssignment()!=null)
118                                    var.unassign(iteration);
119                    }
120                    super.unassign(iteration);
121            }
122            
123            public String getName() {
124                    StringBuffer sb = new StringBuffer("[");
125                    for (Enumeration e=variables().elements();e.hasMoreElements();) {
126                            Variable v = (Variable)e.nextElement();
127                            sb.append(v==null?"null":v.getName());
128                            if (e.hasMoreElements()) sb.append(",");
129                    }
130                    sb.append("]");
131                    return sb.toString();
132            }
133            
134            
135            public void variableAssigned(long iteration, Value value) {}
136            public void variableUnassigned(long iteration, Value value) {
137                    MultiValue mValue = (MultiValue)value.getExtra();
138                    if (mValue!=null && mValue.variable().getAssignment()!=null)
139                            mValue.variable().unassign(iteration);
140            }
141            public void valueRemoved(long iteration, Value value) {}
142    }