コード例 #1
0
ファイル: psolC.py プロジェクト: Skar0/generalizedparity
def R_set(g, target_set, j):
    """
    We compute the attractor of a set of node-priority pairs where the priority
    represents the maximal priority seen so far.
    """
    ascending_priorities = g.get_sorted_priorities()
    v_out = init_out(g)  # a counter for visited edges from each vertex
    out = {(v, p): v_out[v]
           for v in g.get_nodes() for p in ascending_priorities}
    regions = defaultdict(lambda: -1)
    adversary = operations.opponent(j)

    # we keep a queue of newly found winning vertex-priority pairs
    queue = deque(target_set)
    while queue:
        (node, priority) = queue.popleft()
        for pred in g.get_predecessors(node):
            pred_player = g.get_node_player(pred)
            pred_priority = g.get_node_priority(pred)
            if pred_priority > priority:
                continue  # cannot be a predecessor
            if priority > g.get_node_priority(node):
                options = [priority]
            else:
                assert (priority == g.get_node_priority(node))
                options = filter(
                    lambda x: x >= pred_priority and x <= priority,
                    ascending_priorities)
                assert (len(options) > 0)
            for p in options:
                if regions[(pred, p)] == -1:  # vertex-priority is undecided
                    if pred_player == j:
                        regions[(pred, p)] = j
                        if (pred, p) not in target_set:
                            queue.append((pred, p))
                    elif pred_player == adversary:
                        out[(pred, p)] -= 1
                        if out[(pred, p)] == 0:
                            regions[(pred, p)] = j
                            if (pred, p) not in target_set:
                                queue.append((pred, p))
    # prepare output
    W = set()
    for n in g.get_nodes():
        if regions[(n, g.get_node_priority(n))] == j:
            W.add(n)
    return W
コード例 #2
0
def monotone_attractor_including_target(g, target_set, color):
    """
    Computes the monotone attractor of the target set, meaning the attractor without visiting bigger priorities than
    the one of the target set. This implementation adds the target set in the attractor at the start and checks during
    computation if the nodes of that target set would have been added to the attractor had they not been added at the
    start. This differs from the usual implementation which does not add the target set to the attractor at the start.
    In theory, this should allow us a quicker check of inclusion of the target set in the attractor.
    :param g: a game graph.
    :param target_set: a target set of nodes.
    :param color: the color of the nodes in target set.
    :return: W, in_att, Wbis the attractor, a dictionary of which nodes in the target set are in the attractor and the
    nodes which are not in the attractor.
    """

    p = color  # priority of the node gives us the player for which we compute the attractor
    out = init_out(g)  # init out
    queue = deque()  # init queue (deque is part of standard library and allows O(1) append() and pop() at either end)
    # this dictionary is used to know if a node belongs to a winning region without
    # iterating over both winning regions lists (we can check in O(1) in average)
    regions = defaultdict(lambda: -1)
    W = []  # the attractor
    j = p % 2  # the player for which we compute the attractor
    opponent = ops.opponent(j)  # player j's opponent

    in_att = defaultdict(lambda: 0)

    # for each node in the target set U
    for node in target_set:
        queue.append(node)  # add node to the end of the queue
        regions[node] = j  # set its regions to j (node is winning for j because reachability objective is satisfied)
        W.append(node)  # add the node to the winning region list of j

    if DEBUG_PRINT:
        print(g)
        print("Set " + str(target_set) + " Player " + str(j) + " Opponent " + str(opponent) + " Prio " + str(p))
        print("Marked before start " + str(regions) + " Queue before start " + str(queue))

    # while queue is not empty
    while queue:

        if DEBUG_PRINT: print("     Queue " + str(queue))

        s = queue.popleft()  # remove and return node on the left side of the queue (first in, first out)

        if DEBUG_PRINT: print("     Considering node " + str(s))

        # iterating over the predecessors of node s
        for sbis in g.get_predecessors(s):

            # get sbis info
            sbis_player = g.get_node_player(sbis)
            sbis_priority = g.get_node_priority(sbis)

            if DEBUG_PRINT:
                print("         Considering predecessor " + str(sbis) + " Is marked ? " + str(regions[sbis]) + "Player "
                      + str(sbis_player) + " Priority " + str(sbis_priority))

            # if the predecessor is in the target set
            # TODO here instead of in, we can use a special value in the regions dictionnary for nodes in target
            # set for quicker check, if so we also need to modify Wbis computation to take this into account
            if sbis in target_set:

                # if it belongs to player 1, sbis is in the attractor so we mark it
                if sbis_player == j:
                    in_att[sbis] = 1

                # else  we decrement its out value, and when it is 0 we mark it
                else:
                    out[sbis] -= 1
                    if out[sbis] == 0:
                        in_att[sbis] = 1

            if regions[sbis] == -1:  # if sbis is not yet visited, its region is -1 by default

                if sbis_player == j and sbis_priority <= p:

                    if DEBUG_PRINT: print("             Predecessor " + str(sbis) + " Added ")

                    # belongs to j, set regions and strategy accordingly
                    queue.append(sbis)
                    regions[sbis] = j
                    W.append(sbis)

                elif sbis_player == opponent and sbis_priority <= p:
                    # belongs to j bar, decrement out. If out is 0, set the region accordingly
                    out[sbis] -= 1

                    if DEBUG_PRINT: print("             Predecessor " + str(sbis) + " Decrement, new count = " +
                                          str(out[sbis]))
                    if out[sbis] == 0:

                        if DEBUG_PRINT: print("             Predecessor " + str(sbis) + " Added ")

                        queue.append(sbis)
                        regions[sbis] = j
                        W.append(sbis)

    # every node that is not marked is not in the attractor, we filter them for speed
    Wbis = filter(lambda x: regions[x] != j, g.nodes.iterkeys())

    if DEBUG_PRINT:
        print("Attractor " + str(W) + " Complement " + str(Wbis))
        print("-------------------------\n")

    return W, in_att, Wbis
コード例 #3
0
def monotone_attractor(g, target_set, color):
    """
    Computes the monotone attractor of the target set, meaning the attractor without visiting bigger priorities than
    the one of the target set.
    :param g: a game graph.
    :param target_set: a target set of nodes.
    :param color: the color of the nodes in target set.
    :return: W, Wbis the attractor and the nodes which are not in the attractor.
    """

    priority = color  # priority of the node gives us the player for which we compute the attractor
    out = init_out(g)  # init out
    queue = deque()  # init queue (deque is part of standard library and allows O(1) append() and pop() at either end)
    # this dictionary is used to know if a node belongs to a winning region without
    # iterating over both winning regions lists (we can check in O(1) in average)
    regions = defaultdict(lambda: -1)
    W = []  # the attractor
    j = priority % 2  # the player for which we compute the attractor
    opponent = ops.opponent(j)  # player j's opponent

    for node in target_set:
        queue.append(node)  # add node to the end of the queue

    if DEBUG_PRINT:
        print("--- Monotone attractor ---")
        print(g)
        print("Set " + str(target_set) + " Player " + str(j) + " Opponent " + str(opponent) + " Prio " + str(priority))
        print("Marked before start " + str(regions) + " Queue before start " + str(queue))

    # while queue is not empty
    while queue:

        if DEBUG_PRINT: print("     Queue " + str(queue))

        s = queue.popleft()  # remove and return node on the left side of the queue (first in, first out)

        if DEBUG_PRINT: print("     Considering node " + str(s))

        # iterating over the predecessors of node s
        for sbis in g.get_predecessors(s):

            # get sbis info
            sbis_player = g.get_node_player(sbis)
            sbis_priority = g.get_node_priority(sbis)

            if DEBUG_PRINT:
                print("         Considering predecessor " + str(sbis) + " Is marked ? " + str(regions[sbis]) + "Player "
                      + str(sbis_player) + " Priority " + str(sbis_priority))

            if regions[sbis] == -1:  # if sbis is not yet visited, its region is -1 by default

                # if node is the correct player and its priority is lower or equal, add it
                if sbis_player == j and sbis_priority <= priority:

                    if DEBUG_PRINT: print("             Predecessor " + str(sbis) + " Added ")

                    # if node has not been considered yet (not already been in the queue) add it
                    # this is to avoid considering the same node twice, which can happen only for the target node and
                    # can mess up the decrementation of the counters for nodes of the opponent
                    if sbis not in target_set:
                        queue.append(sbis)

                    # mark accordingly and add to winning region
                    regions[sbis] = j
                    W.append(sbis)

                # if node is the opposite player and its priority is lower or equal, check its counter of successors
                elif sbis_player == opponent and sbis_priority <= priority:

                    # belongs to j bar, decrement out. If out is 0, set the region accordingly
                    out[sbis] -= 1

                    if DEBUG_PRINT: print("             Predecessor " + str(sbis) + " Decrement, new count = " +
                                          str(out[sbis]))

                    if out[sbis] == 0:

                        if DEBUG_PRINT: print("             Predecessor " + str(sbis) + " Added ")

                        # if node has not been considered yet (not already been in the queue) add it
                        if sbis not in target_set:
                            queue.append(sbis)

                        # mark accordingly and add to winning region
                        regions[sbis] = j
                        W.append(sbis)

    # every node that is not marked is not in the attractor, we filter them for speed
    Wbis = filter(lambda x: regions[x] != j, g.nodes.iterkeys())

    if DEBUG_PRINT:
        print("Attractor " + str(W) + " Complement " + str(Wbis))
        print("-------------------------\n")

    return W, Wbis