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 }