ConstraintSolver 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. data/bin/ConstraintSolver +24 -0
  2. data/doc/classes/Array.html +209 -0
  3. data/doc/classes/ConstraintSolver.html +242 -0
  4. data/doc/classes/ConstraintSolver/AbstractConstraint.html +317 -0
  5. data/doc/classes/ConstraintSolver/AllDifferentConstraint.html +451 -0
  6. data/doc/classes/ConstraintSolver/AllDifferentConstraintTest.html +397 -0
  7. data/doc/classes/ConstraintSolver/BinaryConstraint.html +483 -0
  8. data/doc/classes/ConstraintSolver/BinaryConstraintTest.html +367 -0
  9. data/doc/classes/ConstraintSolver/BinaryRelation.html +276 -0
  10. data/doc/classes/ConstraintSolver/BinaryRelationTest.html +194 -0
  11. data/doc/classes/ConstraintSolver/ConstraintList.html +208 -0
  12. data/doc/classes/ConstraintSolver/ConstraintListTest.html +252 -0
  13. data/doc/classes/ConstraintSolver/ConstraintSolver.html +353 -0
  14. data/doc/classes/ConstraintSolver/ConstraintSolverTest.html +403 -0
  15. data/doc/classes/ConstraintSolver/Domain.html +522 -0
  16. data/doc/classes/ConstraintSolver/DomainTest.html +356 -0
  17. data/doc/classes/ConstraintSolver/DomainWipeoutException.html +158 -0
  18. data/doc/classes/ConstraintSolver/Problem.html +239 -0
  19. data/doc/classes/ConstraintSolver/ProblemTest.html +227 -0
  20. data/doc/classes/ConstraintSolver/Solution.html +342 -0
  21. data/doc/classes/ConstraintSolver/SolutionTest.html +250 -0
  22. data/doc/classes/ConstraintSolver/UndoStackEmptyException.html +158 -0
  23. data/doc/classes/ConstraintSolver/Variable.html +418 -0
  24. data/doc/classes/ConstraintSolver/VariableTest.html +284 -0
  25. data/doc/classes/ExtensionsTest.html +233 -0
  26. data/doc/classes/Fixnum.html +153 -0
  27. data/doc/created.rid +1 -0
  28. data/doc/dot/f_0.dot +38 -0
  29. data/doc/dot/f_0.png +0 -0
  30. data/doc/dot/f_1.dot +392 -0
  31. data/doc/dot/f_1.png +0 -0
  32. data/doc/dot/f_10.dot +392 -0
  33. data/doc/dot/f_10.png +0 -0
  34. data/doc/dot/f_11.dot +38 -0
  35. data/doc/dot/f_11.png +0 -0
  36. data/doc/dot/f_12.dot +392 -0
  37. data/doc/dot/f_12.png +0 -0
  38. data/doc/dot/f_13.dot +392 -0
  39. data/doc/dot/f_13.png +0 -0
  40. data/doc/dot/f_14.dot +392 -0
  41. data/doc/dot/f_14.png +0 -0
  42. data/doc/dot/f_15.dot +392 -0
  43. data/doc/dot/f_15.png +0 -0
  44. data/doc/dot/f_16.dot +392 -0
  45. data/doc/dot/f_16.png +0 -0
  46. data/doc/dot/f_17.dot +392 -0
  47. data/doc/dot/f_17.png +0 -0
  48. data/doc/dot/f_18.dot +392 -0
  49. data/doc/dot/f_18.png +0 -0
  50. data/doc/dot/f_19.dot +392 -0
  51. data/doc/dot/f_19.png +0 -0
  52. data/doc/dot/f_2.dot +392 -0
  53. data/doc/dot/f_2.png +0 -0
  54. data/doc/dot/f_3.dot +392 -0
  55. data/doc/dot/f_3.png +0 -0
  56. data/doc/dot/f_4.dot +392 -0
  57. data/doc/dot/f_4.png +0 -0
  58. data/doc/dot/f_5.dot +392 -0
  59. data/doc/dot/f_5.png +0 -0
  60. data/doc/dot/f_6.dot +14 -0
  61. data/doc/dot/f_6.png +0 -0
  62. data/doc/dot/f_7.dot +392 -0
  63. data/doc/dot/f_7.png +0 -0
  64. data/doc/dot/f_8.dot +392 -0
  65. data/doc/dot/f_8.png +0 -0
  66. data/doc/dot/f_9.dot +392 -0
  67. data/doc/dot/f_9.png +0 -0
  68. data/doc/dot/m_10_0.dot +392 -0
  69. data/doc/dot/m_10_0.png +0 -0
  70. data/doc/dot/m_12_0.dot +392 -0
  71. data/doc/dot/m_12_0.png +0 -0
  72. data/doc/dot/m_13_0.dot +392 -0
  73. data/doc/dot/m_13_0.png +0 -0
  74. data/doc/dot/m_14_0.dot +392 -0
  75. data/doc/dot/m_14_0.png +0 -0
  76. data/doc/dot/m_15_0.dot +392 -0
  77. data/doc/dot/m_15_0.png +0 -0
  78. data/doc/dot/m_16_0.dot +392 -0
  79. data/doc/dot/m_16_0.png +0 -0
  80. data/doc/dot/m_17_0.dot +392 -0
  81. data/doc/dot/m_17_0.png +0 -0
  82. data/doc/dot/m_18_0.dot +392 -0
  83. data/doc/dot/m_18_0.png +0 -0
  84. data/doc/dot/m_19_0.dot +392 -0
  85. data/doc/dot/m_19_0.png +0 -0
  86. data/doc/dot/m_1_0.dot +392 -0
  87. data/doc/dot/m_1_0.png +0 -0
  88. data/doc/dot/m_2_0.dot +392 -0
  89. data/doc/dot/m_2_0.png +0 -0
  90. data/doc/dot/m_3_0.dot +392 -0
  91. data/doc/dot/m_3_0.png +0 -0
  92. data/doc/dot/m_4_0.dot +392 -0
  93. data/doc/dot/m_4_0.png +0 -0
  94. data/doc/dot/m_5_0.dot +392 -0
  95. data/doc/dot/m_5_0.png +0 -0
  96. data/doc/dot/m_7_0.dot +392 -0
  97. data/doc/dot/m_7_0.png +0 -0
  98. data/doc/dot/m_8_0.dot +392 -0
  99. data/doc/dot/m_8_0.png +0 -0
  100. data/doc/dot/m_9_0.dot +392 -0
  101. data/doc/dot/m_9_0.png +0 -0
  102. data/doc/files/lib/AbstractConstraint_rb.html +148 -0
  103. data/doc/files/lib/AllDifferentConstraint_rb.html +156 -0
  104. data/doc/files/lib/BinaryConstraint_rb.html +155 -0
  105. data/doc/files/lib/ConstraintList_rb.html +148 -0
  106. data/doc/files/lib/ConstraintSolver_rb.html +162 -0
  107. data/doc/files/lib/Domain_rb.html +155 -0
  108. data/doc/files/lib/Problem_rb.html +148 -0
  109. data/doc/files/lib/Solution_rb.html +148 -0
  110. data/doc/files/lib/Variable_rb.html +148 -0
  111. data/doc/files/lib/extensions_rb.html +108 -0
  112. data/doc/files/test/AllDifferentConstraintTest_rb.html +158 -0
  113. data/doc/files/test/BinaryConstraintTest_rb.html +158 -0
  114. data/doc/files/test/ConstraintListTest_rb.html +160 -0
  115. data/doc/files/test/ConstraintSolverTest_rb.html +164 -0
  116. data/doc/files/test/DomainTest_rb.html +156 -0
  117. data/doc/files/test/ProblemTest_rb.html +160 -0
  118. data/doc/files/test/SolutionTest_rb.html +159 -0
  119. data/doc/files/test/TestSuite_rb.html +113 -0
  120. data/doc/files/test/VariableTest_rb.html +157 -0
  121. data/doc/files/test/extensionsTest_rb.html +118 -0
  122. data/doc/fr_class_index.html +51 -0
  123. data/doc/fr_file_index.html +46 -0
  124. data/doc/fr_method_index.html +133 -0
  125. data/doc/index.html +24 -0
  126. data/examples/example.rb +7 -0
  127. data/examples/queens.rb +13 -0
  128. data/examples/soft.rb +14 -0
  129. data/lib/AbstractConstraint.rb +45 -0
  130. data/lib/AllDifferentConstraint.rb +160 -0
  131. data/lib/BinaryConstraint.rb +187 -0
  132. data/lib/ConstraintList.rb +31 -0
  133. data/lib/ConstraintSolver.rb +213 -0
  134. data/lib/Domain.rb +100 -0
  135. data/lib/GraphUtils.rb +293 -0
  136. data/lib/OneOfEqualsConstraint.rb +81 -0
  137. data/lib/Problem.rb +30 -0
  138. data/lib/Solution.rb +56 -0
  139. data/lib/TupleConstraint.rb +111 -0
  140. data/lib/Variable.rb +74 -0
  141. data/lib/extensions.rb +55 -0
  142. data/test/AllDifferentConstraintTest.rb +140 -0
  143. data/test/BinaryConstraintTest.rb +108 -0
  144. data/test/ConstraintListTest.rb +41 -0
  145. data/test/ConstraintSolverTest.rb +274 -0
  146. data/test/DomainTest.rb +83 -0
  147. data/test/GraphUtilsTest.rb +83 -0
  148. data/test/OneOfEqualsConstraintTest.rb +82 -0
  149. data/test/ProblemTest.rb +35 -0
  150. data/test/SolutionTest.rb +35 -0
  151. data/test/TestSuite.rb +10 -0
  152. data/test/TupleConstraintTest.rb +151 -0
  153. data/test/VariableTest.rb +47 -0
  154. data/test/extensionsTest.rb +57 -0
  155. metadata +212 -0
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
4
+
5
+ require 'test/unit'
6
+ require 'GraphUtils'
7
+ require 'set'
8
+
9
+ module GraphUtils
10
+ class BipartiteGraphTest < Test::Unit::TestCase
11
+ def testConstructor
12
+ assert_raise(ArgumentError) { BipartiteGraph.new }
13
+ assert_raise(ArgumentError) { BipartiteGraph.new(nil, nil, nil) }
14
+ assert_raise(ArgumentError) { BipartiteGraph.new(Set.new, Set.new, Hash.new) }
15
+ assert_nothing_raised { BipartiteGraph.new(["a"].to_set, [1].to_set, { "a" => [1] }) }
16
+ end
17
+
18
+ def testMaximumMatchingCovering
19
+ graph = BipartiteGraph.new(["x","y","z"].to_set, [1,2,3].to_set,
20
+ { "x" => [1,3].to_set, "y" => [2,3].to_set, "z" => [2].to_set })
21
+ matching = graph.maximum_matching
22
+ assert_equal(3, matching.size)
23
+ assert_equal(1, matching["x"])
24
+ assert_equal(3, matching["y"])
25
+ assert_equal(2, matching["z"])
26
+ end
27
+
28
+ def testMaximumMatchingNotCovering
29
+ graph = BipartiteGraph.new(["x","y","z"].to_set, [1,2].to_set,
30
+ { "x" => [1,2].to_set, "y" => [1,2].to_set, "z" => [1,2].to_set })
31
+ matching = graph.maximum_matching
32
+ assert_equal(2, matching.size)
33
+ end
34
+
35
+ def testMaximumMatchingRecalc
36
+ graph = BipartiteGraph.new(["x","y","z"].to_set, [1,2,3,4].to_set,
37
+ { "x" => [1,2,3].to_set, "y" => [2,3,4].to_set, "z" => [2,3].to_set })
38
+ matching = graph.maximum_matching
39
+ assert_equal(true, matching.eql?(graph.maximum_matching))
40
+ graph.e["x"] = [2,3].to_set
41
+ matching = graph.maximum_matching
42
+ assert_equal(3, matching.size)
43
+ assert_equal(2, matching["x"])
44
+ assert_equal(4, matching["y"])
45
+ assert_equal(3, matching["z"])
46
+ end
47
+
48
+ def testRemovableValues
49
+ graph = BipartiteGraph.new(["x","y","z"].to_set, [1,2,3].to_set,
50
+ { "x" => [1,3].to_set, "y" => [2,3].to_set, "z" => [2].to_set })
51
+ matching = graph.maximum_matching
52
+ assert_equal({ "x" => [ 3 ].to_set, "y" => [ 2 ].to_set },
53
+ graph.removable_values(matching))
54
+ end
55
+ end
56
+
57
+ class GraphUtilsTest < Test::Unit::TestCase
58
+ def testStronglyConnectedComponents
59
+ assert_equal([],
60
+ GraphUtils::strongly_connected_components([ 1, 2 ], [ DirectedEdge.new(1, 2) ]))
61
+
62
+ graph = [ DirectedEdge.new(1, 2), DirectedEdge.new(1, 3),
63
+ DirectedEdge.new(2, 1), DirectedEdge.new(3, 2),
64
+ DirectedEdge.new(3, 4), DirectedEdge.new(4, 5),
65
+ DirectedEdge.new(5, 4) ]
66
+ assert_equal([[ 4, 5 ], [ 1, 2, 3 ]],
67
+ GraphUtils::strongly_connected_components([ 1, 2, 3, 4, 5 ], graph))
68
+
69
+ assert_equal([["y", 2, "z", 3]],
70
+ GraphUtils::strongly_connected_components([ "x", "y", "z", 1, 2, 3 ],
71
+ [ DirectedEdge.new("x", 1), DirectedEdge.new(3, "x"),
72
+ DirectedEdge.new("y", 2), DirectedEdge.new(3, "y"),
73
+ DirectedEdge.new("z", 3), DirectedEdge.new(2, "z") ]))
74
+ end
75
+
76
+ def testFindPaths
77
+ graph = [ DirectedEdge.new(1, 2), DirectedEdge.new(2, 3),
78
+ DirectedEdge.new(3, 2), DirectedEdge.new(4, 3) ]
79
+ assert_equal(graph[0..2].to_set, GraphUtils::find_paths(1, graph).to_set)
80
+ assert_equal(graph[1..3].to_set, GraphUtils::find_paths(4, graph).to_set)
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
4
+
5
+ require 'test/unit'
6
+ require 'OneOfEqualsConstraint'
7
+ require 'Variable'
8
+ require 'Domain'
9
+
10
+ module ConstraintSolver
11
+ class OneOfEqualsConstraintTest < Test::Unit::TestCase
12
+ def setup
13
+ @x = Variable.new("x", Domain.new([ 1, 2 ].to_set))
14
+ @y = Variable.new("y", Domain.new([ 1, 2 ].to_set))
15
+ @constraint = OneOfEqualsConstraint.new([ @x, @y ], 2)
16
+ end
17
+
18
+ def testConstructor
19
+ assert_raise(ArgumentError) { OneOfEqualsConstraint.new }
20
+ assert_raise(ArgumentError) { OneOfEqualsConstraint.new([], 1) }
21
+ assert_nothing_raised { OneOfEqualsConstraint.new([ @x, @y ], 2) }
22
+ assert_nothing_raised { OneOfEqualsConstraint.new([ @x, @y ], 2, 0) }
23
+ end
24
+
25
+ def testAssigned
26
+ assert_equal(false, @constraint.allAssigned?)
27
+ @x.value = 1
28
+ assert_equal(false, @constraint.allAssigned?)
29
+ @y.value = 1
30
+ assert_equal(true, @constraint.allAssigned?)
31
+ @x.reset
32
+ @y.reset
33
+ end
34
+
35
+ def testInclude
36
+ assert_equal(true, @constraint.include?(@x))
37
+ assert_equal(true, @constraint.include?(@y))
38
+ assert_equal(false, @constraint.include?(Variable.new("2", [ 3 ].to_set)))
39
+ end
40
+
41
+ def testHolds
42
+ assert_equal(true, @constraint.holds?)
43
+ @x.value = 1
44
+ @y.value = 1
45
+ assert_equal(false, @constraint.holds?)
46
+ @x.value = 2
47
+ @y.value = 2
48
+ assert_equal(true, @constraint.holds?)
49
+ @x.value = 1
50
+ @y.value = 2
51
+ assert_equal(true, @constraint.holds?)
52
+ @x.value = 2
53
+ @y.value = 1
54
+ assert_equal(true, @constraint.holds?)
55
+ end
56
+
57
+ def testEquals
58
+ assert_equal(OneOfEqualsConstraint.new([ @x, @y ], 2), @constraint)
59
+ assert_not_equal(OneOfEqualsConstraint.new([ Variable.new("z", Domain.new([ 1, 2 ].to_set)), @y ], 2), @constraint)
60
+ assert_not_equal(OneOfEqualsConstraint.new([ @x, @y ], 1), @constraint)
61
+ end
62
+
63
+ def testRevise
64
+ assert_equal([ [], 0, false ], @constraint.revise)
65
+ @y.value = 2
66
+ assert_equal([ [], 0, false ], @constraint.revise)
67
+ @y.value = 1
68
+ assert_equal([ [ @x ], 0, false ], @constraint.revise)
69
+ assert_equal([ 2 ].to_set, @x.domain.values)
70
+ @y.reset
71
+ @x.domain.undoPruning
72
+ end
73
+
74
+ def testFaulty
75
+ x = Variable.new("x", Domain.new([ 1, 2 ].to_set))
76
+ y = Variable.new("y", Domain.new([ 1, 2 ].to_set))
77
+ constraint = OneOfEqualsConstraint.new([ x, y ], 3)
78
+ y.value = 1
79
+ assert_equal([ [ x ], 0, true ], constraint.revise)
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
4
+
5
+ require 'test/unit'
6
+ require 'Problem'
7
+ require 'Variable'
8
+ require 'BinaryConstraint'
9
+ require 'ConstraintList'
10
+ require 'Domain'
11
+
12
+ module ConstraintSolver
13
+ class ProblemTest < Test::Unit::TestCase
14
+ def setup
15
+ @var1 = Variable.new("var1", nil, 1)
16
+ var2 = Variable.new("var2", nil, 2)
17
+ var3 = Variable.new("var3", nil, 3)
18
+
19
+ @c1 = BinaryConstraint.new(@var1, var2, Proc.new {|a, b| a == b })
20
+ c2 = BinaryConstraint.new(var2, var3, Proc.new {|a, b| a < b })
21
+
22
+ @problem = Problem.new([ @var1, var2, var3 ], ConstraintList.new([ @c1, c2 ]))
23
+ end
24
+
25
+ def testConstructor
26
+ assert_raise(ArgumentError) { Problem.new }
27
+ assert_raise(ArgumentError) { Problem.new(Array.new, Array.new) }
28
+ assert_nothing_raised { Problem.new(@var1, @c1) }
29
+ assert_nothing_raised { Problem.new([ @var1 ], [ @c1 ]) }
30
+ assert_nothing_raised { Problem.new([ @var1 ], [ @c1 ], {}) }
31
+ assert_nothing_raised { Problem.new([ @var1 ], [ @c1 ], {}, true) }
32
+ assert_nothing_raised { Problem.new([ @var1 ], [ @c1 ], {}, true, 0) }
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
4
+
5
+ require 'test/unit'
6
+ require 'Solution'
7
+ require 'Variable'
8
+ require 'Domain'
9
+ require 'extensions'
10
+
11
+ module ConstraintSolver
12
+ class SolutionTest < Test::Unit::TestCase
13
+ def setup
14
+ @var = Variable.new("test", Domain.new([ 1 ].to_set), nil, 2)
15
+ end
16
+
17
+ def testConstructor
18
+ assert_raise(ArgumentError) { Solution.new }
19
+ assert_raise(ArgumentError) { Solution.new(@var) }
20
+ @var.value = 1
21
+ assert_nothing_raised { Solution.new(@var) }
22
+ assert_nothing_raised { Solution.new(@var, {}) }
23
+ assert_nothing_raised { Solution.new(@var, {}, 0.5) }
24
+ @var.reset
25
+ end
26
+
27
+ def testValues
28
+ @var.value = 1
29
+ solution = Solution.new(@var, { 1 => 2 })
30
+ assert_equal(4, solution.merit)
31
+ assert_equal(1, solution.variables.size)
32
+ assert_equal(1, solution.variables.first.value)
33
+ end
34
+ end
35
+ end
data/test/TestSuite.rb ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'test/unit'
4
+ glob = $0.split(File::Separator)
5
+ glob.pop
6
+ glob << "*Test.rb"
7
+ glob = glob.join(File::Separator)
8
+ Dir[glob].each { |test|
9
+ require test
10
+ }
@@ -0,0 +1,151 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
4
+
5
+ require 'test/unit'
6
+ require 'TupleConstraint'
7
+ require 'Variable'
8
+ require 'Domain'
9
+
10
+ module ConstraintSolver
11
+ class TupleConstraintTest < Test::Unit::TestCase
12
+ def setup
13
+ @x = Variable.new("x", Domain.new([ 1, 2 ].to_set))
14
+ @y = Variable.new("y", Domain.new([ 1, 2 ].to_set))
15
+ @tuples = [ [ 1, 1 ], [ 2, 2 ] ]
16
+ @constraint = TupleConstraint.new([ @x, @y ], @tuples)
17
+ end
18
+
19
+ def testConstructor
20
+ assert_raise(ArgumentError) { TupleConstraint.new }
21
+ assert_raise(ArgumentError) { TupleConstraint.new([ @x, @y ], [ [ 1, 2 ], [ 1 ] ]) }
22
+ assert_nothing_raised { TupleConstraint.new([ @x, @y ], @tuples) }
23
+ assert_nothing_raised { TupleConstraint.new([ @x, @y ], @tuples, false) }
24
+ assert_nothing_raised { TupleConstraint.new([ @x, @y ], @tuples, 0) }
25
+ end
26
+
27
+ def testAssigned
28
+ assert_equal(false, @constraint.allAssigned?)
29
+ @x.value = 1
30
+ assert_equal(false, @constraint.allAssigned?)
31
+ @y.value = 1
32
+ assert_equal(true, @constraint.allAssigned?)
33
+ @x.reset
34
+ @y.reset
35
+ end
36
+
37
+ def testInclude
38
+ assert_equal(true, @constraint.include?(@x))
39
+ assert_equal(true, @constraint.include?(@y))
40
+ assert_equal(false, @constraint.include?(Variable.new("2", [ 3 ].to_set)))
41
+ end
42
+
43
+ def testHoldsAllowed
44
+ assert_equal(true, @constraint.holds?)
45
+ @x.value = 1
46
+ @y.value = 1
47
+ assert_equal(true, @constraint.holds?)
48
+ @x.value = 2
49
+ @y.value = 2
50
+ assert_equal(true, @constraint.holds?)
51
+ @x.value = 1
52
+ @y.value = 2
53
+ assert_equal(false, @constraint.holds?)
54
+ @x.value = 2
55
+ @y.value = 1
56
+ assert_equal(false, @constraint.holds?)
57
+ @y.reset
58
+ @x.value = 2
59
+ assert_equal(true, @constraint.holds?)
60
+ @x.reset
61
+ @y.value = 1
62
+ assert_equal(true, @constraint.holds?)
63
+ @y.reset
64
+ end
65
+
66
+ def testHoldsDisallowed
67
+ constraint = TupleConstraint.new([ @x, @y ], @tuples, false)
68
+ assert_equal(true, constraint.holds?)
69
+ @x.value = 1
70
+ @y.value = 1
71
+ assert_equal(false, constraint.holds?)
72
+ @x.value = 2
73
+ @y.value = 2
74
+ assert_equal(false, constraint.holds?)
75
+ @x.value = 1
76
+ @y.value = 2
77
+ assert_equal(true, constraint.holds?)
78
+ @x.value = 2
79
+ @y.value = 1
80
+ assert_equal(true, constraint.holds?)
81
+ @y.reset
82
+ @x.value = 2
83
+ assert_equal(true, constraint.holds?)
84
+ @x.reset
85
+ @y.value = 1
86
+ assert_equal(true, constraint.holds?)
87
+ end
88
+
89
+ def testEquals
90
+ assert_equal(TupleConstraint.new([ @x, @y ], @tuples), @constraint)
91
+ assert_not_equal(TupleConstraint.new([ Variable.new("z", Domain.new([ 1, 2 ].to_set)), @y ], @tuples), @constraint)
92
+ assert_not_equal(TupleConstraint.new([ @x, @y ], [ [ 1, 1 ] ]), @constraint)
93
+ end
94
+
95
+ def testReviseAllowed
96
+ x = Variable.new("x", Domain.new([ 1, 2, 3 ].to_set))
97
+ y = Variable.new("y", Domain.new([ 1, 2, 3 ].to_set))
98
+ z = Variable.new("z", Domain.new([ 1, 2, 3 ].to_set))
99
+ constraint = TupleConstraint.new([ x, y, z ], [ [ 1, 2, 3 ], [ 3, 2, 1 ], [ 3, 3, 3 ] ])
100
+ assert_equal([ [ x, y, z ], 0, false ], constraint.revise)
101
+ assert_equal([ 1, 3 ].to_set, x.domain.values)
102
+ assert_equal([ 2, 3 ].to_set, y.domain.values)
103
+ assert_equal([ 1, 3 ].to_set, z.domain.values)
104
+ x.domain.undoPruning
105
+ y.domain.undoPruning
106
+ z.domain.undoPruning
107
+
108
+ x.value = 1
109
+ assert_equal([ [ y, z ], 0, false ], constraint.revise)
110
+ assert_equal([ 2 ].to_set, y.domain.values)
111
+ assert_equal([ 3 ].to_set, z.domain.values)
112
+ x.reset
113
+ y.domain.undoPruning
114
+ z.domain.undoPruning
115
+
116
+ z.value = 3
117
+ assert_equal([ [ x, y ], 0, false ], constraint.revise)
118
+ assert_equal([ 1, 3 ].to_set, x.domain.values)
119
+ assert_equal([ 2, 3 ].to_set, y.domain.values)
120
+ z.reset
121
+ x.domain.undoPruning
122
+ y.domain.undoPruning
123
+
124
+ x.value = 2
125
+ assert_equal([ [ y ], 0, true ], constraint.revise)
126
+ end
127
+
128
+ def testReviseDisallowed
129
+ x = Variable.new("x", Domain.new([ 1, 2, 3 ].to_set))
130
+ y = Variable.new("y", Domain.new([ 1, 2, 3 ].to_set))
131
+ z = Variable.new("z", Domain.new([ 1, 2, 3 ].to_set))
132
+ constraint = TupleConstraint.new([ x, y, z ], [ [ 1, 2, 3 ], [ 3, 2, 1 ], [ 3, 3, 3 ] ], false)
133
+ assert_equal([ [], 0, false ], constraint.revise)
134
+ x.value = 1
135
+ assert_equal([ [ y, z ], 0, false ], constraint.revise)
136
+ assert_equal([ 1, 3 ].to_set, y.domain.values)
137
+ assert_equal([ 1, 2 ].to_set, z.domain.values)
138
+ y.domain.undoPruning
139
+ z.domain.undoPruning
140
+ x.reset
141
+
142
+ z.value = 3
143
+ assert_equal([ [ x, y ], 0, false ], constraint.revise)
144
+ assert_equal([ 2 ].to_set, x.domain.values)
145
+ assert_equal([ 1 ].to_set, y.domain.values)
146
+ x.domain.undoPruning
147
+ y.domain.undoPruning
148
+ z.reset
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
4
+
5
+ require 'test/unit'
6
+ require 'Variable'
7
+ require 'Domain'
8
+
9
+ module ConstraintSolver
10
+ class VariableTest < Test::Unit::TestCase
11
+ def setup
12
+ @variable = Variable.new("test", Domain.new([ 3, 4, 5 ].to_set))
13
+ end
14
+
15
+ def testConstructor
16
+ assert_raise(ArgumentError) { Variable.new }
17
+ assert_raise(ArgumentError) { Variable.new(nil) }
18
+ assert_raise(ArgumentError) { Variable.new(3) }
19
+ assert_raise(ArgumentError) { Variable.new("name", Domain.new([ 3 ].to_set), 4) }
20
+ assert_nothing_raised {
21
+ var = Variable.new("name", nil, 3)
22
+ assert_equal([ 3 ].to_set, var.domain.values)
23
+ }
24
+ assert_nothing_raised { Variable.new("name", Domain.new([ 3 ].to_set)) }
25
+ assert_nothing_raised { Variable.new("name", Domain.new([ 3 ].to_set), 3) }
26
+ end
27
+
28
+ def testAssignment
29
+ assert_raise(ArgumentError) { @variable.value = 2 }
30
+ assert_nothing_raised { @variable.value = nil }
31
+ assert_nothing_raised { @variable.value = 3 }
32
+ assert(@variable.assigned?)
33
+ assert_equal(3, @variable.value)
34
+ @variable.reset
35
+ assert_equal(false, @variable.assigned?)
36
+ assert_equal(nil, @variable.value)
37
+ end
38
+
39
+ def testEquals
40
+ assert_equal(@variable, Variable.new("test", Domain.new([ 3, 4, 5 ].to_set)))
41
+ assert_equal(@variable, Variable.new("test", Domain.new(Set.new)))
42
+ assert_not_equal(@variable, Variable.new("test", nil, 3))
43
+ assert_not_equal(@variable, Variable.new("test", Domain.new([ 3, 4, 5 ].to_set), 3))
44
+ assert_not_equal(@variable, Variable.new("tester", Domain.new([ 3, 4, 5 ].to_set)))
45
+ end
46
+ end
47
+ end