ConstraintSolver 0.1

Sign up to get free protection for your applications and to get access to all the features.
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