def run_on_edge(self, edge): """ Run Kempe Path Algorithm on an error edge. :returns: length of path involved - If error is reduced -length of path involved - If no error is reduced """ # not an error, stop if not edge.is_error(): return -1 (a, b) = edge.get_endpoints() ca = edge.get_link(a).color cb = edge.get_link(b).color if random.random() < 0.5: p = create_path(self.graph, a, cb, ca) else: p = create_path(self.graph, b, ca, cb) # meet start edge, stop if p.is_closed(): return -len(p) # flip whole path p.swap_colors(ca, cb) return len(p)
def check_cycles(self): ((c, a, d), (e, b, f)) = self.removed if self.graph.get_color(c, d) != self.graph.get_color(e, f): self.put_back_edge() return False self.put_back_edge() self.last_removed = ((c, a, d), (e, b, f)) c0 = self.graph.get_color(c, a) colors = [1, 2, 3] colors.remove(c0) c1, c2 = tuple(colors) # try 1st self.graph.set_color(a, c, c1) self.graph.set_color(b, e, c1) self.graph.set_color(a, b, c2) self.graph.set_color(b, a, c2) p1 = create_path(self.graph, self.graph.get_edge(a, c), a, c0, c1) p2 = create_path(self.graph, self.graph.get_edge(b, e), b, c0, c1) if not p1.is_closed() or not p2.is_closed(): return False self.bicycle_configs = [(c0, c1, c2, p1, p2)] # try 2nd self.graph.set_color(a, c, c2) self.graph.set_color(b, e, c2) self.graph.set_color(a, b, c1) self.graph.set_color(b, a, c1) p1 = create_path(self.graph, self.graph.get_edge(a, c), a, c0, c2) p2 = create_path(self.graph, self.graph.get_edge(b, e), b, c0, c2) if not p1.is_closed() or not p2.is_closed(): return False self.bicycle_configs.append((c0, c2, c1, p1, p2)) return True
def _sub_routine_for_resolve(self, path1): a, b = path1.c2, path1.c1 v1 = path1.begin v2 = path1.end c = 6 - a - b path_ac = create_path(self.graph, v1, c, a) path_bc = create_path(self.graph, v2, c, b) v_ac = [] v_bc = [] for ve in self.graph.vertices: if ve.id not in path_ac: v_ac.append(ve.id) if ve.id not in path_bc: v_bc.append(ve.id) ac_cycle = self.factor_cycle(v_ac, a, c) bc_cycle = self.factor_cycle(v_bc, b, c) cycles = ac_cycle + bc_cycle for x in cycles: x.invert_colors() temp = create_path(self.graph, v1, b, a) if temp.is_closed() != True: x.invert_colors() return True x.invert_colors() return False
def highlight_bc_cycles(self): if not hasattr(self, "state") or self.state != "bc cycles": cycles = self.find_two_cycle() if cycles == None: print "not has two cycles" return False else: self.state = "bc cycles" left, right = cycles if left.c1 == 1: path_bc = create_path(self.graph, left.begin, 3, 2) else: path_bc = create_path(self.graph, left.end, 3, 2) v_bc = [] for v in self.graph.vertices: if v.id not in path_bc: v_bc.append(v.id) self.bc_cycles = self.factor_cycle(v_bc, 2, 3) self.highlighted = [] if len(self.bc_cycles) > 0: self.highlighted.append(self.bc_cycles[0]) self.bc_cycles = self.bc_cycles[1:] + self.bc_cycles[0:1] return self.prepare_highlight_data()
def _sub_routine_for_count(self, path1): a, b = path1.c2, path1.c1 v1 = path1.begin v2 = path1.end c = 6 - a - b path_ac = create_path(self.graph, v1, c, a) path_bc = create_path(self.graph, v2, c, b) v_ac = [] v_bc = [] for ve in self.graph.vertices: if ve.id not in path_ac: v_ac.append(ve.id) if ve.id not in path_bc: v_bc.append(ve.id) ac_cycle = self.factor_cycle(v_ac, a, c) bc_cycle = self.factor_cycle(v_bc, b, c) cycles = ac_cycle + bc_cycle for x in cycles: x.invert_colors() temp = create_path(self.graph, v1, b, a) if temp.is_closed() != True: x.invert_colors() return True x.invert_colors() return False
def highlight_bc_cycles(self): if not hasattr(self, 'state') or self.state != "bc cycles": cycles = self.find_two_cycle() if cycles == None: print("not has two cycles") return False else: self.state = "bc cycles" left, right = cycles if left.c1 == 1: path_bc = create_path(self.graph, left.begin, 3, 2) else: path_bc = create_path(self.graph, left.end, 3, 2) v_bc = [] for v in self.graph.vertices: if v.id not in path_bc: v_bc.append(v.id) self.bc_cycles = self.factor_cycle(v_bc, 2, 3) self.highlighted = [] if len(self.bc_cycles) > 0: self.highlighted.append(self.bc_cycles[0]) self.bc_cycles = self.bc_cycles[1:] + self.bc_cycles[0:1] return self.prepare_highlight_data()
def find_two_cycle(self): errors = [] for edge in self.graph.errors: errors.append(edge) if len(errors) != 2: print ("errors not equal 2, return false") return None (v1, v2) = errors[0].get_endpoints() (x1, y1) = self.graph._positions[v1] (x2, y2) = self.graph._positions[v2] mid1 = x1 + x2 (v3, v4) = errors[1].get_endpoints() (x3, y3) = self.graph._positions[v3] (x4, y4) = self.graph._positions[v4] mid2 = x3 + x4 if mid1 <= mid2: left = errors[0] right = errors[1] else: left = errors[1] right = errors[0] (v1, v2) = left.get_endpoints() (v3, v4) = right.get_endpoints() la = left.link_color(v1) lb = left.link_color(v2) ra = right.link_color(v3) rb = right.link_color(v4) if la + lb != ra + rb: print ("Two variable not same, return false") return None left_p = create_path(self.graph, v1, lb, la) if left_p.is_closed() != True: print ("two variables are adjacent, return False") return None right_p = create_path(self.graph, v3, rb, ra) c = 6 - la - lb if c != 3: self.graph.swap_colors(c, 3) if left_p.c1 == 3: left_p.c1 = c; else: left_p.c2 = c; if right_p.c1 == 3: right_p.c1 = c; else: right_p.c2 = c; return (left_p, right_p)
def find_two_cycle(self): errors = [] for edge in self.graph.errors: errors.append(edge) if len(errors) != 2: print "errors not equal 2, return false" return None (v1, v2) = errors[0].get_endpoints() (x1, y1) = self.graph._positions[v1] (x2, y2) = self.graph._positions[v2] mid1 = x1 + x2 (v3, v4) = errors[1].get_endpoints() (x3, y3) = self.graph._positions[v3] (x4, y4) = self.graph._positions[v4] mid2 = x3 + x4 if mid1 <= mid2: left = errors[0] right = errors[1] else: left = errors[1] right = errors[0] (v1, v2) = left.get_endpoints() (v3, v4) = right.get_endpoints() la = left.link_color(v1) lb = left.link_color(v2) ra = right.link_color(v3) rb = right.link_color(v4) if la + lb != ra + rb: print "Two variable not same, return false" return None left_p = create_path(self.graph, v1, lb, la) if left_p.is_closed() != True: print "two variables are adjacent, return False" return None right_p = create_path(self.graph, v3, rb, ra) c = 6 - la - lb if c != 3: self.graph.swap_colors(c, 3) if left_p.c1 == 3: left_p.c1 = c; else: left_p.c2 = c; if right_p.c1 == 3: right_p.c1 = c; else: right_p.c2 = c; return (left_p, right_p)
def bicycle_algorithm(self): errors = [] for e in self.graph.errors: errors.append(e) if len(errors) != 2: print "errors not equal 2, return false" return False left = errors[0] right = errors[1] (v1, v2) = left.get_endpoints() (v3, v4) = right.get_endpoints() la = left.link_color(v1) lb = left.link_color(v2) ra = right.link_color(v3) rb = right.link_color(v4) a, b = la, lb if (la, lb) == (ra, rb): pass elif (la, lb) == (rb, ra): v3, v4 = v4, v3 else: print "Two variable not same, return false" return False left_p = create_path(self.graph, v1, b, a) if left_p.is_closed() != True: count_utility.count(-1) left_p.swap_colors(b, a) return True right_p = create_path(self.graph, v3, b, a) len_left = len(left_p) len_right = len(right_p) steps = 0 for i in range(0, 2 * len_left): for j in range(0, 2 * len_right): if self.sub_routine_for_bicycle_algorithm(left_p, right_p): count_utility.count(steps) return True right_p.move_one_step() steps = steps + 1 left_p.move_one_step() return False
def bicycle_algorithm(self): errors = [] for e in self.graph.errors: errors.append(e) if len(errors) != 2: print ("errors not equal 2, return false") return False left = errors[0] right = errors[1] (v1, v2) = left.get_endpoints() (v3, v4) = right.get_endpoints() la = left.link_color(v1) lb = left.link_color(v2) ra = right.link_color(v3) rb = right.link_color(v4) a, b = la, lb if (la, lb) == (ra, rb): pass elif (la, lb) == (rb, ra): v3, v4 = v4, v3 else: print ("Two variable not same, return false") return False left_p = create_path(self.graph, v1, b, a) if left_p.is_closed() != True: count_utility.count(-1) left_p.swap_colors(b, a) return True right_p = create_path(self.graph, v3, b, a) len_left = len(left_p) len_right = len(right_p) steps = 0 for i in range(0, 2 * len_left): for j in range(0, 2 * len_right): if self.sub_routine_for_bicycle_algorithm(left_p, right_p): count_utility.count(steps) return True right_p.move_one_step() steps = steps + 1 left_p.move_one_step() return False
def not_finished_cycles_algorithm(self): cycles = self.find_locking_cycles() if cycles == False: return while len(cycles) > 0: cyc1 = random.choice(cycles) a, b = cyc1.c2, cyc1.c1 v1 = cyc1.begin v2 = cyc1.end c = 6 - a - b ac_cycle = self.factor_graph(a, c) bc_cycle = self.factor_graph(b, c) resolutions = ac_cycle + bc_cycle for x in resolutions: x.invert_colors() temp = create_path(self.graph, v1, b, a) if temp.is_closed() != True: temp.invert_colors() for cc in cycles: if temp.end in cc: cycles.remove(cc) print ("resolve two variables") break x.invert_colors() return False return True
def not_finished_cycles_algorithm(self): cycles = self.find_locking_cycles() if cycles == False: return while len(cycles) > 0: cyc1 = random.choice(cycles) a, b = cyc1.c2, cyc1.c1 v1 = cyc1.begin v2 = cyc1.end c = 6 - a - b ac_cycle = self.factor_graph(a, c) bc_cycle = self.factor_graph(b, c) resolutions = ac_cycle + bc_cycle for x in resolutions: x.invert_colors() temp = create_path(self.graph, v1, b, a) if temp.is_closed() != True: temp.invert_colors() for cc in cycles: if temp.end in cc: cycles.remove(cc) print "resolve two variables" break x.invert_colors() return False return True
def check_resolvable(self): errors = [] for edge in self.graph.errors: errors.append(edge) if len(errors) != 2: print "errors not equal 2, return false" return False left = errors[0] right = errors[1] (v1, v2) = left.get_endpoints() (v3, v4) = right.get_endpoints() la = left.link_color(v1) lb = left.link_color(v2) ra = right.link_color(v3) rb = right.link_color(v4) if (la + lb) != (ra + rb): print "Two variable not same, return false" return False path_1 = create_path(self.graph, v1, lb, la) if path_1.is_closed() != True: print "Two variables are connected!" return True return self._sub_routine_for_resolve(path_1)
def find_locking_cycles(self, standard = True): etype = None variables = [] for edge in self.graph.errors: variables.append(edge) if etype == None: etype = edge.edge_type elif edge.edge_type != etype: print "Not homogeneous configuration!" return False # different variables found if standard == True: if etype == "ac": self.graph.swap_colors(1, 3) elif etype == "bc": self.graph.swap_colors(2, 3) cycles = [] while len(variables) > 0: edge = variables.pop() (a, b) = edge.get_endpoints() ca = edge.link_color(a) cb = edge.link_color(b) temp = create_path(self.graph, a, cb, ca) if temp.is_closed() == True: cycles.append(temp) else: end = temp.end temp.invert_colors() for xx in variables: if end in xx: variables.remove(xx) break return cycles
def check_resolvable(self): errors = [] for edge in self.graph.errors: errors.append(edge) if len(errors) != 2: print("errors not equal 2, return false") return False left = errors[0] right = errors[1] (v1, v2) = left.get_endpoints() (v3, v4) = right.get_endpoints() la = left.link_color(v1) lb = left.link_color(v2) ra = right.link_color(v3) rb = right.link_color(v4) if (la + lb) != (ra + rb): print("Two variable not same, return false") return False path_1 = create_path(self.graph, v1, lb, la) if path_1.is_closed() != True: print("Two variables are connected!") return True return self._sub_routine_for_resolve(path_1)
def find_locking_cycles(self, standard = True): etype = None variables = [] for edge in self.graph.errors: variables.append(edge) if etype == None: etype = edge.edge_type elif edge.edge_type != etype: print ("Not homogeneous configuration!") return False # different variables found if standard == True: if etype == "ac": self.graph.swap_colors(1, 3) elif etype == "bc": self.graph.swap_colors(2, 3) cycles = [] while len(variables) > 0: edge = variables.pop() (a, b) = edge.get_endpoints() ca = edge.link_color(a) cb = edge.link_color(b) temp = create_path(self.graph, a, cb, ca) if temp.is_closed() == True: cycles.append(temp) else: end = temp.end temp.invert_colors() for xx in variables: if end in xx: variables.remove(xx) break return cycles
def bicycle_layout(self, width=600, height=600, margin=20): if not hasattr(self, 'state') or self.state != "two cycles": cycles = self.find_two_cycle() if cycles == None: print("not has two cycles") return False else: self.state = "two cycles" self.left_p, self.right_p = cycles left_top = self.left_p.begin right_top = self.right_p.begin radius = width * 0.6 import math rad = 2 * math.asin(0.5 * float(height - 2 * margin) / radius) for index in range(0, len(self.left_p), 1): p_rad = index * rad / (len(self.left_p) - 1) p_y = margin + (height - 2 * margin) / 2 - math.sin(rad / 2 - p_rad) * radius p_x = margin + math.cos(rad / 2 - p_rad) * radius - math.cos( rad / 2) * radius self.graph._positions[self.left_p._vertices[index]] = (p_x, p_y) for index in range(0, len(self.right_p), 1): p_rad = index * rad / (len(self.right_p) - 1) p_y = margin + (height - 2 * margin) / 2 - math.sin(rad / 2 - p_rad) * radius p_x = width - margin - (math.cos(rad / 2 - p_rad) * radius - math.cos(rad / 2) * radius) self.graph._positions[self.right_p._vertices[index]] = (p_x, p_y) color_a = self.left_p.c1 color_b = self.left_p.c2 other_vertices = [] for vertex in self.graph._vertices: if (vertex not in self.left_p) and (vertex not in self.right_p): other_vertices.append(int(vertex)) cycle = [] while len(other_vertices) > 0: start = other_vertices[0] p = create_path(self.graph, start, color_a, color_b) for x in p._vertices: other_vertices.remove(int(x)) cycle.append(p._vertices) x0 = width / 2 step = (height - 2 * margin) / (len(cycle) + 1) for i in range(0, len(cycle), 1): y0 = margin + (i + 1) * step step_angle = 2 * math.pi / len(cycle[i]) for j in range(0, len(cycle[i]), 1): x = x0 + math.cos(j * step_angle) * (width - 2 * margin) / 6 y = y0 + math.sin(j * step_angle) * (width - 2 * margin) / 6 self.graph._positions[cycle[i][j]] = (x, y) return True
def highlight_bc_exclusive_chain(self): if not hasattr(self, "state") or self.state != "exclusive chain": cycles = self.find_two_cycle() if cycles == None: print "not has two cycles" return False else: self.state = "exclusive chain" if cycles[0].c1 == 1: self.ac_chain = create_path(self.graph, cycles[0].end, 3, 1) self.bc_chain = create_path(self.graph, cycles[0].begin, 3, 2) else: self.ac_chain = create_path(self.graph, cycles[0].begin, 3, 1) self.bc_chain = create_path(self.graph, cycles[0].end, 3, 2) self.highlighted = [self.bc_chain] return self.prepare_highlight_data()
def highlight_bc_exclusive_chain(self): if not hasattr(self, 'state') or self.state != "exclusive chain": cycles = self.find_two_cycle() if cycles == None: print "not has two cycles" return False else: self.state = "exclusive chain" if cycles[0].c1 == 1: self.ac_chain = create_path(self.graph, cycles[0].end, 3, 1) self.bc_chain = create_path(self.graph, cycles[0].begin, 3, 2) else: self.ac_chain = create_path(self.graph, cycles[0].begin, 3, 1) self.bc_chain = create_path(self.graph, cycles[0].end, 3, 2) self.highlighted = [self.bc_chain] return self.prepare_highlight_data()
def format_location(cls, graph, kaixuanmen, width=600, height=600, margin=20): left, right, left_top, right_top, ceil = kaixuanmen radius = width import math rad = 2 * math.asin( 0.5 * float(height - 2 * margin) / radius ) left_p = create_path(graph, left_top, left.link_color(left.get_another_vertex(left_top)), left.link_color(left_top)) for index in range(0, len(left_p), 1): p_rad = index * rad / (len(left_p)-1) p_y = margin + (height - 2 * margin) / 2 - math.sin(rad / 2 - p_rad) * radius p_x = margin + math.cos(rad /2 - p_rad) * radius - math.cos(rad / 2) * radius graph._positions[left_p._vertices[index]] = (p_x, p_y) right_p = create_path(graph, right_top, right.link_color(right.get_another_vertex(right_top)), right.link_color(right_top)) for index in range(0, len(right_p), 1): p_rad = index * rad / (len(right_p)-1) p_y = margin + (height - 2 * margin) /2 - math.sin(rad / 2 - p_rad) * radius p_x = width - margin - (math.cos(rad / 2 - p_rad) * radius - math.cos(rad / 2) * radius) graph._positions[right_p._vertices[index]] = (p_x, p_y) (la, lb) = left.links color_a = la.color color_b = lb.color other_vertices = [] for vertex in graph._vertices: if (vertex not in left_p) and (vertex not in right_p): other_vertices.append(int(vertex)) cycle = [] while len(other_vertices) > 0: start = other_vertices[0] p = create_path(graph, start, color_a, color_b) for x in p._vertices: other_vertices.remove(int(x)) cycle.append(p._vertices) x0 = width / 2 step = (height - 2 * margin) / (len(cycle) + 1) for i in range(0,len(cycle),1): y0 = margin + (i + 1) * step step_angle = 2 * math.pi / len(cycle[i]) for j in range(0, len(cycle[i]), 1): x = x0 + math.cos(j * step_angle) * (width - 2 * margin)/4 y = y0 + math.sin(j * step_angle) * (width - 2 * margin)/4 graph._positions[cycle[i][j]] = (x,y)
def count_resolve(self): errors = [] for edge in self.graph.errors: errors.append(edge) if len(errors) != 2: print("errors not equal 2, return false") return left = errors[0] right = errors[1] (v1, v2) = left.get_endpoints() (v3, v4) = right.get_endpoints() la = left.link_color(v1) lb = left.link_color(v2) ra = right.link_color(v3) rb = right.link_color(v4) if la + lb != ra + rb: print("Two variable not same, return false") return left_p = create_path(self.graph, v1, lb, la) if left_p.is_closed() != True: print("Error: Two variables are connected!") return right_p = create_path(self.graph, v3, rb, ra) count = 0 for i in range(0, 2 * len(left_p)): for j in range(0, 2 * len(right_p)): if self._sub_routine_for_resolve(left_p): count = count + 1 right_p.move_one_step() left_p.move_one_step() print( "Total: ", 4, "*", len(left_p), "*", len(right_p), ) print(" = ", 4 * len(left_p) * len(right_p)) print("Solution #: ", count)
def invert_right_xy(cls, graph): result, err_msg, left, right, left_top, right_top, ceil = cls( ).find_KaiXuanMen(graph) right_bottom = right.get_another_vertex(right_top) path = create_path(graph, right_top, right.link_color(right_bottom), right.link_color(right_top)) path.swap_colors(right.link_color(right_bottom), right.link_color(right_top))
def count_solutions(self): errors = [] for e in self.graph.errors: errors.append(e) if len(errors) != 2: return False left = errors[0] right = errors[1] (v1, v2) = left.get_endpoints() (v3, v4) = right.get_endpoints() la = left.link_color(v1) lb = left.link_color(v2) ra = right.link_color(v3) rb = right.link_color(v4) a, b = la, lb if (la, lb) == (ra, rb): pass elif (la, lb) == (rb, ra): v3, v4 = v4, v3 else: return False left_p = create_path(self.graph, v1, b, a) if left_p.is_closed() != True: return -1 right_p = create_path(self.graph, v3, b, a) len_left = len(left_p) len_right = len(right_p) count = 0 for i in range(0, 2 * len_left): for j in range(0, 2 * len_right): if self._sub_routine_for_count(left_p): count = count + 1 right_p.move_one_step() left_p.move_one_step() return float(count) / (4 * len_left * len_right)
def bicycle_layout(self, width=600, height=600, margin=20): if not hasattr(self, "state") or self.state != "two cycles": cycles = self.find_two_cycle() if cycles == None: print "not has two cycles" return False else: self.state = "two cycles" self.left_p, self.right_p = cycles left_top = self.left_p.begin right_top = self.right_p.begin radius = width * 0.6 import math rad = 2 * math.asin(0.5 * float(height - 2 * margin) / radius) for index in range(0, len(self.left_p), 1): p_rad = index * rad / (len(self.left_p) - 1) p_y = margin + (height - 2 * margin) / 2 - math.sin(rad / 2 - p_rad) * radius p_x = margin + math.cos(rad / 2 - p_rad) * radius - math.cos(rad / 2) * radius self.graph._positions[self.left_p._vertices[index]] = (p_x, p_y) for index in range(0, len(self.right_p), 1): p_rad = index * rad / (len(self.right_p) - 1) p_y = margin + (height - 2 * margin) / 2 - math.sin(rad / 2 - p_rad) * radius p_x = width - margin - (math.cos(rad / 2 - p_rad) * radius - math.cos(rad / 2) * radius) self.graph._positions[self.right_p._vertices[index]] = (p_x, p_y) color_a = self.left_p.c1 color_b = self.left_p.c2 other_vertices = [] for vertex in self.graph._vertices: if (vertex not in self.left_p) and (vertex not in self.right_p): other_vertices.append(int(vertex)) cycle = [] while len(other_vertices) > 0: start = other_vertices[0] p = create_path(self.graph, start, color_a, color_b) for x in p._vertices: other_vertices.remove(int(x)) cycle.append(p._vertices) x0 = width / 2 step = (height - 2 * margin) / (len(cycle) + 1) for i in range(0, len(cycle), 1): y0 = margin + (i + 1) * step step_angle = 2 * math.pi / len(cycle[i]) for j in range(0, len(cycle[i]), 1): x = x0 + math.cos(j * step_angle) * (width - 2 * margin) / 6 y = y0 + math.sin(j * step_angle) * (width - 2 * margin) / 6 self.graph._positions[cycle[i][j]] = (x, y) return True
def find_KaiXuanMen(cls, graph): ''' contaions only two variables of the same kind which are linked by a ceil edge and the two variables are in different kempe cycles ''' errors = [] for edge in graph.edges: if edge.is_error(): errors.append(edge) if len(errors) != 2: err_msg = "errors not equal 2, return false" return (False, err_msg, None, None, None, None, None) left = errors[0] right = errors[1] (la, lb) = left.links (ra, rb) = right.links if la.color + lb.color != ra.color + rb.color: err_msg = "Two variable not same, return false" return (False, err_msg, None, None, None, None, None) ceil = None (la, lb) = left.get_endpoints() (ra, rb) = right.get_endpoints() if graph.get_edge_by_endpoint(la, ra) != None: left_top, right_top = la, ra ceil = graph.get_edge_by_endpoint(left_top, right_top) if graph.get_edge_by_endpoint(la, rb) != None: left_top, right_top = la, rb ceil = graph.get_edge_by_endpoint(left_top, right_top) if graph.get_edge_by_endpoint(lb, ra) != None: left_top, right_top = lb, ra ceil = graph.get_edge_by_endpoint(left_top, right_top) if graph.get_edge_by_endpoint(lb, rb) != None: left_top, right_top = lb, rb ceil = graph.get_edge_by_endpoint(left_top, right_top) if ceil == None: err_msg = "format color failed! Two variable not adjacent, return false" return (False, err_msg, None, None, None, None, None) left_p = create_path( graph, left_top, left.link_color(left.get_another_vertex(left_top)), left.link_color(left_top)) if left_p.is_closed() != True: err_msg = "left path not closed. Two variables are linked by kempe path, return false" return (False, err_msg, None, None, None, None, None) return (True, "", left, right, left_top, right_top, ceil)
def standard_format(cls, graph, width=600, height=600, margin=20): result, err_msg, left, right, left_top, right_top, ceil = cls().find_KaiXuanMen(graph) if result == False: print err_msg return False if ceil.color != 3: graph.swap_colors(ceil.color,3) if left.link_color(left_top) != 2: p = create_path(graph, left_top, 2, 1) p.swap_colors(1, 2) if right.link_color(right_top) != 2: p = create_path(graph, right_top, 2, 1) p.swap_colors(1, 2) kaixuanmen = (left, right, left_top, right_top, ceil) cls().format_location(graph, kaixuanmen, width, height, margin) return True
def standard_format(cls, graph, width=600, height=600, margin=20): result, err_msg, left, right, left_top, right_top, ceil = cls( ).find_KaiXuanMen(graph) if result == False: print err_msg return False if ceil.color != 3: graph.swap_colors(ceil.color, 3) if left.link_color(left_top) != 2: p = create_path(graph, left_top, 2, 1) p.swap_colors(1, 2) if right.link_color(right_top) != 2: p = create_path(graph, right_top, 2, 1) p.swap_colors(1, 2) kaixuanmen = (left, right, left_top, right_top, ceil) cls().format_location(graph, kaixuanmen, width, height, margin) return True
def factor_graph(self, x, y): vid_list = self.graph.vid_list rc = list() while len(vid_list) > 0: v = random.choice(vid_list) temp = create_path(self.graph, v, x, y) for v in temp: if v in vid_list: vid_list.remove(v) if temp.is_closed(): rc.append(temp) return rc
def find_KaiXuanMen(cls, graph): ''' contaions only two variables of the same kind which are linked by a ceil edge and the two variables are in different kempe cycles ''' errors = [] for edge in graph.edges: if edge.is_error(): errors.append(edge) if len(errors) != 2: err_msg = "errors not equal 2, return false" return (False, err_msg, None, None, None, None, None) left = errors[0] right = errors[1] (la, lb) = left.links (ra, rb) = right.links if la.color + lb.color != ra.color + rb.color: err_msg = "Two variable not same, return false" return (False, err_msg, None, None, None, None, None) ceil = None (la, lb) = left.get_endpoints() (ra, rb) = right.get_endpoints() if graph.get_edge_by_endpoint(la, ra) != None: left_top, right_top = la, ra ceil = graph.get_edge_by_endpoint(left_top, right_top) if graph.get_edge_by_endpoint(la, rb) != None: left_top, right_top = la, rb ceil = graph.get_edge_by_endpoint(left_top, right_top) if graph.get_edge_by_endpoint(lb, ra) != None: left_top, right_top = lb, ra ceil = graph.get_edge_by_endpoint(left_top, right_top) if graph.get_edge_by_endpoint(lb, rb) != None: left_top, right_top = lb, rb ceil = graph.get_edge_by_endpoint(left_top, right_top) if ceil == None: err_msg = "format color failed! Two variable not adjacent, return false" return (False, err_msg, None, None, None, None, None) left_p = create_path(graph, left_top, left.link_color(left.get_another_vertex(left_top)), left.link_color(left_top)) if left_p.is_closed() != True: err_msg = "left path not closed. Two variables are linked by kempe path, return false" return (False, err_msg, None, None, None, None, None) return (True, "", left, right, left_top, right_top, ceil)
def count_resolve(self): errors = [] for edge in self.graph.errors: errors.append(edge) if len(errors) != 2: print "errors not equal 2, return false" return left = errors[0] right = errors[1] (v1, v2) = left.get_endpoints() (v3, v4) = right.get_endpoints() la = left.link_color(v1) lb = left.link_color(v2) ra = right.link_color(v3) rb = right.link_color(v4) if la + lb != ra + rb: print "Two variable not same, return false" return left_p = create_path(self.graph, v1, lb, la) if left_p.is_closed() != True: print "Error: Two variables are connected!" return right_p = create_path(self.graph, v3, rb, ra) count = 0 for i in range(0, 2 * len(left_p)): for j in range(0, 2 * len(right_p)): if self._sub_routine_for_resolve(left_p): count = count + 1 right_p.move_one_step() left_p.move_one_step() print "Total: ", 4, "*", len(left_p), "*", len(right_p), print " = ", 4 * len(left_p) * len(right_p) print "Solution #: ", count
def factor_cycle(self, vertices, x, y): # vertices is the v_id list cycles = [] paths = [] while len(vertices) > 0: s = vertices[0] cycle1 = [] path = create_path(self.graph, s, x, y) paths.append(path) assert path.is_closed(), "assert path.is_closed()" for v in path: cycle1.append(v) vertices.remove(v) cycles.append(list(cycle1)) return paths
def smooth(self): for v in self.graph.vertices: if len(self.graph._neighbors[v.id]) == 2: eid1, eid2 = self.graph._neighbors[v.id] edge1 = self.graph.get_edge(eid1) edge2 = self.graph.get_edge(eid2) vid1 = edge1.get_another_vertex(v.id) vid2 = edge2.get_another_vertex(v.id) c1 = edge1.get_link(vid1).color c2 = edge2.get_link(vid2).color neweid = self.graph.smooth_vertex(v.id) edge = self.graph.get_edge(neweid) edge.get_link(vid1).color = c1 edge.get_link(vid2).color = c2 path = create_path(self.graph, vid1, c2, c1) if not path.is_closed(): path.invert_colors()
def easy_put_back(self): # check to see if there is edge removed. # if yes, simply put it back. And resolve the variables if it is easy. # return (k, Boolean) # k is the length of the cycle # Boolean is whether the variables are cleared up. if len(self.removed) > 0: e1, e2, cycle = self.removed.pop() else: print "nothing to put back" return colors = {1, 2, 3} k = len(cycle) #print "k: ", k a, b = tuple(cycle[:2]) if k == 2: # _ # c -- a -/ \- b -- d # \_/ # e_1 = c -- b # e_2 = c -- d # edge = self.graph.get_edge(e2) x0 = edge.color x1, x2 = tuple(colors - {x0}) (c, d) = edge.get_endpoints() self.graph.remove_edge(e2) self.graph.add_vertex(a) self.graph.add_vertex(b) f1 = self.graph.add_edge(a, b) f2 = self.graph.add_edge(a, b) f3 = self.graph.add_edge(a, c) f4 = self.graph.add_edge(b, d) self.graph.get_edge(f1).color = x1 self.graph.get_edge(f2).color = x2 self.graph.get_edge(f3).color = x0 self.graph.get_edge(f4).color = x0 self.state = "proper" return (k, True) edge_1 = self.graph.get_edge(e1) edge_2 = self.graph.get_edge(e2) if k == 3: # see p2 x1 = edge_1.color x2 = edge_2.color x0 = 6 - x1 - x2 v2 = cycle[2] v5 = edge_1.get_another_vertex(v2) v6 = edge_2.get_another_vertex(v2) self.graph.remove_edge(e1) self.graph.remove_edge(e2) self.graph.add_vertex(a) self.graph.add_vertex(b) f0 = self.graph.add_edge(a, b) f1 = self.graph.add_edge(a, v2) f2 = self.graph.add_edge(a, v5) f3 = self.graph.add_edge(b, v2) f4 = self.graph.add_edge(b, v6) self.graph.get_edge(f0).color = x0 self.graph.get_edge(f1).color = x2 self.graph.get_edge(f2).color = x1 self.graph.get_edge(f3).color = x1 self.graph.get_edge(f4).color = x2 self.state = "proper" return (k, True) if k == 4: # see p3 v2 = cycle[2] v1 = cycle[3] v5 = edge_1.get_another_vertex(v1) v6 = edge_2.get_another_vertex(v2) edge = self.graph.get_edge_by_endpoints(v1, v2) x0 = edge.color x1 = edge_1.color x2 = 6 - x0 - x1 x3 = edge_2.color # case 0, different color, independent cycles if x3 != x1: # different color path = create_path(self.graph, v2, x3, x1) if not v1 in path: # independent cycle path.swap_colors(x1, x3) # edge_1 and edge_2 should have the same color now x3 = edge_2.color # updated # put edges back self.graph.remove_edge(e1) self.graph.remove_edge(e2) self.graph.add_vertex(a) self.graph.add_vertex(b) f0 = self.graph.add_edge(a, b) f1 = self.graph.add_edge(a, v1) f2 = self.graph.add_edge(a, v5) f3 = self.graph.add_edge(b, v2) f4 = self.graph.add_edge(b, v6) # case 1, same color if x1 == x3: self.graph.get_edge(f0).color = x2 self.graph.get_edge(f1).color = x0 self.graph.get_edge(f2).color = x1 self.graph.get_edge(f3).color = x0 self.graph.get_edge(f4).color = x1 edge.color = x1 else: # case 2, different color, one cycle self.graph.get_edge(f0).color = x0 self.graph.get_edge(f2).color = x1 self.graph.get_edge(f4).color = x2 self.graph.get_link(f1, v1).color = x1 self.graph.get_link(f1, a).color = x2 self.graph.get_link(f3, v2).color = x2 self.graph.get_link(f3, b).color = x1 path = create_path(self.graph, v1, x2, x1) path.swap_colors(x1, x2) self.state = "proper" return (k, True) if k == 5: v1, v2, v3, v4, v5 = tuple(cycle) v8 = edge_1.get_another_vertex(v5) v6 = edge_2.get_another_vertex(v3) x1 = edge_1.color x3 = edge_2.color self.graph.remove_edge(e1) self.graph.remove_edge(e2) self.graph.add_vertex(v1) self.graph.add_vertex(v2) f0 = self.graph.add_edge(v1, v2) f1 = self.graph.add_edge(v1, v5) f2 = self.graph.add_edge(v1, v8) f3 = self.graph.add_edge(v2, v3) f4 = self.graph.add_edge(v2, v6) if x1 == x3: # case (a, b)|(a, b) x2 = self.graph.get_edge_by_endpoints(v4, v5).color x0 = 6 - x1 - x2 self.graph.get_edge(f0).color = x0 self.graph.get_edge(f2).color = x1 self.graph.get_edge(f4).color = x1 self.graph.get_link(f1, v5).color = x1 self.graph.get_link(f1, v1).color = x2 self.graph.get_link(f3, v3).color = x1 self.graph.get_link(f3, v2).color = x2 path = create_path(self.graph, v2, x1, x2) if not path.is_closed(): # not blocked, two var cancelled path.swap_colors(x1, x2) self.state = "proper" return (k, True) else: x2 = x3 x0 = 6 - x1 - x2 self.graph.get_edge(f0).color = x0 self.graph.get_edge(f2).color = x1 self.graph.get_edge(f4).color = x2 self.graph.get_link(f1, v5).color = x1 self.graph.get_link(f1, v1).color = x2 self.graph.get_link(f3, v3).color = x2 self.graph.get_link(f3, v2).color = x1 path = create_path(self.graph, v2, x2, x1) path.swap_colors(x1, x2) if not path.is_closed(): # not blocked, two var cancelled self.state = "proper" return (k, True) # if var not cancelled, it is formatted as (x1, x2) | (x1, x2) type v7 = filter(lambda v: not v in [v1, v4], self.graph.get_vertex(v5).neighbor_vertices)[0] v9 = filter(lambda v: not v in [v3, v5], self.graph.get_vertex(v4).neighbor_vertices)[0] v10 = filter(lambda v: not v in [v2, v4], self.graph.get_vertex(v3).neighbor_vertices)[0] f5 = self.graph.get_edge_by_endpoints(v5, v7).id f6 = self.graph.get_edge_by_endpoints(v4, v9).id f7 = self.graph.get_edge_by_endpoints(v3, v10).id f8 = self.graph.get_edge_by_endpoints(v4, v5).id f9 = self.graph.get_edge_by_endpoints(v3, v4).id self.vertices = (v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) self.edges = (f0, f1, f2, f3, f4, f5, f6, f7, f8, f9) self.state = "petersen" return (k, False) return (k, False)
def false_algorithm_1(self): errors = [] for e in self.graph.errors: errors.append(e) if len(errors) != 2: print ("errors not equal 2, return false") return False left = errors[0] right = errors[1] (v1, v2) = left.get_endpoints() (v3, v4) = right.get_endpoints() la = left.link_color(v1) lb = left.link_color(v2) ra = right.link_color(v3) rb = right.link_color(v4) a, b = la, lb if (la, lb) == (ra, rb): pass elif (la, lb) == (rb, ra): v3, v4 = v4, v3 else: print ("Two variable not same, return false") return False left_p = create_path(self.graph, v1, b, a) if left_p.is_closed() != True: left_p.swap_colors(b, a) return True if self.graph.multiplicity(v1, v3) == 1: x, y = v1, v3 elif self.graph.multiplicity(v1, v4) == 1: x, y = v1, v4 elif self.graph.multiplicity(v2, v3) == 1: x, y = v2, v3 elif self.graph.multiplicity(v2, v4) == 1: x, y = v2, v4 else: raise Exception("weriuhgas") xx = v1 + v2 - x yy = v3 + v4 - y vid_x = self.graph.neighbor_vid_list(x) vid_y = self.graph.neighbor_vid_list(y) vid_x.remove(y) vid_y.remove(x) x1, x2 = vid_x y1, y2 = vid_y def list_to_set(li): ss = set() for x in li: ss.add(x) return ss temp1 = self.graph.neighbor_vid_list(x1) ################### right_p = create_path(self.graph, v3, b, a) len_left = len(left_p) len_right = len(right_p) steps = 0 for i in range(0, 2 * len_left): for j in range(0, 2 * len_right): if self.sub_routine_for_bicycle_algorithm(left_p, right_p): count_utility.count(steps) return True right_p.move_one_step() steps = steps + 1 left_p.move_one_step() return False
def false_algorithm_1(self): errors = [] for e in self.graph.errors: errors.append(e) if len(errors) != 2: print "errors not equal 2, return false" return False left = errors[0] right = errors[1] (v1, v2) = left.get_endpoints() (v3, v4) = right.get_endpoints() la = left.link_color(v1) lb = left.link_color(v2) ra = right.link_color(v3) rb = right.link_color(v4) a, b = la, lb if (la, lb) == (ra, rb): pass elif (la, lb) == (rb, ra): v3, v4 = v4, v3 else: print "Two variable not same, return false" return False left_p = create_path(self.graph, v1, b, a) if left_p.is_closed() != True: left_p.swap_colors(b, a) return True if self.graph.multiplicity(v1, v3) == 1: x, y = v1, v3 elif self.graph.multiplicity(v1, v4) == 1: x, y = v1, v4 elif self.graph.multiplicity(v2, v3) == 1: x, y = v2, v3 elif self.graph.multiplicity(v2, v4) == 1: x, y = v2, v4 else: raise Exception("weriuhgas") xx = v1 + v2 - x yy = v3 + v4 - y vid_x = self.graph.neighbor_vid_list(x) vid_y = self.graph.neighbor_vid_list(y) vid_x.remove(y) vid_y.remove(x) x1, x2 = vid_x y1, y2 = vid_y def list_to_set(li): ss = set() for x in li: ss.add(x) return ss temp1 = self.graph.neighbor_vid_list(x1) ################### right_p = create_path(self.graph, v3, b, a) len_left = len(left_p) len_right = len(right_p) steps = 0 for i in range(0, 2 * len_left): for j in range(0, 2 * len_right): if self.sub_routine_for_bicycle_algorithm(left_p, right_p): count_utility.count(steps) return True right_p.move_one_step() steps = steps + 1 left_p.move_one_step() return False
def invert_right_xy(cls, graph): result, err_msg, left, right, left_top, right_top, ceil = cls().find_KaiXuanMen(graph) right_bottom = right.get_another_vertex(right_top) path = create_path(graph, right_top, right.link_color(right_bottom), right.link_color(right_top)) path.swap_colors(right.link_color(right_bottom), right.link_color(right_top))
def create_cycle_by_variable(self, var): (a,b) = var.get_endpoints() ca = var.link_color(a) cb = var.link_color(b) path = create_path(self.graph, a, b, cb, ca) return path
def format_location(cls, graph, kaixuanmen, width=600, height=600, margin=20): left, right, left_top, right_top, ceil = kaixuanmen radius = width import math rad = 2 * math.asin(0.5 * float(height - 2 * margin) / radius) left_p = create_path( graph, left_top, left.link_color(left.get_another_vertex(left_top)), left.link_color(left_top)) for index in range(0, len(left_p), 1): p_rad = index * rad / (len(left_p) - 1) p_y = margin + (height - 2 * margin) / 2 - math.sin(rad / 2 - p_rad) * radius p_x = margin + math.cos(rad / 2 - p_rad) * radius - math.cos( rad / 2) * radius graph._positions[left_p._vertices[index]] = (p_x, p_y) right_p = create_path( graph, right_top, right.link_color(right.get_another_vertex(right_top)), right.link_color(right_top)) for index in range(0, len(right_p), 1): p_rad = index * rad / (len(right_p) - 1) p_y = margin + (height - 2 * margin) / 2 - math.sin(rad / 2 - p_rad) * radius p_x = width - margin - (math.cos(rad / 2 - p_rad) * radius - math.cos(rad / 2) * radius) graph._positions[right_p._vertices[index]] = (p_x, p_y) (la, lb) = left.links color_a = la.color color_b = lb.color other_vertices = [] for vertex in graph._vertices: if (vertex not in left_p) and (vertex not in right_p): other_vertices.append(int(vertex)) cycle = [] while len(other_vertices) > 0: start = other_vertices[0] p = create_path(graph, start, color_a, color_b) for x in p._vertices: other_vertices.remove(int(x)) cycle.append(p._vertices) x0 = width / 2 step = (height - 2 * margin) / (len(cycle) + 1) for i in range(0, len(cycle), 1): y0 = margin + (i + 1) * step step_angle = 2 * math.pi / len(cycle[i]) for j in range(0, len(cycle[i]), 1): x = x0 + math.cos(j * step_angle) * (width - 2 * margin) / 4 y = y0 + math.sin(j * step_angle) * (width - 2 * margin) / 4 graph._positions[cycle[i][j]] = (x, y)
def easy_put_back(self): # check to see if there is edge removed. # if yes, simply put it back. And resolve the variables if it is easy. # return (k, Boolean) # k is the length of the cycle # Boolean is whether the variables are cleared up. if len(self.removed) > 0: e1, e2, cycle = self.removed.pop() else: print ("nothing to put back") return colors = {1, 2, 3} k = len(cycle) #print "k: ", k a, b = tuple(cycle[:2]) if k == 2: # _ # c -- a -/ \- b -- d # \_/ # e_1 = c -- b # e_2 = c -- d # edge = self.graph.get_edge(e2) x0 = edge.color x1, x2 = tuple(colors - {x0}) (c, d) = edge.get_endpoints() self.graph.remove_edge(e2) self.graph.add_vertex(a) self.graph.add_vertex(b) f1 = self.graph.add_edge(a, b) f2 = self.graph.add_edge(a, b) f3 = self.graph.add_edge(a, c) f4 = self.graph.add_edge(b, d) self.graph.get_edge(f1).color = x1 self.graph.get_edge(f2).color = x2 self.graph.get_edge(f3).color = x0 self.graph.get_edge(f4).color = x0 self.state = "proper" return (k, True) edge_1 = self.graph.get_edge(e1) edge_2 = self.graph.get_edge(e2) if k == 3: # see p2 x1 = edge_1.color x2 = edge_2.color x0 = 6 - x1 - x2 v2 = cycle[2] v5 = edge_1.get_another_vertex(v2) v6 = edge_2.get_another_vertex(v2) self.graph.remove_edge(e1) self.graph.remove_edge(e2) self.graph.add_vertex(a) self.graph.add_vertex(b) f0 = self.graph.add_edge(a, b) f1 = self.graph.add_edge(a, v2) f2 = self.graph.add_edge(a, v5) f3 = self.graph.add_edge(b, v2) f4 = self.graph.add_edge(b, v6) self.graph.get_edge(f0).color = x0 self.graph.get_edge(f1).color = x2 self.graph.get_edge(f2).color = x1 self.graph.get_edge(f3).color = x1 self.graph.get_edge(f4).color = x2 self.state = "proper" return (k, True) if k == 4: # see p3 v2 = cycle[2] v1 = cycle[3] v5 = edge_1.get_another_vertex(v1) v6 = edge_2.get_another_vertex(v2) edge = self.graph.get_edge_by_endpoints(v1, v2) x0 = edge.color x1 = edge_1.color x2 = 6 - x0 - x1 x3 = edge_2.color # case 0, different color, independent cycles if x3 != x1: # different color path = create_path(self.graph, v2, x3, x1) if not v1 in path: # independent cycle path.swap_colors(x1, x3) # edge_1 and edge_2 should have the same color now x3 = edge_2.color # updated # put edges back self.graph.remove_edge(e1) self.graph.remove_edge(e2) self.graph.add_vertex(a) self.graph.add_vertex(b) f0 = self.graph.add_edge(a, b) f1 = self.graph.add_edge(a, v1) f2 = self.graph.add_edge(a, v5) f3 = self.graph.add_edge(b, v2) f4 = self.graph.add_edge(b, v6) # case 1, same color if x1 == x3: self.graph.get_edge(f0).color = x2 self.graph.get_edge(f1).color = x0 self.graph.get_edge(f2).color = x1 self.graph.get_edge(f3).color = x0 self.graph.get_edge(f4).color = x1 edge.color = x1 else: # case 2, different color, one cycle self.graph.get_edge(f0).color = x0 self.graph.get_edge(f2).color = x1 self.graph.get_edge(f4).color = x2 self.graph.get_link(f1, v1).color = x1 self.graph.get_link(f1, a).color = x2 self.graph.get_link(f3, v2).color = x2 self.graph.get_link(f3, b).color = x1 path = create_path(self.graph, v1, x2, x1) path.swap_colors(x1, x2) self.state = "proper" return (k, True) if k == 5: v1, v2, v3, v4, v5 = tuple(cycle) v8 = edge_1.get_another_vertex(v5) v6 = edge_2.get_another_vertex(v3) x1 = edge_1.color x3 = edge_2.color self.graph.remove_edge(e1) self.graph.remove_edge(e2) self.graph.add_vertex(v1) self.graph.add_vertex(v2) f0 = self.graph.add_edge(v1, v2) f1 = self.graph.add_edge(v1, v5) f2 = self.graph.add_edge(v1, v8) f3 = self.graph.add_edge(v2, v3) f4 = self.graph.add_edge(v2, v6) if x1 == x3: # case (a, b)|(a, b) x2 = self.graph.get_edge_by_endpoints(v4, v5).color x0 = 6 - x1 - x2 self.graph.get_edge(f0).color = x0 self.graph.get_edge(f2).color = x1 self.graph.get_edge(f4).color = x1 self.graph.get_link(f1, v5).color = x1 self.graph.get_link(f1, v1).color = x2 self.graph.get_link(f3, v3).color = x1 self.graph.get_link(f3, v2).color = x2 path = create_path(self.graph, v2, x1, x2) if not path.is_closed(): # not blocked, two var cancelled path.swap_colors(x1, x2) self.state = "proper" return (k, True) else: x2 = x3 x0 = 6 - x1 - x2 self.graph.get_edge(f0).color = x0 self.graph.get_edge(f2).color = x1 self.graph.get_edge(f4).color = x2 self.graph.get_link(f1, v5).color = x1 self.graph.get_link(f1, v1).color = x2 self.graph.get_link(f3, v3).color = x2 self.graph.get_link(f3, v2).color = x1 path = create_path(self.graph, v2, x2, x1) path.swap_colors(x1, x2) if not path.is_closed(): # not blocked, two var cancelled self.state = "proper" return (k, True) # if var not cancelled, it is formatted as (x1, x2) | (x1, x2) type v7 = filter(lambda v: not v in [v1, v4], self.graph.get_vertex(v5).neighbor_vertices)[0] v9 = filter(lambda v: not v in [v3, v5], self.graph.get_vertex(v4).neighbor_vertices)[0] v10 = filter(lambda v: not v in [v2, v4], self.graph.get_vertex(v3).neighbor_vertices)[0] f5 = self.graph.get_edge_by_endpoints(v5, v7).id f6 = self.graph.get_edge_by_endpoints(v4, v9).id f7 = self.graph.get_edge_by_endpoints(v3, v10).id f8 = self.graph.get_edge_by_endpoints(v4, v5).id f9 = self.graph.get_edge_by_endpoints(v3, v4).id self.vertices = (v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) self.edges = (f0, f1, f2, f3, f4, f5, f6, f7, f8, f9) self.state = "petersen" return (k, False) return (k, False)