Ejemplo n.º 1
0
    def expand(self, node):
        def proof_sum(children):
            return sum(c.pn for c in children)

        def disproof_min(children):
            return min(c.dpn for c in children)

        #print (node.proof,node.disproof,node.state.board)
        proof, disproof = self.findtable(node)
        # Terminate searching if not necessary, limit reached of TT limit reached
        if node.pn <= proof or node.dpn <= disproof or self.max_table_size <= self.get_size(
        ) or self.terminated:
            node.pn = proof
            node.dpn = disproof
            return
        # If node has no successors
        # check if game is finished
        self.evaluate_node(node)
        result = node.value
        if (result == 1
                and node.node_type == "AND") or (result == 0
                                                 and node.node_type == "OR"):
            node.pn = float('inf')
            node.dpn = 0
            self.putintable(node)
            return
        elif result in (1, 0):
            node.pn = 0
            node.dpn = float('inf')
            self.putintable(node)
            return

        # Stored in transposition table to detect cycles
        self.putintable(node)

        children = []
        # generate all children
        for a in node.state.allowed_actions():
            new_state = node.state.perform_action(a)
            # find children in TT
            child_type = "AND" if node.node_type == "OR" else "OR"
            #child_node = Node(child_type,new_state,None,a)
            child_node = Node(node_type=child_type,
                              state=new_state,
                              parent=node,
                              depth=node.depth + 1,
                              action=a)
            child_proof, child_disproof = self.findtable(child_node)
            child_node.pn = child_proof
            child_node.dpn = child_disproof
            children.append(child_node)
        # iterative deepening, stop when TT max size is reached
        while node.pn > disproof_min(children) and node.dpn > proof_sum(
                children) and self.max_table_size > self.get_size(
                ) and not self.terminated:
            child, child_proof, child2_dpn = self.select_child(children)
            child.pn = node.dpn + child_proof - proof_sum(children)
            # e-trick
            if self.e:
                child.dpn = min(node.pn, child2_dpn * (1 + self.e))
            else:
                child.dpn = min(node.pn, child2_dpn + 1)
            # Second level search
            if self.second_level and (not self.in_table(child)):
                res, size = self.second_level(child)
                if child.node_type == "OR":
                    child.pn = res.pn
                    child.dpn = res.dpn
                else:
                    child.dpn = res.pn
                    child.pn = res.dpn
                self.putintable(child, size=size)
            else:
                self.expand(child)
        # store search result
        node.pn = disproof_min(children)
        node.dpn = proof_sum(children)
        self.putintable(node)
Ejemplo n.º 2
0
    def expand(self, node):
        def proof_sum(children):
            return sum(c.pn for c in children)

        def disproof_min(children):
            return min(c.dpn for c in children)

        #print (node.proof,node.disproof,node.state.board)
        proof, disproof = self.findtable(node)
        # Terminate searching if not necessary
        if proof == 0 or disproof == 0 or (proof >= node.pn
                                           and disproof >= node.dpn):
            node.pn = proof
            node.dpn = disproof
            return
        # If node has no successors
        # check if game is finished
        self.evaluate_node(node)
        result = node.value
        if (result == 1
                and node.node_type == "AND") or (result == 0
                                                 and node.node_type == "OR"):
            node.pn = float('inf')
            node.dpn = 0
            self.putintable(node)
            return
        elif result in (1, 0):
            node.pn = 0
            node.dpn = float('inf')
            self.putintable(node)
            return

        # Stored in transposition table to avoid cycles
        self.putintable(node)

        # multiple iterative deepening
        while True:
            children = []
            # generate all children
            for a in node.state.allowed_actions():
                new_state = node.state.perform_action(a)
                # find children in TT
                child_type = "AND" if node.node_type == "OR" else "OR"
                child_node = Node(node_type=child_type,
                                  state=new_state,
                                  parent=node,
                                  depth=node.depth + 1,
                                  action=a)
                child_proof, child_disproof = self.findtable(child_node)
                child_node.pn = child_proof
                child_node.dpn = child_disproof
                children.append(child_node)
            if node.depth == 0:
                print([c.pn for c in children])
                print([c.dpn for c in children])
                print("_____")
            # terminate if thresholds reached
            if proof_sum(children) == 0 or disproof_min(children) == 0 or (
                    node.pn <= disproof_min(children)
                    and node.dpn <= proof_sum(children)):
                node.pn = disproof_min(children)
                node.dpn = proof_sum(children)
                self.putintable(node)
                return

            proof = max(proof, disproof_min(children))
            child = self.select_child(children, proof)
            if node.dpn > proof_sum(children) and (
                    child.pn <= child.dpn
                    or node.pn <= disproof_min(children)):
                if self.e: child.pn *= (1 + self.e)
                else: child.pn += 1
            else:
                if self.e: child.dpn *= (1 + self.e)
                else: child.dpn += 1
            # Second level search
            if self.second_level and (not self.in_table(child)):
                res, size = self.second_level(child)
                if child.node_type == "OR":
                    child.pn = res.pn
                    child.dpn = res.dpn
                else:
                    child.dpn = res.pn
                    child.pn = res.dpn
                self.putintable(child, size=size)
            else:
                self.expand(child)
Ejemplo n.º 3
0
    def expand(self, node, pn_threshold):
        c = self.findtable(node)
        # IF node already solved or pn exceeds threshold
        if c == 0 or c > pn_threshold:
            node.pn = c
            return
        # Initialize PN as 1
        #if node.pn == None: node.pn = 1

        # If node has no successors
        # check if game is finished
        self.evaluate_node(node)
        result = node.value
        if result == 0:
            node.pn = float('inf')
            self.putintable(node, pn_threshold)
            return
        elif result == 1:
            node.pn = 0
            self.putintable(node, pn_threshold)
            return
        # Stored in transposition table to detect cycles
        self.putintable(node, pn_threshold)

        if node.node_type == "OR":
            # Recursive call of successor and nodes
            min_child = float('inf')
            for a in node.state.allowed_actions():
                new_state = node.state.perform_action(a)
                child_node = Node(node_type="AND",
                                  state=new_state,
                                  parent=node,
                                  depth=node.depth + 1,
                                  action=a)
                self.expand(child_node, pn_threshold)
                min_child = min(min_child, child_node.pn)
                if child_node.pn == 0:
                    break
            node.pn = min_child
            self.putintable(node, pn_threshold)
            return

        if node.node_type == "AND":
            # Dynamic evaluation
            child_pn = []
            for a in node.state.allowed_actions():
                new_state = node.state.perform_action(a)
                child_node = Node(node_type="OR",
                                  state=new_state,
                                  parent=node,
                                  depth=node.depth + 1,
                                  action=a)
                entry = self.findtable(child_node)
                child_pn.append(entry)
            if sum(child_pn) > pn_threshold:
                node.pn = sum(child_pn)
                self.putintable(node, pn_threshold)
                return

            # The recursive call of the successor OR nodes
            for i, a in enumerate(node.state.allowed_actions()):
                new_state = node.state.perform_action(a)
                # Recursive iterative deepening
                child_node = Node(node_type="OR",
                                  state=new_state,
                                  parent=node,
                                  depth=node.depth + 1,
                                  action=a)
                child_node.pn = 1
                while child_node.pn != 0:
                    self.expand(child_node, child_node.pn)
                    # in case child is solved
                    if child_node.pn == 0: break

                    # if unsolved within threshold
                    child_pn[i] = child_node.pn
                    if sum(child_pn) > pn_threshold:
                        node.pn = sum(child_pn)
                        self.putintable(node, pn_threshold)
                        return

            # All successor OR nodes of node n are solved
            node.pn = 0
            self.putintable(node, pn_threshold)
            return