def Cpre_0(antichain, graph, nbr_functions, max_value): """ Computes the antichain of the controllable predecessors for player 0 of 'antichain'. :param antichain: :type antichain: :param graph: :type graph: :param nbr_functions: :type nbr_functions: :param max_value: :type max_value: :return: :rtype: """ if antichain.incomparable_elements == []: return antichain cur_antichain = Antichain(comparator_generalized_0, intersector_generalized_0) for element in antichain.incomparable_elements: for pred in graph.get_predecessors(element[0]): if graph.get_node_player(pred) == 0: computed_down = down_generalized_0(element, graph.nodes[pred][1:], pred, nbr_functions, max_value) if computed_down != -1: cur_antichain.insert(computed_down) return cur_antichain
def Cpre_0(antichain, graph, max_counter): """ Computes the antichain of the controllable predecessors for player 0 of 'antichain'. :param antichain: :type antichain: :param graph: :type graph: :param max_counter: :type max_counter: :return: :rtype: """ if antichain.incomparable_elements == []: return antichain cur_antichain = Antichain(comparator, intersector) # check predecessors of each node present in the antichain for element in antichain.incomparable_elements: for pred in graph.get_predecessors(element[0]): # if said predecessors belong to player 0, compute down and add to the result if graph.get_node_player(pred) == 0: computed_down = down(element, graph.get_node_priority(pred), pred, max_counter) if computed_down != -1: cur_antichain.insert(computed_down) return cur_antichain
def create_start_antichain(starting_nodes, nbr_func, even_values): # TODO this is a crude creation adding every possibility, we can directly add the max elements io the max # even value for each start_antichain = Antichain(comparator_generalized, intersector_generalized) # create the antichain of maximal elements of the safe set # every counter in every tuple has the maximal value for node in starting_nodes: temp = [0] * (nbr_func + 1) temp[0] = node for func in range(1, nbr_func + 1): # even values are sorted temp[func] = even_values[func - 1][0] # even values are sorted so first is smallest start_antichain.insert(temp) return start_antichain
def Cpre_1(antichain, graph, nbr_functions, max_value): """ Computes the antichain of the controllable predecessors for player 1 of 'antichain'. :param antichain: :type antichain: :param graph: :type graph: :param nbr_functions: :type nbr_functions: :param max_value: :type max_value: :return: :rtype: """ if antichain.incomparable_elements == []: return antichain cur_antichain = Antichain(comparator_generalized_0, intersector_generalized_0) for node in graph.get_nodes(): if graph.get_node_player(node) == 1: first_iteration = True temp2 = Antichain( comparator_generalized_0, intersector_generalized_0) # contains the set for intersection for succ in graph.get_successors(node): temp1 = Antichain(comparator_generalized_0, intersector_generalized_0) for element in antichain.incomparable_elements: if element[0] == succ: computed_down = down_generalized_0( element, graph.nodes[node][1:], node, nbr_functions, max_value) # print("Down = "+str(computed_down)+" Compute down of "+str(element)+" with prio "+str(graph.get_node_priority(node))+" node "+str(node)+" val max "+str(max_counter)) if computed_down != -1: temp1.insert(computed_down) if first_iteration: temp2 = temp1 first_iteration = False else: # print("temp1 "+str(temp1)+ " temp2 "+str(temp2)) temp2 = temp1.intersection(temp2) # print("inter "+str(temp2)) cur_antichain = cur_antichain.union(temp2) return cur_antichain
def get_winning_regions_incremental(graph): """ Incremental algorithm to obtain the solution of the generalized parity game from the solutions of the safety games with incrementally larger maximum values. :param graph: :type graph: :return: :rtype: """ # start with small maximum value max_value = 1 # the game is completely solved if we have decided a winner for each node completely_solved = False nbr_nodes = len(graph.get_nodes()) while not completely_solved: # compute both fixpoints for the current maximal value fixpoint_0 = compute_fixpoint_0(graph, max_value) # TODO this shoould be fixpoint_1 = compute_fixpoint_p1(graph, max_value) fixpoint_1 = Antichain(comparator_generalized_0, intersector_generalized_0) # extract both winning regions winning_region_0 = set() winning_region_1 = set() for element in fixpoint_0.incomparable_elements: winning_region_0.add(element[0]) for element in fixpoint_1.incomparable_elements: winning_region_1.add(element[0]) # check if the game is completely solved # TODO we need a stopping criterion when the theoretical maximal value that gives the equivalence is reached # TODO for testing purposes, stop at max_value = 100 if len(winning_region_0) + len( winning_region_1) == nbr_nodes or max_value == 100: completely_solved = True # print("MAX VALUE "+str(max_value)) # print("winning 0 " + str(winning_region_0)) # print("winning 1 " + str(winning_region_1)) # if it is not, increment the maximal value max_value += 1 # print("value "+str(max_value)+" current fixpoint 0 : "+ str( fixpoint_0)) # print("value "+str(max_value)+" current fixpoint 1 : "+ str( fixpoint_1)) return list(winning_region_0), list(winning_region_1)
def compute_fixpoint_0(graph, max_value): """ Computes the fixpoint obtained by the symbolic version of the backward algorithm for safety games. Starts from the antichain of the safe set and works backwards using controllable predecessors. The maximum value for the counters is a parameter to facilitate the incremental algorithm. :param graph: :type graph: :param max_value: :type max_value: :return: :rtype: """ # wether we want to print the sets during computation toPrint = False # get the values to create the create the antichain of maximal elements of the safe set nbr_functions, nbr_counters_per_function = compute_counters_sizes_0(graph) start_antichain = Antichain(comparator_generalized_0, intersector_generalized_0) # create the antichain of maximal elements of the safe set # every counter in every tuple has the maximal value for node in graph.get_nodes(): temp = [node] for func in range(0, nbr_functions): temp.append(nbr_counters_per_function[func] * [max_value]) start_antichain.insert(temp) if (toPrint): print("Start antichain : " + str(start_antichain) + "\n") antichain1 = start_antichain cpre1 = Cpre(start_antichain, 1, graph, nbr_functions, max_value) if (toPrint): print("CPre_1 of start antichain: " + str(cpre1) + "\n") cpre0 = Cpre(start_antichain, 0, graph, nbr_functions, max_value) if (toPrint): print("CPre_0 of start antichain: " + str(cpre0) + "\n") # we know the elements of cpre0 and cpre1 to be incomparable. Union of the two antichains can be done through # simple extend cpre0.incomparable_elements.extend(cpre1.incomparable_elements) if (toPrint): print("Union of CPre_0 and CPre_1 " + str(cpre0) + "\n") antichain2 = antichain1.intersection(cpre0) if (toPrint): print("Inter of start and previous union " + str(antichain2) + "\n") nb_iter = 0 # while we have not obtained the fixpoint while not antichain1.compare(antichain2): nb_iter += 1 antichain1 = antichain2 cpre1 = Cpre(antichain1, 1, graph, nbr_functions, max_value) if (toPrint): print("ITER " + str(nb_iter) + " CPre 1 of prev " + str(cpre1) + "\n") cpre0 = Cpre(antichain1, 0, graph, nbr_functions, max_value) if (toPrint): print("ITER " + str(nb_iter) + " CPre 0 of prev " + str(cpre0) + "\n") temp = cpre0.union(cpre1) if (toPrint): print("ITER " + str(nb_iter) + " Union of Pre 0 and Pre 1 " + str(temp) + "\n") antichain2 = antichain1.intersection(temp) if (toPrint): print("ITER " + str(nb_iter) + " final set " + str(antichain2) + "\n") return antichain1
def test_natvectors(self): print("Testing natural vector antichains") def compare_lists(t1, t2): return len(t1) == len(t2) and\ all(map(lambda x: x[0] <= x[1], zip(t1, t2))) def meet_lists(t1, t2): assert len(t1) == len(t2) return map(lambda x: max(x[0], x[1]), zip(t1, t2)) ac = Antichain(compare_lists, meet_lists) ac.insert([1, 2]) # this should enter self.assertTrue(ac.contains([1, 2])) ac.insert([1, 3]) # this is larger than the previous one self.assertFalse(ac.contains([1, 2])) self.assertTrue(ac.contains([1, 3])) ac.insert([2, 1]) # this should enter too self.assertTrue(ac.contains([2, 1])) self.assertTrue(ac.contains([1, 3]))
def compute_fixpoint(graph): """ Computes the fixpoint obtained by the symbolic version of the backward algorithm for safety games. Starts from the antichain of the safety set and works backwards using controllable predecessors. :param graph: :type graph: :return: :rtype: """ # wether we want to print the sets during computation toPrint = False # create the antichain of maximal elements of the safe set max_counter = compute_max_counter(graph) start_antichain = Antichain(comparator, intersector) for node in graph.get_nodes(): start_antichain.insert([node] + max_counter) if (toPrint): print("Start antichain : " + str(start_antichain) + "\n") antichain1 = start_antichain cpre1 = Cpre(start_antichain, 1, graph, max_counter) if (toPrint): print("CPre_1 of start antichain: " + str(cpre1) + "\n") cpre0 = Cpre(start_antichain, 0, graph, max_counter) if (toPrint): print("CPre_0 of start antichain: " + str(cpre0) + "\n") # we know the elements of cpre0 and cpre1 to be incomparable. Union of the two antichains can be done through # simple extend cpre0.incomparable_elements.extend(cpre1.incomparable_elements) if (toPrint): print("Union of CPre_0 and CPre_1 " + str(cpre0) + "\n") antichain2 = antichain1.intersection(cpre0) if (toPrint): print("Inter of start and previous union " + str(antichain2) + "\n") nb_iter = 0 # while we have not obtained the fixpoint while not antichain1.compare(antichain2): nb_iter += 1 antichain1 = antichain2 cpre1 = Cpre(antichain1, 1, graph, max_counter) if (toPrint): print("ITER " + str(nb_iter) + " CPre 1 of prev " + str(cpre1) + "\n") cpre0 = Cpre(antichain1, 0, graph, max_counter) if (toPrint): print("ITER " + str(nb_iter) + " CPre 0 of prev " + str(cpre0) + "\n") temp = cpre0.union(cpre1) if (toPrint): print("ITER " + str(nb_iter) + " Union of Pre 0 and Pre 1 " + str(temp) + "\n") antichain2 = antichain1.intersection(temp) if (toPrint): print("ITER " + str(nb_iter) + " final set " + str(antichain2) + "\n") return antichain1
def compute_fixpoint(graph, starting_nodes, nbr_func, even_values, max_values): """ This is the attractor starting node is f_j Computes the fixpoint obtained by the symbolic version of the backward algorithm for safety games. Starts from the antichain of the safe set and works backwards using controllable predecessors. The maximum value for the counters is a parameter to facilitate the incremental algorithm. :param graph: :type graph: :param max_value: :type max_value: :return: :rtype: """ if DEBUG_PRINT: print("ARRIVING IN FIXPOINT ") print(graph) print("even_values " + str(even_values)) print("max values " + str(max_values)) # wether we want to print the sets during computation toPrint = False # start antichain is antichain of tj start_antichain = create_start_antichain(starting_nodes, nbr_func, even_values) # TODO change intersection to union, also add target as union when computing cpre, also the true start is # the cpre of start if (toPrint): print("Dtart antichain : " + str(start_antichain) + "\n") cpre1 = Cpre(start_antichain, 1, graph, nbr_func, max_values) if (toPrint): print("CPre_1 of start antichain - new start : " + str(cpre1) + "\n") cpre0 = Cpre(start_antichain, 0, graph, nbr_func, max_values) if (toPrint): print("CPre_0 of start antichain - new start : " + str(cpre0) + "\n") # we know the elements of cpre0 and cpre1 to be incomparable. Union of the two antichains can be done through # simple extend cpre0.incomparable_elements.extend(cpre1.incomparable_elements) if (toPrint): print("New start antichain : " + str(cpre0) + "\n") antichain1 = cpre0 antichain1_union_start = Antichain(comparator_generalized, intersector_generalized) antichain1_union_start.union(cpre0) antichain1_union_start.union(start_antichain) cpre1 = Cpre(antichain1_union_start, 1, graph, nbr_func, max_values) if (toPrint): print("CPre_1 of start antichain: " + str(cpre1) + "\n") cpre0 = Cpre(antichain1_union_start, 0, graph, nbr_func, max_values) if (toPrint): print("CPre_0 of start antichain: " + str(cpre0) + "\n") # we know the elements of cpre0 and cpre1 to be incomparable. Union of the two antichains can be done through # simple extend cpre0.incomparable_elements.extend(cpre1.incomparable_elements) if (toPrint): print("Union of CPre_0 and CPre_1 " + str(cpre0) + "\n") tmp = copy.deepcopy(antichain1) antichain2 = antichain1.union(cpre0) antichain1 = tmp if (toPrint): print("Union of new start and previous union " + str(antichain2) + "\n") nb_iter = 0 #print("antichain 1"+str(antichain1)) #print("antichain 2" +str(antichain2)) # while we have not obtained the fixpoint while not antichain2.compare(antichain1): nb_iter += 1 antichain1 = antichain2 antichain1_union_start = Antichain(comparator_generalized, intersector_generalized) antichain1_union_start.union(antichain1) antichain1_union_start.union(start_antichain) cpre1 = Cpre(antichain1_union_start, 1, graph, nbr_func, max_values) if (toPrint): print("ITER " + str(nb_iter) + " CPre 1 of prev " + str(cpre1) + "\n") cpre0 = Cpre(antichain1_union_start, 0, graph, nbr_func, max_values) if (toPrint): print("ITER " + str(nb_iter) + " CPre 0 of prev " + str(cpre0) + "\n") temp = cpre0.union(cpre1) if (toPrint): print("ITER " + str(nb_iter) + " Union of Pre 0 and Pre 1 " + str(temp) + "\n") tmp = copy.deepcopy(antichain1) antichain2 = antichain1.union(temp) antichain1 = tmp if (toPrint): print("ITER " + str(nb_iter) + " final set " + str(antichain2) + "\n") return antichain1