| OLD | NEW |
| 1 // Copyright 2011 Google Inc. All Rights Reserved. | 1 // Copyright 2011 Google Inc. All Rights Reserved. |
| 2 // Copyright 1996 John Maloney and Mario Wolczko | 2 // Copyright 1996 John Maloney and Mario Wolczko |
| 3 // | 3 // |
| 4 // This file is part of GNU Smalltalk. | 4 // This file is part of GNU Smalltalk. |
| 5 // | 5 // |
| 6 // GNU Smalltalk is free software; you can redistribute it and/or modify it | 6 // GNU Smalltalk is free software; you can redistribute it and/or modify it |
| 7 // under the terms of the GNU General Public License as published by the Free | 7 // under the terms of the GNU General Public License as published by the Free |
| 8 // Software Foundation; either version 2, or (at your option) any later version. | 8 // Software Foundation; either version 2, or (at your option) any later version. |
| 9 // | 9 // |
| 10 // GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT | 10 // GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 } | 39 } |
| 40 | 40 |
| 41 /// Benchmark class required to report results. | 41 /// Benchmark class required to report results. |
| 42 class DeltaBlue { | 42 class DeltaBlue { |
| 43 void run() { | 43 void run() { |
| 44 chainTest(100); | 44 chainTest(100); |
| 45 projectionTest(100); | 45 projectionTest(100); |
| 46 } | 46 } |
| 47 } | 47 } |
| 48 | 48 |
| 49 | |
| 50 /** | 49 /** |
| 51 * Strengths are used to measure the relative importance of constraints. | 50 * Strengths are used to measure the relative importance of constraints. |
| 52 * New strengths may be inserted in the strength hierarchy without | 51 * New strengths may be inserted in the strength hierarchy without |
| 53 * disrupting current constraints. Strengths cannot be created outside | 52 * disrupting current constraints. Strengths cannot be created outside |
| 54 * this class, so == can be used for value comparison. | 53 * this class, so == can be used for value comparison. |
| 55 */ | 54 */ |
| 56 class Strength { | 55 class Strength { |
| 57 | |
| 58 final int value; | 56 final int value; |
| 59 final String name; | 57 final String name; |
| 60 | 58 |
| 61 const Strength(this.value, this.name); | 59 const Strength(this.value, this.name); |
| 62 | 60 |
| 63 Strength nextWeaker() => | 61 Strength nextWeaker() => const <Strength>[ |
| 64 const <Strength>[STRONG_PREFERRED, PREFERRED, STRONG_DEFAULT, NORMAL, | 62 STRONG_PREFERRED, |
| 65 WEAK_DEFAULT, WEAKEST][value]; | 63 PREFERRED, |
| 64 STRONG_DEFAULT, |
| 65 NORMAL, |
| 66 WEAK_DEFAULT, |
| 67 WEAKEST |
| 68 ][value]; |
| 66 | 69 |
| 67 static bool stronger(Strength s1, Strength s2) { | 70 static bool stronger(Strength s1, Strength s2) { |
| 68 return s1.value < s2.value; | 71 return s1.value < s2.value; |
| 69 } | 72 } |
| 70 | 73 |
| 71 static bool weaker(Strength s1, Strength s2) { | 74 static bool weaker(Strength s1, Strength s2) { |
| 72 return s1.value > s2.value; | 75 return s1.value > s2.value; |
| 73 } | 76 } |
| 74 | 77 |
| 75 static Strength weakest(Strength s1, Strength s2) { | 78 static Strength weakest(Strength s1, Strength s2) { |
| 76 return weaker(s1, s2) ? s1 : s2; | 79 return weaker(s1, s2) ? s1 : s2; |
| 77 } | 80 } |
| 78 | 81 |
| 79 static Strength strongest(Strength s1, Strength s2) { | 82 static Strength strongest(Strength s1, Strength s2) { |
| 80 return stronger(s1, s2) ? s1 : s2; | 83 return stronger(s1, s2) ? s1 : s2; |
| 81 } | 84 } |
| 82 } | 85 } |
| 83 | 86 |
| 84 | |
| 85 // Compile time computed constants. | 87 // Compile time computed constants. |
| 86 const REQUIRED = const Strength(0, "required"); | 88 const REQUIRED = const Strength(0, "required"); |
| 87 const STRONG_PREFERRED = const Strength(1, "strongPreferred"); | 89 const STRONG_PREFERRED = const Strength(1, "strongPreferred"); |
| 88 const PREFERRED = const Strength(2, "preferred"); | 90 const PREFERRED = const Strength(2, "preferred"); |
| 89 const STRONG_DEFAULT = const Strength(3, "strongDefault"); | 91 const STRONG_DEFAULT = const Strength(3, "strongDefault"); |
| 90 const NORMAL = const Strength(4, "normal"); | 92 const NORMAL = const Strength(4, "normal"); |
| 91 const WEAK_DEFAULT = const Strength(5, "weakDefault"); | 93 const WEAK_DEFAULT = const Strength(5, "weakDefault"); |
| 92 const WEAKEST = const Strength(6, "weakest"); | 94 const WEAKEST = const Strength(6, "weakest"); |
| 93 | |
| 94 | 95 |
| 95 abstract class Constraint { | 96 abstract class Constraint { |
| 96 | |
| 97 final Strength strength; | 97 final Strength strength; |
| 98 | 98 |
| 99 const Constraint(this.strength); | 99 const Constraint(this.strength); |
| 100 | 100 |
| 101 bool isSatisfied(); | 101 bool isSatisfied(); |
| 102 void markUnsatisfied(); | 102 void markUnsatisfied(); |
| 103 void addToGraph(); | 103 void addToGraph(); |
| 104 void removeFromGraph(); | 104 void removeFromGraph(); |
| 105 void chooseMethod(int mark); | 105 void chooseMethod(int mark); |
| 106 void markInputs(int mark); | 106 void markInputs(int mark); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 * is one that depends on external state, such as the mouse, the | 150 * is one that depends on external state, such as the mouse, the |
| 151 * keybord, a clock, or some arbitraty piece of imperative code. | 151 * keybord, a clock, or some arbitraty piece of imperative code. |
| 152 */ | 152 */ |
| 153 bool isInput() => false; | 153 bool isInput() => false; |
| 154 } | 154 } |
| 155 | 155 |
| 156 /** | 156 /** |
| 157 * Abstract superclass for constraints having a single possible output variable. | 157 * Abstract superclass for constraints having a single possible output variable. |
| 158 */ | 158 */ |
| 159 abstract class UnaryConstraint extends Constraint { | 159 abstract class UnaryConstraint extends Constraint { |
| 160 | |
| 161 final Variable myOutput; | 160 final Variable myOutput; |
| 162 bool satisfied = false; | 161 bool satisfied = false; |
| 163 | 162 |
| 164 UnaryConstraint(this.myOutput, Strength strength) : super(strength) { | 163 UnaryConstraint(this.myOutput, Strength strength) : super(strength) { |
| 165 addConstraint(); | 164 addConstraint(); |
| 166 } | 165 } |
| 167 | 166 |
| 168 /// Adds this constraint to the constraint graph | 167 /// Adds this constraint to the constraint graph |
| 169 void addToGraph() { | 168 void addToGraph() { |
| 170 myOutput.addConstraint(this); | 169 myOutput.addConstraint(this); |
| 171 satisfied = false; | 170 satisfied = false; |
| 172 } | 171 } |
| 173 | 172 |
| 174 /// Decides if this constraint can be satisfied and records that decision. | 173 /// Decides if this constraint can be satisfied and records that decision. |
| 175 void chooseMethod(int mark) { | 174 void chooseMethod(int mark) { |
| 176 satisfied = (myOutput.mark != mark) | 175 satisfied = (myOutput.mark != mark) && |
| 177 && Strength.stronger(strength, myOutput.walkStrength); | 176 Strength.stronger(strength, myOutput.walkStrength); |
| 178 } | 177 } |
| 179 | 178 |
| 180 /// Returns true if this constraint is satisfied in the current solution. | 179 /// Returns true if this constraint is satisfied in the current solution. |
| 181 bool isSatisfied() => satisfied; | 180 bool isSatisfied() => satisfied; |
| 182 | 181 |
| 183 void markInputs(int mark) { | 182 void markInputs(int mark) { |
| 184 // has no inputs. | 183 // has no inputs. |
| 185 } | 184 } |
| 186 | 185 |
| 187 /// Returns the current output variable. | 186 /// Returns the current output variable. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 204 } | 203 } |
| 205 | 204 |
| 206 bool inputsKnown(int mark) => true; | 205 bool inputsKnown(int mark) => true; |
| 207 | 206 |
| 208 void removeFromGraph() { | 207 void removeFromGraph() { |
| 209 if (myOutput != null) myOutput.removeConstraint(this); | 208 if (myOutput != null) myOutput.removeConstraint(this); |
| 210 satisfied = false; | 209 satisfied = false; |
| 211 } | 210 } |
| 212 } | 211 } |
| 213 | 212 |
| 214 | |
| 215 /** | 213 /** |
| 216 * Variables that should, with some level of preference, stay the same. | 214 * Variables that should, with some level of preference, stay the same. |
| 217 * Planners may exploit the fact that instances, if satisfied, will not | 215 * Planners may exploit the fact that instances, if satisfied, will not |
| 218 * change their output during plan execution. This is called "stay | 216 * change their output during plan execution. This is called "stay |
| 219 * optimization". | 217 * optimization". |
| 220 */ | 218 */ |
| 221 class StayConstraint extends UnaryConstraint { | 219 class StayConstraint extends UnaryConstraint { |
| 222 | |
| 223 StayConstraint(Variable v, Strength str) : super(v, str); | 220 StayConstraint(Variable v, Strength str) : super(v, str); |
| 224 | 221 |
| 225 void execute() { | 222 void execute() { |
| 226 // Stay constraints do nothing. | 223 // Stay constraints do nothing. |
| 227 } | 224 } |
| 228 } | 225 } |
| 229 | 226 |
| 230 | |
| 231 /** | 227 /** |
| 232 * A unary input constraint used to mark a variable that the client | 228 * A unary input constraint used to mark a variable that the client |
| 233 * wishes to change. | 229 * wishes to change. |
| 234 */ | 230 */ |
| 235 class EditConstraint extends UnaryConstraint { | 231 class EditConstraint extends UnaryConstraint { |
| 236 | |
| 237 EditConstraint(Variable v, Strength str) : super(v, str); | 232 EditConstraint(Variable v, Strength str) : super(v, str); |
| 238 | 233 |
| 239 /// Edits indicate that a variable is to be changed by imperative code. | 234 /// Edits indicate that a variable is to be changed by imperative code. |
| 240 bool isInput() => true; | 235 bool isInput() => true; |
| 241 | 236 |
| 242 void execute() { | 237 void execute() { |
| 243 // Edit constraints do nothing. | 238 // Edit constraints do nothing. |
| 244 } | 239 } |
| 245 } | 240 } |
| 246 | 241 |
| 247 | |
| 248 // Directions. | 242 // Directions. |
| 249 const int NONE = 1; | 243 const int NONE = 1; |
| 250 const int FORWARD = 2; | 244 const int FORWARD = 2; |
| 251 const int BACKWARD = 0; | 245 const int BACKWARD = 0; |
| 252 | 246 |
| 253 | |
| 254 /** | 247 /** |
| 255 * Abstract superclass for constraints having two possible output | 248 * Abstract superclass for constraints having two possible output |
| 256 * variables. | 249 * variables. |
| 257 */ | 250 */ |
| 258 abstract class BinaryConstraint extends Constraint { | 251 abstract class BinaryConstraint extends Constraint { |
| 259 | |
| 260 Variable v1; | 252 Variable v1; |
| 261 Variable v2; | 253 Variable v2; |
| 262 int direction = NONE; | 254 int direction = NONE; |
| 263 | 255 |
| 264 BinaryConstraint(this.v1, this.v2, Strength strength) : super(strength) { | 256 BinaryConstraint(this.v1, this.v2, Strength strength) : super(strength) { |
| 265 addConstraint(); | 257 addConstraint(); |
| 266 } | 258 } |
| 267 | 259 |
| 268 /** | 260 /** |
| 269 * Decides if this constraint can be satisfied and which way it | 261 * Decides if this constraint can be satisfied and which way it |
| 270 * should flow based on the relative strength of the variables related, | 262 * should flow based on the relative strength of the variables related, |
| 271 * and record that decision. | 263 * and record that decision. |
| 272 */ | 264 */ |
| 273 void chooseMethod(int mark) { | 265 void chooseMethod(int mark) { |
| 274 if (v1.mark == mark) { | 266 if (v1.mark == mark) { |
| 275 direction = (v2.mark != mark && | 267 direction = |
| 276 Strength.stronger(strength, v2.walkStrength)) | 268 (v2.mark != mark && Strength.stronger(strength, v2.walkStrength)) |
| 277 ? FORWARD : NONE; | 269 ? FORWARD |
| 270 : NONE; |
| 278 } | 271 } |
| 279 if (v2.mark == mark) { | 272 if (v2.mark == mark) { |
| 280 direction = (v1.mark != mark && | 273 direction = |
| 281 Strength.stronger(strength, v1.walkStrength)) | 274 (v1.mark != mark && Strength.stronger(strength, v1.walkStrength)) |
| 282 ? BACKWARD : NONE; | 275 ? BACKWARD |
| 276 : NONE; |
| 283 } | 277 } |
| 284 if (Strength.weaker(v1.walkStrength, v2.walkStrength)) { | 278 if (Strength.weaker(v1.walkStrength, v2.walkStrength)) { |
| 285 direction = Strength.stronger(strength, v1.walkStrength) | 279 direction = |
| 286 ? BACKWARD : NONE; | 280 Strength.stronger(strength, v1.walkStrength) ? BACKWARD : NONE; |
| 287 } else { | 281 } else { |
| 288 direction = Strength.stronger(strength, v2.walkStrength) | 282 direction = |
| 289 ? FORWARD : BACKWARD; | 283 Strength.stronger(strength, v2.walkStrength) ? FORWARD : BACKWARD; |
| 290 } | 284 } |
| 291 } | 285 } |
| 292 | 286 |
| 293 /// Add this constraint to the constraint graph. | 287 /// Add this constraint to the constraint graph. |
| 294 void addToGraph() { | 288 void addToGraph() { |
| 295 v1.addConstraint(this); | 289 v1.addConstraint(this); |
| 296 v2.addConstraint(this); | 290 v2.addConstraint(this); |
| 297 direction = NONE; | 291 direction = NONE; |
| 298 } | 292 } |
| 299 | 293 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 return i.mark == mark || i.stay || i.determinedBy == null; | 327 return i.mark == mark || i.stay || i.determinedBy == null; |
| 334 } | 328 } |
| 335 | 329 |
| 336 void removeFromGraph() { | 330 void removeFromGraph() { |
| 337 if (v1 != null) v1.removeConstraint(this); | 331 if (v1 != null) v1.removeConstraint(this); |
| 338 if (v2 != null) v2.removeConstraint(this); | 332 if (v2 != null) v2.removeConstraint(this); |
| 339 direction = NONE; | 333 direction = NONE; |
| 340 } | 334 } |
| 341 } | 335 } |
| 342 | 336 |
| 343 | |
| 344 /** | 337 /** |
| 345 * Relates two variables by the linear scaling relationship: "v2 = | 338 * Relates two variables by the linear scaling relationship: "v2 = |
| 346 * (v1 * scale) + offset". Either v1 or v2 may be changed to maintain | 339 * (v1 * scale) + offset". Either v1 or v2 may be changed to maintain |
| 347 * this relationship but the scale factor and offset are considered | 340 * this relationship but the scale factor and offset are considered |
| 348 * read-only. | 341 * read-only. |
| 349 */ | 342 */ |
| 350 | 343 |
| 351 class ScaleConstraint extends BinaryConstraint { | 344 class ScaleConstraint extends BinaryConstraint { |
| 352 | |
| 353 final Variable scale; | 345 final Variable scale; |
| 354 final Variable offset; | 346 final Variable offset; |
| 355 | 347 |
| 356 ScaleConstraint(Variable src, this.scale, this.offset, | 348 ScaleConstraint( |
| 357 Variable dest, Strength strength) | 349 Variable src, this.scale, this.offset, Variable dest, Strength strength) |
| 358 : super(src, dest, strength); | 350 : super(src, dest, strength); |
| 359 | 351 |
| 360 /// Adds this constraint to the constraint graph. | 352 /// Adds this constraint to the constraint graph. |
| 361 void addToGraph() { | 353 void addToGraph() { |
| 362 super.addToGraph(); | 354 super.addToGraph(); |
| 363 scale.addConstraint(this); | 355 scale.addConstraint(this); |
| 364 offset.addConstraint(this); | 356 offset.addConstraint(this); |
| 365 } | 357 } |
| 366 | 358 |
| 367 void removeFromGraph() { | 359 void removeFromGraph() { |
| 368 super.removeFromGraph(); | 360 super.removeFromGraph(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 388 * Calculate the walkabout strength, the stay flag, and, if it is | 380 * Calculate the walkabout strength, the stay flag, and, if it is |
| 389 * 'stay', the value for the current output of this constraint. Assume | 381 * 'stay', the value for the current output of this constraint. Assume |
| 390 * this constraint is satisfied. | 382 * this constraint is satisfied. |
| 391 */ | 383 */ |
| 392 void recalculate() { | 384 void recalculate() { |
| 393 Variable ihn = input(), out = output(); | 385 Variable ihn = input(), out = output(); |
| 394 out.walkStrength = Strength.weakest(strength, ihn.walkStrength); | 386 out.walkStrength = Strength.weakest(strength, ihn.walkStrength); |
| 395 out.stay = ihn.stay && scale.stay && offset.stay; | 387 out.stay = ihn.stay && scale.stay && offset.stay; |
| 396 if (out.stay) execute(); | 388 if (out.stay) execute(); |
| 397 } | 389 } |
| 398 | |
| 399 } | 390 } |
| 400 | 391 |
| 401 | |
| 402 /** | 392 /** |
| 403 * Constrains two variables to have the same value. | 393 * Constrains two variables to have the same value. |
| 404 */ | 394 */ |
| 405 class EqualityConstraint extends BinaryConstraint { | 395 class EqualityConstraint extends BinaryConstraint { |
| 406 | |
| 407 EqualityConstraint(Variable v1, Variable v2, Strength strength) | 396 EqualityConstraint(Variable v1, Variable v2, Strength strength) |
| 408 : super(v1, v2, strength); | 397 : super(v1, v2, strength); |
| 409 | 398 |
| 410 /// Enforce this constraint. Assume that it is satisfied. | 399 /// Enforce this constraint. Assume that it is satisfied. |
| 411 void execute() { | 400 void execute() { |
| 412 output().value = input().value; | 401 output().value = input().value; |
| 413 } | 402 } |
| 414 } | 403 } |
| 415 | 404 |
| 416 | |
| 417 /** | 405 /** |
| 418 * A constrained variable. In addition to its value, it maintain the | 406 * A constrained variable. In addition to its value, it maintain the |
| 419 * structure of the constraint graph, the current dataflow graph, and | 407 * structure of the constraint graph, the current dataflow graph, and |
| 420 * various parameters of interest to the DeltaBlue incremental | 408 * various parameters of interest to the DeltaBlue incremental |
| 421 * constraint solver. | 409 * constraint solver. |
| 422 **/ | 410 **/ |
| 423 class Variable { | 411 class Variable { |
| 424 | |
| 425 List<Constraint> constraints = <Constraint>[]; | 412 List<Constraint> constraints = <Constraint>[]; |
| 426 Constraint determinedBy; | 413 Constraint determinedBy; |
| 427 int mark = 0; | 414 int mark = 0; |
| 428 Strength walkStrength = WEAKEST; | 415 Strength walkStrength = WEAKEST; |
| 429 bool stay = true; | 416 bool stay = true; |
| 430 int value; | 417 int value; |
| 431 final String name; | 418 final String name; |
| 432 | 419 |
| 433 Variable(this.name, this.value); | 420 Variable(this.name, this.value); |
| 434 | 421 |
| 435 /** | 422 /** |
| 436 * Add the given constraint to the set of all constraints that refer | 423 * Add the given constraint to the set of all constraints that refer |
| 437 * this variable. | 424 * this variable. |
| 438 */ | 425 */ |
| 439 void addConstraint(Constraint c) { | 426 void addConstraint(Constraint c) { |
| 440 constraints.add(c); | 427 constraints.add(c); |
| 441 } | 428 } |
| 442 | 429 |
| 443 /// Removes all traces of c from this variable. | 430 /// Removes all traces of c from this variable. |
| 444 void removeConstraint(Constraint c) { | 431 void removeConstraint(Constraint c) { |
| 445 constraints.remove(c); | 432 constraints.remove(c); |
| 446 if (determinedBy == c) determinedBy = null; | 433 if (determinedBy == c) determinedBy = null; |
| 447 } | 434 } |
| 448 } | 435 } |
| 449 | 436 |
| 450 | |
| 451 class Planner { | 437 class Planner { |
| 452 | |
| 453 int currentMark = 0; | 438 int currentMark = 0; |
| 454 | 439 |
| 455 /** | 440 /** |
| 456 * Attempt to satisfy the given constraint and, if successful, | 441 * Attempt to satisfy the given constraint and, if successful, |
| 457 * incrementally update the dataflow graph. Details: If satifying | 442 * incrementally update the dataflow graph. Details: If satifying |
| 458 * the constraint is successful, it may override a weaker constraint | 443 * the constraint is successful, it may override a weaker constraint |
| 459 * on its output. The algorithm attempts to resatisfy that | 444 * on its output. The algorithm attempts to resatisfy that |
| 460 * constraint using some other method. This process is repeated | 445 * constraint using some other method. This process is repeated |
| 461 * until either a) it reaches a variable that was not previously | 446 * until either a) it reaches a variable that was not previously |
| 462 * determined by any constraint or b) it reaches a constraint that | 447 * determined by any constraint or b) it reaches a constraint that |
| 463 * is too weak to be satisfied using any of its methods. The | 448 * is too weak to be satisfied using any of its methods. The |
| 464 * variables of constraints that have been processed are marked with | 449 * variables of constraints that have been processed are marked with |
| 465 * a unique mark value so that we know where we've been. This allows | 450 * a unique mark value so that we know where we've been. This allows |
| 466 * the algorithm to avoid getting into an infinite loop even if the | 451 * the algorithm to avoid getting into an infinite loop even if the |
| 467 * constraint graph has an inadvertent cycle. | 452 * constraint graph has an inadvertent cycle. |
| 468 */ | 453 */ |
| 469 void incrementalAdd(Constraint c) { | 454 void incrementalAdd(Constraint c) { |
| 470 int mark = newMark(); | 455 int mark = newMark(); |
| 471 for(Constraint overridden = c.satisfy(mark); | 456 for (Constraint overridden = c.satisfy(mark); |
| 472 overridden != null; | 457 overridden != null; |
| 473 overridden = overridden.satisfy(mark)); | 458 overridden = overridden.satisfy(mark)); |
| 474 } | 459 } |
| 475 | 460 |
| 476 /** | 461 /** |
| 477 * Entry point for retracting a constraint. Remove the given | 462 * Entry point for retracting a constraint. Remove the given |
| 478 * constraint and incrementally update the dataflow graph. | 463 * constraint and incrementally update the dataflow graph. |
| 479 * Details: Retracting the given constraint may allow some currently | 464 * Details: Retracting the given constraint may allow some currently |
| 480 * unsatisfiable downstream constraint to be satisfied. We therefore collect | 465 * unsatisfiable downstream constraint to be satisfied. We therefore collect |
| 481 * a list of unsatisfied downstream constraints and attempt to | 466 * a list of unsatisfied downstream constraints and attempt to |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 | 593 |
| 609 void addConstraintsConsumingTo(Variable v, List<Constraint> coll) { | 594 void addConstraintsConsumingTo(Variable v, List<Constraint> coll) { |
| 610 Constraint determining = v.determinedBy; | 595 Constraint determining = v.determinedBy; |
| 611 for (int i = 0; i < v.constraints.length; i++) { | 596 for (int i = 0; i < v.constraints.length; i++) { |
| 612 Constraint c = v.constraints[i]; | 597 Constraint c = v.constraints[i]; |
| 613 if (c != determining && c.isSatisfied()) coll.add(c); | 598 if (c != determining && c.isSatisfied()) coll.add(c); |
| 614 } | 599 } |
| 615 } | 600 } |
| 616 } | 601 } |
| 617 | 602 |
| 618 | |
| 619 /** | 603 /** |
| 620 * A Plan is an ordered list of constraints to be executed in sequence | 604 * A Plan is an ordered list of constraints to be executed in sequence |
| 621 * to resatisfy all currently satisfiable constraints in the face of | 605 * to resatisfy all currently satisfiable constraints in the face of |
| 622 * one or more changing inputs. | 606 * one or more changing inputs. |
| 623 */ | 607 */ |
| 624 class Plan { | 608 class Plan { |
| 625 List<Constraint> list = <Constraint>[]; | 609 List<Constraint> list = <Constraint>[]; |
| 626 | 610 |
| 627 void addConstraint(Constraint c) { | 611 void addConstraint(Constraint c) { |
| 628 list.add(c); | 612 list.add(c); |
| 629 } | 613 } |
| 630 | 614 |
| 631 int size() => list.length; | 615 int size() => list.length; |
| 632 | 616 |
| 633 void execute() { | 617 void execute() { |
| 634 for (int i = 0; i < list.length; i++) { | 618 for (int i = 0; i < list.length; i++) { |
| 635 list[i].execute(); | 619 list[i].execute(); |
| 636 } | 620 } |
| 637 } | 621 } |
| 638 } | 622 } |
| 639 | 623 |
| 640 | |
| 641 /** | 624 /** |
| 642 * This is the standard DeltaBlue benchmark. A long chain of equality | 625 * This is the standard DeltaBlue benchmark. A long chain of equality |
| 643 * constraints is constructed with a stay constraint on one end. An | 626 * constraints is constructed with a stay constraint on one end. An |
| 644 * edit constraint is then added to the opposite end and the time is | 627 * edit constraint is then added to the opposite end and the time is |
| 645 * measured for adding and removing this constraint, and extracting | 628 * measured for adding and removing this constraint, and extracting |
| 646 * and executing a constraint satisfaction plan. There are two cases. | 629 * and executing a constraint satisfaction plan. There are two cases. |
| 647 * In case 1, the added constraint is stronger than the stay | 630 * In case 1, the added constraint is stronger than the stay |
| 648 * constraint and values must propagate down the entire length of the | 631 * constraint and values must propagate down the entire length of the |
| 649 * chain. In case 2, the added constraint is weaker than the stay | 632 * chain. In case 2, the added constraint is weaker than the stay |
| 650 * constraint so it cannot be accomodated. The cost in this case is, | 633 * constraint so it cannot be accomodated. The cost in this case is, |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 713 EditConstraint edit = new EditConstraint(v, PREFERRED); | 696 EditConstraint edit = new EditConstraint(v, PREFERRED); |
| 714 Plan plan = planner.extractPlanFromConstraints(<EditConstraint>[edit]); | 697 Plan plan = planner.extractPlanFromConstraints(<EditConstraint>[edit]); |
| 715 for (int i = 0; i < 10; i++) { | 698 for (int i = 0; i < 10; i++) { |
| 716 v.value = newValue; | 699 v.value = newValue; |
| 717 plan.execute(); | 700 plan.execute(); |
| 718 } | 701 } |
| 719 edit.destroyConstraint(); | 702 edit.destroyConstraint(); |
| 720 } | 703 } |
| 721 | 704 |
| 722 Planner planner; | 705 Planner planner; |
| OLD | NEW |