001 package ifs.example.csp;
002
003 import ifs.util.*;
004 import ifs.model.*;
005 import java.util.*;
006
007 /**
008 * Random Binary CSP with kernels.
009 * <br><br>
010 * This class only implements the generation of Structured CSP problem.<br>
011 * In Structured CSP, variables are divided into several kernels (some variables may remain ouside kernels).
012 * Different constraints (in density and tightnes) are generated according to whether variables are from the same kernel or not.
013 * <br><br>
014 * Model parameters:
015 * <br>
016 * <table border='1'><tr><th>Parameter</th><th>Type</th><th>Comment</th></tr>
017 * <tr><td>CSP.NrVariables</td><td>{@link Integer}</td><td>Number of variables</td></tr>
018 * <tr><td>CSP.DomainSize</td><td>{@link Integer}</td><td>Number of values for each variable</td></tr>
019 * <tr><td>CSP.NrKernels</td><td>{@link Integer}</td><td>Number of kernels</td></tr>
020 * <tr><td>CSP.KernelSize</td><td>{@link Integer}</td><td>Number of variables in each kernel</td></tr>
021 * <tr><td>CSP.Tightness</td><td>{@link Double}</td><td>Tightness of constraints outside kernels</td></tr>
022 * <tr><td>CSP.KernelTightness</td><td>{@link Double}</td><td>Tightness of constraints inside a kernel</td></tr>
023 * <tr><td>CSP.Density</td><td>{@link Double}</td><td>Density of constraints outside kernels</td></tr>
024 * <tr><td>CSP.KernelDensity</td><td>{@link Double}</td><td>Density of constraints inside a kernel</td></tr>
025 * <tr><td>General.MPP</td><td>{@link String}</td><td>Minimal perturbation problem --> generate initial assignment</td></tr>
026 * </table>
027 * <br>
028 *
029 * @author <a href="mailto:muller@ktiml.mff.cuni.cz">Tomáš Müller</a>
030 * @version 1.0
031 */
032 public class StructuredCSPModel extends Model {
033 private static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger.getLogger(StructuredCSPModel.class);
034 private DataProperties iProperties = null;
035
036 /** Constructor */
037 public StructuredCSPModel(DataProperties properties, long seed) {
038 iProperties = properties;
039 generate(seed);
040 }
041
042 private void swap(Variable[][] allPairs, int first, int second) {
043 Variable[] a = allPairs[first];
044 allPairs[first]=allPairs[second];
045 allPairs[second]=a;
046 }
047
048 private void buildBinaryConstraintGraph(Vector variables, Vector constraints, Random rnd) {
049 int numberOfAllPairs = variables.size()*(variables.size()-1)/2;
050 Variable[][] allPairs = new Variable[numberOfAllPairs][];
051 int idx=0;
052 for (Enumeration i1=variables.elements();i1.hasMoreElements();) {
053 Variable v1 = (Variable)i1.nextElement();
054 for (Enumeration i2=variables.elements();i2.hasMoreElements();) {
055 Variable v2 = (Variable)i2.nextElement();
056 if (v1.getId()>=v2.getId()) continue;
057 allPairs[idx++]=new Variable[] {v1,v2};
058 }
059 }
060 idx = 0;
061 for (Enumeration i1=constraints.elements();i1.hasMoreElements();) {
062 CSPBinaryConstraint c = (CSPBinaryConstraint) i1.nextElement();
063 swap(allPairs, idx, idx+(int)(rnd.nextDouble()*(numberOfAllPairs-idx)));
064 idx++;
065 }
066 idx = 0;
067 for (Enumeration i1=constraints.elements();i1.hasMoreElements();) {
068 CSPBinaryConstraint c = (CSPBinaryConstraint) i1.nextElement();
069 c.addVariable(allPairs[idx][0]);
070 c.addVariable(allPairs[idx][1]);
071 idx++;
072 }
073 }
074
075 private void buildBinaryConstraintGraph2(Vector variables, int numberOfAllPairs, Vector constraints, Random rnd) {
076 Variable[][] allPairs = new Variable[numberOfAllPairs][];
077 int idx=0;
078 for (Enumeration i1=variables.elements();i1.hasMoreElements();) {
079 CSPVariable v1 = (CSPVariable)i1.nextElement();
080 for (Enumeration i2=variables.elements();i2.hasMoreElements();) {
081 CSPVariable v2 = (CSPVariable)i2.nextElement();
082 if (v1.getId()>=v2.getId()) continue;
083 if (v1.getKernelId()>=0 && v1.getKernelId()==v2.getKernelId()) continue;
084 allPairs[idx++]=new Variable[] {v1,v2};
085 }
086 }
087 idx = 0;
088 for (Enumeration i1=constraints.elements();i1.hasMoreElements();) {
089 CSPBinaryConstraint c = (CSPBinaryConstraint) i1.nextElement();
090 swap(allPairs, idx, idx+(int)(rnd.nextDouble()*(numberOfAllPairs-idx)));
091 idx++;
092 }
093 idx = 0;
094 for (Enumeration i1=constraints.elements();i1.hasMoreElements();) {
095 CSPBinaryConstraint c = (CSPBinaryConstraint) i1.nextElement();
096 c.addVariable(allPairs[idx][0]);
097 c.addVariable(allPairs[idx][1]);
098 idx++;
099 }
100 }
101
102 private void generate(long seed) {
103 int nrVariables = iProperties.getPropertyInt("CSP.NrVariables", 60);
104 int nrValues = iProperties.getPropertyInt("CSP.DomainSize", 15);
105 int nrKernels = iProperties.getPropertyInt("CSP.NrKernels", 2);
106 int nrKernelVariables = iProperties.getPropertyInt("CSP.KernelSize", 8);
107
108 int nrPairValues = nrValues*nrValues;
109 float tightnessPerc = iProperties.getPropertyFloat("CSP.Tightness", 0.01f);
110 float kernelTightnessPerc = iProperties.getPropertyFloat("CSP.KernelTightness", 0.097f);
111 int nrCompatiblePairs = (int)Math.round((1.0-tightnessPerc)*nrPairValues);
112 int kernelNrCompatiblePairs = (int)Math.round((1.0-kernelTightnessPerc)*nrPairValues);
113
114 int nrPairVariables = (nrVariables*(nrVariables-1))/2;
115 int nrPairKernelVariables = (nrKernelVariables*(nrKernelVariables-1))/2;
116 nrPairVariables -= nrKernels * nrPairKernelVariables;
117 float densityPerc = iProperties.getPropertyFloat("CSP.Density", 0.01f);
118 float densityKernelPerc = iProperties.getPropertyFloat("CSP.KernelDensity", 0.097f);
119 int density = (int)Math.round(densityPerc*nrPairVariables);
120 int kernelDensity = (int)Math.round(densityKernelPerc*nrPairKernelVariables);
121
122 Random rnd = new Random(seed);
123 Vector generalVariables = new Vector(nrVariables-(nrKernels*nrKernelVariables));
124 int varId = 1;
125 for (int i=0;i<nrVariables-(nrKernels*nrKernelVariables);i++) {
126 CSPVariable var = new CSPVariable(varId++,nrValues);
127 generalVariables.addElement(var);
128 addVariable(var);
129 }
130 sLogger.debug("Created "+generalVariables.size()+" general variables.");
131 Vector[] kernelVariables = new Vector[nrKernels];
132 for (int k=0;k<nrKernels;k++) {
133 kernelVariables[k]=new Vector(nrKernelVariables);
134 for (int i=0;i<nrKernelVariables;i++) {
135 CSPVariable var = new CSPVariable(varId++,nrValues,k);
136 kernelVariables[k].addElement(var);
137 addVariable(var);
138 }
139 if (k==0) sLogger.debug("Created "+kernelVariables[0].size()+" kernel variables (per kernel).");
140 }
141 sLogger.debug("Created "+variables().size()+" variables at total.");
142 int constId = 1;
143 Vector generalConstraints = new Vector(density);
144 for (int i=0;i<density;i++) {
145 CSPBinaryConstraint c = new CSPBinaryConstraint(constId++,nrCompatiblePairs);
146 generalConstraints.addElement(c);
147 addConstraint(c);
148 }
149 sLogger.debug("Created "+generalConstraints.size()+" general constraints (tightness="+tightnessPerc+").");
150 Vector[] kernelConstraints = new Vector[nrKernels];
151 for (int k=0;k<nrKernels;k++) {
152 kernelConstraints[k] = new Vector(kernelDensity);
153 for (int i=0;i<kernelDensity;i++) {
154 CSPBinaryConstraint c = new CSPBinaryConstraint(constId++,kernelNrCompatiblePairs);
155 kernelConstraints[k].addElement(c);
156 addConstraint(c);
157 }
158 if (k==0) sLogger.debug("Created "+kernelConstraints[0].size()+" kernel constraints (per kernel, tightness="+kernelTightnessPerc+").");
159 }
160 sLogger.debug("Created "+constraints().size()+" constraints at total.");
161
162 for (int k=0;k<nrKernels;k++) {
163 buildBinaryConstraintGraph(kernelVariables[k], kernelConstraints[k], rnd);
164 }
165 buildBinaryConstraintGraph2(variables(), nrPairVariables, generalConstraints, rnd);
166
167 for (Enumeration i=constraints().elements();i.hasMoreElements();) {
168 CSPBinaryConstraint constraint = (CSPBinaryConstraint)i.nextElement();
169 constraint.init(rnd);
170 }
171
172 if (iProperties.getPropertyBoolean("General.MPP",false)) {
173 for (Enumeration i=variables().elements();i.hasMoreElements();) {
174 CSPVariable variable = (CSPVariable)i.nextElement();
175 variable.generateInitialValue(rnd);
176 }
177 }
178 }
179
180 /** Return information table */
181 public Hashtable getInfo() {
182 Hashtable ret = super.getInfo();
183 ret.put("Solution value", String.valueOf(getTotalValue()));
184 return ret;
185 }
186 }