示例#1
0
def buchi_gen(bdd, g, f):
    g_copy = g.subarena(g.player0_vertices | g.player1_vertices, bdd)
    while True:
        for curr_f in range(g.nbr_functions):
            b0 = attractor(g_copy, f[curr_f], 0, bdd)
            not_b0 = (g_copy.player0_vertices | g_copy.player1_vertices) & ~b0
            if not not_b0 == bdd.false:
                break
        b1 = attractor(g_copy, not_b0, 1, bdd)
        if b1 == bdd.false:
            break
        not_b1 = ~b1
        g_copy = g_copy.subarena(not_b1, bdd)

    return g_copy.player0_vertices | g_copy.player1_vertices
示例#2
0
def buchi_inter_safety(bdd, g, i, f, s):
    if i == 0:
        oppo = 1
    else:
        oppo = 0  # changed here because for Charly -1 is player 1 and for me -1 evaluates to False (which is 0)
    attr_adv_f = attractor(g, s, oppo, bdd)
    g_bar = g.subarena(~attr_adv_f, bdd)
    return buchi(bdd, g_bar, i, f)
示例#3
0
def buchi_partial_solver(arena, partial_winning_region_player0,
                         partial_winning_region_player1, manager):
    """
    Partial solver for parity games using fatal attractors. Implementation using sets.
    :param arena: the arena we consider
    :type arena: Arena
    :param partial_winning_region_player0: should be empty list when called
    :type partial_winning_region_player0: []
    :param partial_winning_region_player1: should be empty list when called
    :type partial_winning_region_player1: []
    :param manager: the BDD manager
    :type manager: dd.cudd.BDD
    :return: a partial solution sub-arena, partial_player0, partial_player1 in which sub-arena remains unsolved and
    partial_player0 (resp. partial_player1) is included in the winning region of player 0 (resp. player 1) in arena.
    :rtype: (Arena, dd.cudd.Function, dd.cudd.Function)
    """

    empty_set = manager.false

    for priority in sort_priorities_ascending(arena):

        target_set = arena.priorities[0][priority] & (
            arena.player0_vertices | arena.player1_vertices
        )  # set of vertices of priority

        cache = manager.false

        while cache != target_set and target_set != empty_set:

            cache = target_set

            monotone_att = monotone_attractor(arena, target_set, priority,
                                              manager)

            # if target set is a subset of the monotone attractor
            if (monotone_att | target_set) == monotone_att:

                regular_att = attractor(arena, monotone_att, priority % 2,
                                        manager)

                # if priority is odd
                if priority % 2:
                    partial_winning_region_player1 = partial_winning_region_player1 | regular_att
                else:
                    partial_winning_region_player0 = partial_winning_region_player0 | regular_att

                return buchi_partial_solver(
                    arena.subarena(~regular_att,
                                   manager), partial_winning_region_player0,
                    partial_winning_region_player1, manager)

            else:
                target_set = target_set & monotone_att

    return arena, partial_winning_region_player0, partial_winning_region_player1
示例#4
0
def psolB(bdd, g):
    """
    This is Charly's implementation of psolB.
    """

    if g.player0_vertices == bdd.false and g.player1_vertices == bdd.false:

        return bdd.false, bdd.false

    d = max(g.priorities[0].keys())

    for curr_p in range(0, d + 1):

        player = curr_p % 2

        x = g.priorities[0][curr_p] & (g.player0_vertices | g.player1_vertices)

        f_old = bdd.false

        while not (x == bdd.false or x == f_old):

            f_old = x

            m_attr_x = monotone_attractor_cha(bdd, g, player, x, curr_p)

            if (m_attr_x | x) == m_attr_x:

                attr_ma = attractor(g, m_attr_x, player, bdd)

                ind_game = g.subarena(~attr_ma, bdd)

                (w_0, w_1) = psolB(bdd, ind_game)

                if player == 0:

                    w_0 = w_0 | attr_ma

                else:

                    w_1 = w_1 | attr_ma

                return w_0, w_1

            else:

                x = x & m_attr_x

    return bdd.false, bdd.false
示例#5
0
def ziel_with_psolver(g, bdd):
    """
    Solve the parity game provided in arena using a combinations of the recursive algorithm and the partial solver
    implemented using bdds. This is Charly's implementation.
    :param g: a game arena
    :type g: Arena
    :param bdd: the BDD manager
    :type bdd: dd.cudd.BDD
    :return: the solution of the provided parity game, that is the set of vertices won by each player
    :rtype: (dd.cudd.Function, dd.cudd.Function)
    """

    if g.player0_vertices == bdd.false and g.player1_vertices == bdd.false:
        return bdd.false, bdd.false

    z_0, z_1 = psolB(bdd, g)

    g_bar = g.subarena(~(z_0 | z_1), bdd)

    if (g_bar.player0_vertices | g_bar.player1_vertices) == bdd.false:
        return z_0, z_1

    p_max = max(g_bar.priorities[0].keys())  # get max priority occurring in g

    i = p_max % 2

    x = attractor(g_bar, g_bar.priorities[0][p_max], i, bdd)

    g_ind = g_bar.subarena(~x, bdd)

    (win_0, win_1) = ziel_with_psolver(g_ind, bdd)

    if i == 0:

        win_i = win_0
        win_i_bis = win_1
    else:

        win_i = win_1
        win_i_bis = win_0

    if win_i_bis == bdd.false:

        if i == 0:
            return z_0 | win_i | x, z_1
        else:
            return z_0, z_1 | win_i | x

    else:

        x = attractor(g_bar, win_i_bis, 1 - i, bdd)

        g_ind = g_bar.subarena(~x, bdd)

        (win_0, win_1) = ziel_with_psolver(g_ind, bdd)

        if i == 0:

            return z_0 | win_0, z_1 | win_1 | x

        else:

            return z_0 | win_0 | x, z_1 | win_1
示例#6
0
def recursive(arena, manager):
    """
    Solve the parity game provided in arena using the recursive algorithm implemented with bdds.
    :param arena: a game arena
    :type arena: Arena
    :param manager: the BDD manager
    :type manager: dd.cudd.BDD
    :return: the solution of the provided parity game, that is the set of vertices won by each player
    :rtype: (dd.cudd.Function, dd.cudd.Function)
    """

    winning_region_player0 = manager.false  # winning region of player 0
    winning_region_player1 = manager.false  # winning region of player 1

    # if the game is empty, return the empty regions
    if arena.player0_vertices == manager.false and arena.player1_vertices == manager.false:
        return winning_region_player0, winning_region_player1

    else:
        max_occurring_priority = max(arena.priorities[0].keys())  # get max priority occurring in the arena

        # determining which player we are considering, if max_occurring_priority is odd : player 1 and else player 0
        j = max_occurring_priority % 2

        opponent = 0 if j else 1  # getting the opponent of the player

        # vertices with priority max_occurring_priority
        U = arena.priorities[0][max_occurring_priority]

        # getting the attractor A
        A = attractor(arena, U, j, manager)

        # The subgame G\A is composed of the vertices not in the attractor
        G_A = arena.subarena(~A, manager)

        # Recursively solving the subgame G\A
        winning_region_player0_G_A, winning_region_player1_G_A = recursive(G_A, manager)

        # depending on which player we are considering, assign regions to the proper variables
        # if we consider player1
        if j:
            winning_region_player = winning_region_player1_G_A
            winning_region_opponent = winning_region_player0_G_A
        else:
            winning_region_player = winning_region_player0_G_A
            winning_region_opponent = winning_region_player1_G_A

        # if winning_region_opponent is empty we update the regions depending on the current player
        # the region for the whole game for one of the players is empty
        if winning_region_opponent == manager.false:

            # if we consider player1
            if j:
                winning_region_player1 = winning_region_player1 | A
                winning_region_player1 = winning_region_player1 | winning_region_player
            else:
                winning_region_player0 = winning_region_player0 | A
                winning_region_player0 = winning_region_player0 | winning_region_player

        else:
            # compute attractor B
            B = attractor(arena, winning_region_opponent, opponent, manager)

            # The subgame G\B is composed of the vertices not in the attractor
            G_B = arena.subarena(~B, manager)

            # recursively solve subgame G\B
            winning_region_player0_G_B, winning_region_player1_G_B = recursive(G_B, manager)

            # depending on which player we are considering, assign regions to the proper variables
            # if we consider player1
            if j:
                winning_region_player_bis = winning_region_player1_G_B
                winning_region_opponent_bis = winning_region_player0_G_B
            else:
                winning_region_player_bis = winning_region_player0_G_B
                winning_region_opponent_bis = winning_region_player1_G_B

            # the last step is to update the winning regions depending on which player we consider
            # if we consider player1
            if j:
                winning_region_player1 = winning_region_player_bis

                winning_region_player0 = winning_region_player0 | winning_region_opponent_bis
                winning_region_player0 = winning_region_player0 | B
            else:
                winning_region_player0 = winning_region_player_bis

                winning_region_player1 = winning_region_player1 | winning_region_opponent_bis
                winning_region_player1 = winning_region_player1 | B

    return winning_region_player0, winning_region_player1
示例#7
0
def buchi(bdd, g, i, f):
    return attractor(g, recur(bdd, g, i, f), i, bdd)
示例#8
0
def buchi_solver_gen_inverted_players(arena, manager):
    """
    k = nbr func
    @param arena:
    @type arena:
    @param manager:
    @type manager:
    @return:
    @rtype:
    """

    max_priorities = [-1] * arena.nbr_functions

    # TODO check if this should be done in every recursive call
    for function_index in range(arena.nbr_functions):

        for priority, bdd in arena.priorities[function_index].items():

            if (priority) > max_priorities[function_index]:
                max_priorities[function_index] = (priority)

    # Iterate over all 1-priority
    for prio_f_index in range(arena.nbr_functions):
        # arena.d[prio_f_index] max prio selon cette dimension ? TODO
        for curr_prio in range(max_priorities[prio_f_index] + 1):
            if curr_prio % 2 == 0 and not arena.priorities[prio_f_index][
                    curr_prio] == manager.false:
                u = arena.priorities[prio_f_index][curr_prio]
                u_bis = sup_prio_expr_odd(arena, manager, curr_prio,
                                          prio_f_index, max_priorities)

                w = attractor(arena,
                              buchi_inter_safety(manager, arena, 1, u, u_bis),
                              1, manager)  # ca change pas
                # pour buchi inter safety j'ai du changer l'ordre dans le monotone
                if not w == manager.false:
                    ind_game = arena.subarena(~w, manager)
                    (z0, z1) = buchi_solver_gen_inverted_players(
                        ind_game, manager)
                    return z0, z1 | w

    even_priorities = [[] for _ in range(arena.nbr_functions)]
    for prio_f_index in range(arena.nbr_functions):
        # changee en 1 => devrait etre toutes les imapir, le + 1 doit il rester +1 ou bien +2 pour aller au dessu alors que la prio existe pasTODO
        for curr_prio in range(1, max_priorities[prio_f_index] + 1, 2):
            if not arena.priorities[prio_f_index][curr_prio] == manager.false:
                even_priorities[prio_f_index].append(curr_prio)

    all_combinations = product(*even_priorities)  # ici ca devrait etre des odd
    # Iterate over all 0-priority vectors
    for curr_comb in all_combinations:
        u = [
            arena.priorities[l][curr_comb[l]]
            for l in range(arena.nbr_functions)
        ]
        u_bis = sup_one_prio_even(arena, manager, curr_comb, max_priorities)
        w = attractor(arena, buchi_inter_safety_gen(manager, arena, u, u_bis),
                      0, manager)
        if not w == manager.false:
            ind_game = arena.subarena(~w, manager)
            (z0, z1) = buchi_solver_gen_inverted_players(ind_game, manager)
            return z0 | w, z1

    return manager.false, manager.false
示例#9
0
def buchi_solver_gen(arena, manager):
    """
    k = nbr func
    @param arena:
    @type arena:
    @param manager:
    @type manager:
    @return:
    @rtype:
    """

    max_priorities = [-1] * arena.nbr_functions

    # TODO check if this should be done in every recursive call
    for function_index in range(arena.nbr_functions):

        for priority, bdd in arena.priorities[function_index].items():

            if (priority) > max_priorities[function_index]:
                max_priorities[function_index] = (priority)

    # Iterate over all 1-priority
    for prio_f_index in range(arena.nbr_functions):
        # arena.d[prio_f_index] max prio selon cette dimension ?
        for curr_prio in range(max_priorities[prio_f_index] + 1):
            if curr_prio % 2 == 1 and not arena.priorities[prio_f_index][
                    curr_prio] == manager.false:
                u = arena.priorities[prio_f_index][curr_prio]
                u_bis = sup_prio_expr_even(arena, manager, curr_prio,
                                           prio_f_index, max_priorities)

                w = attractor(arena,
                              buchi_inter_safety(manager, arena, 1, u, u_bis),
                              1, manager)

                if not w == manager.false:
                    ind_game = arena.subarena(~w, manager)
                    (z0, z1) = buchi_solver_gen(ind_game, manager)
                    return z0, z1 | w

    even_priorities = [[] for _ in range(arena.nbr_functions)]
    for prio_f_index in range(arena.nbr_functions):
        for curr_prio in range(0, max_priorities[prio_f_index] + 1, 2):
            if not arena.priorities[prio_f_index][curr_prio] == manager.false:
                even_priorities[prio_f_index].append(curr_prio)

    all_combinations = product(*even_priorities)
    # Iterate over all 0-priority vectors
    for curr_comb in all_combinations:
        u = [
            arena.priorities[l][curr_comb[l]]
            for l in range(arena.nbr_functions)
        ]
        u_bis = sup_one_prio_odd(arena, manager, curr_comb, max_priorities)
        w = attractor(arena, buchi_inter_safety_gen(manager, arena, u, u_bis),
                      0, manager)
        if not w == manager.false:
            ind_game = arena.subarena(~w, manager)
            (z0, z1) = buchi_solver_gen(ind_game, manager)
            return z0 | w, z1

    return manager.false, manager.false
示例#10
0
def buchi_inter_safety_gen(bdd, g, f, s):
    attr_adv_f = attractor(g, s, 1, bdd)
    g_bar = g.subarena(~attr_adv_f, bdd)
    return buchi_gen(bdd, g_bar, f)