def test_arc_will_restore_all_domains_when_not_given_the_last_queen(self): ac = ArcConsistency(Arcs(4)) problem = Variables(4) problem.queens[0].value = 1 problem.queens[1].value = 3 ac.arcConsistent(problem) self.assertEqual(set([1, 2, 3, 4]), problem.queens[1].domain) self.assertEqual(3, problem.queens[1].value)
def test_arc_will_not_backtrack_too_far_when_it_sees_a_failure(self): ac = ArcConsistency(Arcs(4)) problem = Variables(4) problem.queens[0].value = 2 problem.queens[3].value = 4 ac.arcConsistent(problem, problem.queens[3]) self.assertEqual(set([3]), problem.queens[3].domain) self.assertEqual(-1, problem.queens[3].value)
def setUp(self): self.ac = ArcConsistency(Arcs(8))
class Line: def __init__(self, Q): self.arcs = Arcs(Q) def arc(self, current_arc, last=False): n = len(current_arc) if last and not len(self.line_arcs) and n == 1: point = current_arc[0] index = self.arcs.get_index(point) if len(index): self.line_arcs.append(index[0]) else: index.append(self.arcs.length) self.line_arcs.append(index[0]) self.arcs.push(current_arc) elif n > 1: self.line_arcs.append(self.arcs.check(current_arc)) def line(self, points, opened): self.line_arcs = [] n = len(points) current_arc = Strut() k = 0 p = False t = False if not opened: points.pop() n -= 1 while k < n: t = self.arcs.peak(points[k]) if opened: break if p and not mysterious_line_test(p, t): tInP = all(map(lambda line: line in p, t)) pInT = all(map(lambda line: line in t, p)) if tInP and not pInT: k -= 1 break p = t k += 1 # If no shared starting point is found for closed lines, rotate to minimum. if k == n and isinstance(p, list) and len(p) > 1: point0 = points[0] i = 2 k = 0 while i < n: point = points[i] if point_compare(point0, point) > 0: point0 = point k = i i += 1 i = -1 if opened: m = n - 1 else: m = n while i < m: i += 1 point = points[(i + k) % n] p = self.arcs.peak(point) if not mysterious_line_test(p, t): tInP = all(map(lambda line: line in p, t)) pInT = all(map(lambda line: line in t, p)) if tInP: current_arc.append(point) self.arc(current_arc) if not tInP and not pInT and len(current_arc): self.arc(Strut([current_arc[-1], point])) if pInT and len(current_arc): current_arc = Strut([current_arc[-1]]) else: current_arc = Strut() if not len(current_arc) or point_compare(current_arc[-1], point): current_arc.append(point) # skip duplicate points t = p self.arc(current_arc, True) return self.line_arcs def line_closed(self, points): return self.line(points, False) def line_open(self, points): return self.line(points, True) def map_func(self, arc): if len(arc) == 2 and type(arc[0]) == type(1): arc = [arc] i = 1 n = len(arc) point = arc[0] x1 = point[0] x2 = dx = y2 = dy = False y1 = point[1] points = [[int(x1), int(y1)]] while i < n: point = arc[i] if not is_point(point): i += 1 continue x2 = point[0] y2 = point[1] dx = int(x2 - x1) dy = int(y2 - y1) if dx or dy: points.append([dx, dy]) x1 = x2 y1 = y2 i += 1 return points def get_arcs(self): return self.arcs.map(self.map_func)
def __init__(self, Q): self.arcs = Arcs(Q)
def setUp(self): self.gac = GlobalArcConsistency(Arcs(8))
class Line: def __init__(self, Q): self.arcs = Arcs(Q) def matchForward(self, b, arthur): i = 0 n = len(arthur) if len(b) != n: return False while i < n: if pointCompare(arthur[i], b[i]): return False i += 1 self.lineArcs.append(b.index) return True def matchBackward(self, b, arthur): i = 0 n = len(arthur) if len(b) != n: return False while i < n: if pointCompare(arthur[i], b[n - i - 1]): return False i += 1 self.lineArcs.append(~b.index) return True def arc(self, alice, last=False): n = len(alice) if last and not len(self.lineArcs) and n == 1: point = alice[0] index = self.arcs.getIndex(point) if len(index): self.lineArcs.append(index[0]) else: index.append(self.arcs.length) self.lineArcs.append(index[0]) self.arcs.push(alice) elif n > 1: a0 = alice[0] a1 = alice[-1] point = a0 if pointCompare(a0, a1) < 0 else a1 pointArcs = self.arcs.getPointArcs(point) if any(map(lambda x: self.matchForward(x, alice), pointArcs)): return if any(map(lambda x: self.matchBackward(x, alice), pointArcs)): return pointArcs.append(alice) alice.index = self.arcs.length self.lineArcs.append(alice.index) self.arcs.push(alice) def line(self, points, opened): self.lineArcs = [] n = len(points) arthur = strut() k = 1 p = False t = False if not opened: points.pop() n -= 1 while k < n: t = self.arcs.peak(points[k]) if opened: break if p and not linesEqual(p, t): tInP = all(map(lambda line: line in p, t)) pInT = all(map(lambda line: line in t, p)) if tInP and not pInT: k -= 1 break p = t k += 1 # If no shared starting point is found for closed lines, rotate to minimum. if k == n and len(p) > 1: point0 = points[0] i = 2 k = 0 while i < n: point = points[i] if pointCompare(point0, point) > 0: point0 = point k = i i += 1 i = 0 if opened: m = n else: m = n + 1 while i < m: i += 1 point = points[(i + k) % n] p = self.arcs.peak(point) if not linesEqual(p, t): tInP = all(map(lambda line: line in p, t)) pInT = all(map(lambda line: line in t, p)) if tInP: arthur.append(point) self.arc(arthur) if not tInP and not pInT: self.arc(strut([arthur[-1], point])) if pInT and len(arthur): arthur = strut([arthur[-1]]) else: arthur = strut() if not len(arthur) or pointCompare(arthur[-1], point): arthur.append(point) # skip duplicate points t = p self.arc(arthur, True) return self.lineArcs def lineClosed(self, points): return self.line(points, False) def lineOpen(self, points): self.line(points, True) def mapFunc(self, arc): if len(arc) == 2 and type(arc[0]) == type(1): arc = [arc] i = 1 n = len(arc) point = arc[0] x1 = point[0] x2 = dx = y2 = dy = False y1 = point[1] points = [[int(x1), int(y1)]] while i < n: point = arc[i] if not isPoint(point): i += 1 continue x2 = point[0] y2 = point[1] dx = int(x2 - x1) dy = int(y2 - y1) if dx or dy: points.append([dx, dy]) x1 = x2 y1 = y2 i += 1 return points def getArcs(self): return self.arcs.map(self.mapFunc)
def test_global_arc_consistency_can_find_a_solution(self): problem = Variables(4) gac = GlobalArcConsistency(Arcs(4)) gac.findSolution(problem) self.assertTrue(self.fourByFourSolution(problem.queens) or self.altFourByFourSolution(problem.queens))
def test_global_arc_consistency_can_find_a_larger_solution(self): problem = Variables(8) gac = GlobalArcConsistency(Arcs(8)) gac.findSolution(problem) for queen in problem.queens: self.assertNotEqual(-1, queen.value)
def __init__(self,Q): self.arcs = Arcs(Q)
class Line: def __init__(self,Q): self.arcs = Arcs(Q) def arc(self,current_arc, last=False): n = len(current_arc) if last and not len(self.line_arcs) and n == 1: point = current_arc[0] index = self.arcs.get_index(point) if len(index): self.line_arcs.append(index[0]) else: index.append(self.arcs.length) self.line_arcs.append(index[0]) self.arcs.push(current_arc) elif n > 1: self.line_arcs.append(self.arcs.check(current_arc)) def line(self,points,opened): self.line_arcs = []; n = len(points) current_arc = Strut() k = 1 p=False t=False if not opened: points.pop() n-=1 while k < n: t = self.arcs.peak(points[k]) if opened: break if p and not mysterious_line_test(p, t): tInP = all(map(lambda line:line in p,t)) pInT = all(map(lambda line:line in t,p)) if tInP and not pInT: k-=1 break p = t k+=1 # If no shared starting point is found for closed lines, rotate to minimum. if k == n and isinstance(p,list) and len(p) > 1: point0 = points[0] i = 2 k=0 while i<n: point = points[i]; if point_compare(point0, point) > 0: point0 = point k = i i+=1 i = 0 if opened: m = n else: m = n+1 while i < m: i+=1 point = points[(i + k) % n] p = self.arcs.peak(point) if not mysterious_line_test(p, t): tInP = all(map(lambda line: line in p,t)) pInT = all(map(lambda line: line in t,p)) if tInP: current_arc.append(point); self.arc(current_arc) if not tInP and not pInT and len(current_arc): self.arc(Strut([current_arc[-1], point])) if pInT and len(current_arc): current_arc = Strut([current_arc[-1]]) else: current_arc = Strut(); if not len(current_arc) or point_compare(current_arc[-1], point): current_arc.append(point) # skip duplicate points t = p self.arc(current_arc, True) return self.line_arcs def line_closed(self,points): return self.line(points,False) def line_open(self,points): return self.line(points,True) def map_func (self,arc): if len(arc)==2 and type(arc[0])==type(1): arc= [arc] i = 1 n = len(arc) point = arc[0] x1 = point[0] x2= dx =y2 = dy=False y1 = point[1] points = [[int(x1), int(y1)]] while i < n: point = arc[i] if not is_point(point): i+=1 continue x2 = point[0] y2 = point[1] dx = int(x2 - x1) dy = int(y2 - y1) if dx or dy: points.append([dx, dy]) x1 = x2 y1 = y2 i+=1 return points def get_arcs (self): return self.arcs.map(self.map_func)
class Line: def __init__(self,Q): self.arcs = Arcs(Q) def matchForward(self,b,arthur): i = 0 n = len(arthur) if len(b) != n: return False while i < n: if pointCompare(arthur[i], b[i]): return False; i+=1 self.lineArcs.append(b.index) return True; def matchBackward(self,b,arthur): i = 0 n = len(arthur) if len(b) != n: return False while i<n: if pointCompare(arthur[i], b[n - i - 1]): return False i+=1 self.lineArcs.append(~b.index) return True def arc(self,alice, last=False): n = len(alice) if last and not len(self.lineArcs) and n == 1: point = alice[0] index = self.arcs.getIndex(point) if len(index): self.lineArcs.append(index[0]) else: index.append(self.arcs.length) self.lineArcs.append(index[0]) self.arcs.push(alice) elif n > 1: a0 = alice[0] a1 = alice[-1] point = a0 if pointCompare(a0, a1) < 0 else a1 pointArcs = self.arcs.getPointArcs(point) if any(map(lambda x:self.matchForward(x,alice),pointArcs)): return if any(map(lambda x:self.matchBackward(x,alice),pointArcs)): return pointArcs.append(alice) alice.index=self.arcs.length self.lineArcs.append(alice.index) self.arcs.push(alice) def line(self,points,opened): self.lineArcs = []; n = len(points) arthur = strut() k = 1 p=False t=False if not opened: points.pop() n-=1 while k < n: t = self.arcs.peak(points[k]) if opened: break if p and not linesEqual(p, t): tInP = all(map(lambda line:line in p,t)) pInT = all(map(lambda line:line in t,p)) if tInP and not pInT: k-=1 break p = t k+=1 # If no shared starting point is found for closed lines, rotate to minimum. if k == n and len(p) > 1: point0 = points[0] i = 2 k=0 while i<n: point = points[i]; if pointCompare(point0, point) > 0: point0 = point k = i i+=1 i = 0 if opened: m = n else: m = n+1 while i < m: i+=1 point = points[(i + k) % n] p = self.arcs.peak(point) if not linesEqual(p, t): tInP = all(map(lambda line: line in p,t)) pInT = all(map(lambda line: line in t,p)) if tInP: arthur.append(point); self.arc(arthur) if not tInP and not pInT: self.arc(strut([arthur[-1], point])) if pInT and len(arthur): arthur = strut([arthur[-1]]) else: arthur = strut(); if not len(arthur) or pointCompare(arthur[-1], point): arthur.append(point) # skip duplicate points t = p self.arc(arthur, True) return self.lineArcs def lineClosed(self,points): return self.line(points,False) def lineOpen(self,points): self.line(points,True) def mapFunc (self,arc): if len(arc)==2 and type(arc[0])==type(1): arc= [arc] i = 1; n = len(arc) point = arc[0] x1 = point[0] x2= dx =y2 = dy=False y1 = point[1] points = [[int(x1), int(y1)]] while i < n: point = arc[i] if not isPoint(point): i+=1 continue x2 = point[0] y2 = point[1] dx = int(x2 - x1) dy = int(y2 - y1) if dx or dy: points.append([dx, dy]) x1 = x2 y1 = y2 i+=1 return points def getArcs (self): return self.arcs.map(self.mapFunc)
def setUp(self): self.constraints = Arcs(8) self.variables = Variables(8)
class Arc_Tests(unittest.TestCase): def setUp(self): self.constraints = Arcs(8) self.variables = Variables(8) def test_there_are_two_arcs_for_each_constraint(self): self.assertEqual(112, len(self.constraints.set)) def test_constraints_can_detect_two_queens_in_the_same_diagonal(self): self.variables.queens[0].value = 4 self.variables.queens[3].value = 7 self.assertEqual(False, self.constraints.verify(self.variables)) def test_constraints_can_detect_two_queens_in_the_opposing_diagonals(self): self.variables.queens[4].value = 6 self.variables.queens[7].value = 3 self.assertEqual(False, self.constraints.verify(self.variables)) def test_constraints_can_detect_three_queens_in_the_same_diagonal(self): self.variables.queens[0].value = 4 self.variables.queens[2].value = 6 self.variables.queens[3].value = 7 self.assertEqual(False, self.constraints.verify(self.variables)) def test_constraints_can_detect_two_queens_in_the_same_rows(self): self.variables.queens[0].value = 1 self.variables.queens[7].value = 1 self.assertEqual(False, self.constraints.verify(self.variables)) def test_constraints_can_detect_three_queens_in_the_same_rows(self): self.variables.queens[0].value = 4 self.variables.queens[1].value = 4 self.variables.queens[2].value = 4 self.assertEqual(False, self.constraints.verify(self.variables)) def test_constraints_will_allow_unassigned_values_to_pass_constraints( self): self.variables.queens[0].value = 1 self.variables.queens[1].value = 3 self.assertEqual(True, self.constraints.verify(self.variables)) def test_contraints_will_prune_domains(self): self.variables.queens[0].value = 1 self.constraints.wipeout(self.variables, self.variables.queens[0]) self.variables.queens[1].value = 3 self.constraints.wipeout(self.variables, self.variables.queens[1]) self.assertEqual(set([5, 6, 7, 8]), self.variables.queens[2].domain) self.assertEqual(set([2, 6, 7, 8]), self.variables.queens[3].domain) self.assertEqual(set([2, 4, 7, 8]), self.variables.queens[4].domain) self.assertEqual(set([2, 4, 5, 6, 7]), self.variables.queens[7].domain) def test_contraints_will_return_nothing_when_assigned_values_wipeout_a_domain( self): self.variables.queens[0].value = 2 self.constraints.wipeout(self.variables, self.variables.queens[0]) self.variables.queens[1].value = 4 self.constraints.wipeout(self.variables, self.variables.queens[1]) self.variables.queens[2].value = 1 self.constraints.wipeout(self.variables, self.variables.queens[2]) self.variables.queens[3].value = 3 self.constraints.wipeout(self.variables, self.variables.queens[3]) self.variables.queens[4].value = 5 self.assertEqual( None, self.constraints.wipeout(self.variables, self.variables.queens[4])) def test_constraints_will_return_the_pruned_values(self): self.variables.queens[0].value = 1 values = self.constraints.wipeout(self.variables, self.variables.queens[0]) self.assertItemsEqual([(3, 1), (2, 3), (7, 8), (2, 1), (7, 1), (5, 6), (4, 1), (4, 5), (5, 1), (1, 2), (3, 4), (6, 1), (1, 1), (6, 7)], values) def test_constraints_can_restore_domains(self): self.variables.queens[0].value = 1 values = self.constraints.wipeout(self.variables, self.variables.queens[0]) self.constraints.restore(self.variables, values) self.assertEqual(set([1, 2, 3, 4, 5, 6, 7, 8]), self.variables.queens[0].domain) self.assertEqual(set([1, 2, 3, 4, 5, 6, 7, 8]), self.variables.queens[1].domain) self.assertEqual(set([1, 2, 3, 4, 5, 6, 7, 8]), self.variables.queens[7].domain)