コード例 #1
0
 def _deep_copy_node(self, node, variable, current_depth, max_depth):
     if isinstance(node, CircuitTerminal):
         return node
     else:
         if len(node.elements) == 0:
             raise ValueError(
                 "Decision nodes should have at least one elements.")
         copied_elements = []
         for element in node.elements:
             copied_elements.append(
                 self._deep_copy_element(element, variable,
                                         current_depth + 1, max_depth))
         self._largest_index += 1
         return OrGate(self._largest_index, node.vtree, copied_elements)
コード例 #2
0
 def _copy_and_modify_node_for_split(self, original_node, variable,
                                     current_depth, max_depth):
     if original_node.num_parents == 0:
         raise ValueError("Some node does not have a parent.")
     original_node.decrease_num_parents_by_one()
     if isinstance(original_node, CircuitTerminal):
         if original_node.var_index == variable:
             if original_node.var_value == LITERAL_IS_TRUE:
                 copied_node = None
             elif original_node.var_value == LITERAL_IS_FALSE:
                 original_node = None
                 copied_node = self._terminal_nodes[self._num_variables +
                                                    variable - 1]
             else:
                 raise ValueError(
                     "Under the current setting,"
                     "we only support terminal nodes that are either positive or negative literals."
                 )
         else:
             copied_node = original_node
         return original_node, copied_node
     else:
         if original_node.num_parents > 0:
             original_node = self._deep_copy_node(original_node, variable,
                                                  current_depth, max_depth)
         copied_elements = []
         i = 0
         while i < len(original_node.elements):
             original_element, copied_element = self._copy_and_modify_element_for_split(
                 original_node.elements[i], variable, current_depth + 1,
                 max_depth)
             if original_element is None:
                 original_node.remove_element(i)
             else:
                 i += 1
             if copied_element is not None:
                 copied_elements.append(copied_element)
         if len(copied_elements) == 0:
             copied_node = None
         else:
             self._largest_index += 1
             copied_node = OrGate(self._largest_index, original_node.vtree,
                                  copied_elements)
         if len(original_node.elements) == 0:
             original_node = None
         return original_node, copied_node
コード例 #3
0
 def _new_logistic_psdd(self, vtree) -> CircuitNode:
     left_vtree = vtree.left
     right_vtree = vtree.right
     prime_variable = left_vtree.var
     sub_variable = right_vtree.var
     if left_vtree.is_leaf():
         left_node = self._precreated_terminal_nodes[prime_variable - 1]
     else:
         left_node = self._new_logistic_psdd(left_vtree)
     if right_vtree.is_leaf():
         right_node = self._precreated_terminal_nodes[sub_variable - 1]
     else:
         right_node = self._new_logistic_psdd(right_vtree)
     elements = [
         AndGate(left_node, right_node,
                 np.random.random_sample(size=(self._num_classes, )))
     ]
     elements[0].splittable_variables = copy.deepcopy(vtree.variables)
     root = OrGate(self._largest_index, vtree, elements)
     self._largest_index += 1
     return root
コード例 #4
0
    def load(self, f):
        # read the format at the beginning
        line = f.readline()
        while line[0] == "c":
            line = f.readline()

        # serialize the vtree
        vtree_nodes = dict()
        unvisited_vtree_nodes = deque()
        unvisited_vtree_nodes.append(self._vtree)
        while len(unvisited_vtree_nodes):
            node = unvisited_vtree_nodes.popleft()
            vtree_nodes[node.index] = node
            if not node.is_leaf():
                unvisited_vtree_nodes.append(node.left)
                unvisited_vtree_nodes.append(node.right)

        # extract the saved logistic circuit
        nodes = dict()
        line = f.readline()
        while line[0] == "T" or line[0] == "F" or line[0] == "S":
            line_as_list = line.strip().split(" ")
            literal_type, var = line_as_list[0], int(line_as_list[3])
            index, vtree_index = int(line_as_list[1]), int(line_as_list[2])
            parameters = []
            for i in range(self._num_classes):
                parameters.append(float(line_as_list[4 + i]))
            parameters = np.array(parameters, dtype=np.float64)
            if literal_type == "T":
                self._precreated_terminal_nodes[self._num_variables + var -
                                                1].parameter = parameters
                nodes[index] = (
                    self._precreated_terminal_nodes[self._num_variables + var -
                                                    1], {var})
            elif literal_type == "F":
                self._precreated_terminal_nodes[2 * self._num_variables + var -
                                                1].parameter = parameters
                nodes[index] = (
                    self._precreated_terminal_nodes[2 * self._num_variables +
                                                    var - 1], {-var})
            else:
                self._precreated_terminal_nodes[var - 1].parameter = parameters
                nodes[index] = (self._precreated_terminal_nodes[var - 1],
                                {-var})
            self._largest_index = max(self._largest_index, index)
            line = f.readline()
        self._terminal_nodes = [x[0] for x in nodes.values()]

        root = None
        while line[0] == "D":
            line_as_list = line.strip().split(" ")
            index, vtree_index, num_elements = int(line_as_list[1]), int(
                line_as_list[2]), int(line_as_list[3])
            elements = []
            variables = set()
            for i in range(num_elements):
                prime_index = int(line_as_list[i * (self._num_classes + 2) +
                                               4].strip("("))
                sub_index = int(line_as_list[i * (self._num_classes + 2) + 5])
                element_variables = nodes[prime_index][1].union(
                    nodes[sub_index][1])
                variables = variables.union(element_variables)
                splittable_variables = set()
                for variable in element_variables:
                    if -variable in element_variables:
                        splittable_variables.add(abs(variable))
                parameters = []
                for j in range(self._num_classes):
                    parameters.append(
                        float(line_as_list[i * (self._num_classes + 2) + 6 +
                                           j].strip(")")))
                parameters = np.array(parameters, dtype=np.float64)
                elements.append(
                    AndGate(nodes[prime_index][0], nodes[sub_index][0],
                            parameters))
                elements[-1].splittable_variables = splittable_variables
            nodes[index] = (OrGate(index, vtree_nodes[vtree_index],
                                   elements), variables)
            root = nodes[index][0]
            self._largest_index = max(self._largest_index, index)
            line = f.readline()

        if line[0] != "B":
            raise ValueError(
                "The last line in a circuit file must record the bias parameters."
            )
        self._bias = np.array([float(x) for x in line.strip().split(" ")[1:]],
                              dtype=np.float64)

        gc.collect()
        return root
コード例 #5
0
 def _new_logistic_psdd(self, vtree) -> CircuitNode:
     left_vtree = vtree.left
     right_vtree = vtree.right
     prime_variable = left_vtree.var
     sub_variable = right_vtree.var
     elements = list()
     if left_vtree.is_leaf() and right_vtree.is_leaf():
         elements.append(
             AndGate(
                 self._terminal_nodes[prime_variable - 1],
                 self._terminal_nodes[sub_variable - 1],
                 self.rand_gen.random_sample(size=(self._num_classes, )),
             ))
         elements.append(
             AndGate(
                 self._terminal_nodes[prime_variable - 1],
                 self._terminal_nodes[self._num_variables + sub_variable -
                                      1],
                 self.rand_gen.random_sample(size=(self._num_classes, )),
             ))
         elements.append(
             AndGate(
                 self._terminal_nodes[self._num_variables + prime_variable -
                                      1],
                 self._terminal_nodes[sub_variable - 1],
                 self.rand_gen.random_sample(size=(self._num_classes, )),
             ))
         elements.append(
             AndGate(
                 self._terminal_nodes[self._num_variables + prime_variable -
                                      1],
                 self._terminal_nodes[self._num_variables + sub_variable -
                                      1],
                 self.rand_gen.random_sample(size=(self._num_classes, )),
             ))
     elif left_vtree.is_leaf():
         elements.append(
             AndGate(
                 self._terminal_nodes[prime_variable - 1],
                 self._new_logistic_psdd(right_vtree),
                 self.rand_gen.random_sample(size=(self._num_classes, )),
             ))
         elements.append(
             AndGate(
                 self._terminal_nodes[self._num_variables + prime_variable -
                                      1],
                 self._new_logistic_psdd(right_vtree),
                 self.rand_gen.random_sample(size=(self._num_classes, )),
             ))
         for element in elements:
             element.splittable_variables = copy.deepcopy(
                 right_vtree.variables)
     elif right_vtree.is_leaf():
         elements.append(
             AndGate(
                 self._new_logistic_psdd(left_vtree),
                 self._terminal_nodes[sub_variable - 1],
                 self.rand_gen.random_sample(size=(self._num_classes, )),
             ))
         elements.append(
             AndGate(
                 self._new_logistic_psdd(left_vtree),
                 self._terminal_nodes[self._num_variables + sub_variable -
                                      1],
                 self.rand_gen.random_sample(size=(self._num_classes, )),
             ))
         for element in elements:
             element.splittable_variables = copy.deepcopy(
                 left_vtree.variables)
     else:
         elements.append(
             AndGate(
                 self._new_logistic_psdd(left_vtree),
                 self._new_logistic_psdd(right_vtree),
                 self.rand_gen.random_sample(size=(self._num_classes, )),
             ))
         elements[0].splittable_variables = copy.deepcopy(vtree.variables)
     root = OrGate(self._largest_index, vtree, elements)
     self._largest_index += 1
     return root
コード例 #6
0
    def load(self, f):
        # read the format at the beginning
        line = f.readline()
        while line[0] == "c":
            line = f.readline()

        # serialize the vtree
        vtree_nodes = dict()
        unvisited_vtree_nodes = deque()
        unvisited_vtree_nodes.append(self._vtree)
        while len(unvisited_vtree_nodes):
            node = unvisited_vtree_nodes.popleft()
            vtree_nodes[node.index] = node
            if not node.is_leaf():
                unvisited_vtree_nodes.append(node.left)
                unvisited_vtree_nodes.append(node.right)

        # extract the saved logistic circuit
        nodes = dict()
        line = f.readline()
        while line[0] == "T" or line[0] == "F":
            line_as_list = line.strip().split(" ")
            positive_literal, var = (line_as_list[0] == "T"), int(
                line_as_list[3])
            index, vtree_index = int(line_as_list[1]), int(line_as_list[2])
            parameters = []
            for i in range(self._num_classes):
                parameters.append(float(line_as_list[4 + i]))
            parameters = np.array(parameters, dtype=np.float64)
            if positive_literal:
                nodes[index] = (CircuitTerminal(index,
                                                vtree_nodes[vtree_index], var,
                                                LITERAL_IS_TRUE,
                                                parameters), {var})
            else:
                nodes[index] = (CircuitTerminal(index,
                                                vtree_nodes[vtree_index], var,
                                                LITERAL_IS_FALSE,
                                                parameters), {-var})
            self._largest_index = max(self._largest_index, index)
            line = f.readline()

        self._terminal_nodes = [x[0] for x in nodes.values()]
        self._terminal_nodes.sort(key=lambda x: (-x.var_value, x.var_index))
        if len(self._terminal_nodes) != 2 * self._num_variables:
            raise ValueError(
                "Number of terminal nodes recorded in the circuit file "
                "does not match 2 * number of variables in the provided vtree."
            )

        root = None
        while line[0] == "D":
            line_as_list = line.strip().split(" ")
            index, vtree_index, num_elements = int(line_as_list[1]), int(
                line_as_list[2]), int(line_as_list[3])
            elements = []
            variables = set()
            for i in range(num_elements):
                prime_index = int(line_as_list[i * (self._num_classes + 2) +
                                               4].strip("("))
                sub_index = int(line_as_list[i * (self._num_classes + 2) + 5])
                element_variables = nodes[prime_index][1].union(
                    nodes[sub_index][1])
                variables = variables.union(element_variables)
                splittable_variables = set()
                for variable in element_variables:
                    if -variable in element_variables:
                        splittable_variables.add(abs(variable))
                parameters = []
                for j in range(self._num_classes):
                    parameters.append(
                        float(line_as_list[i * (self._num_classes + 2) + 6 +
                                           j].strip(")")))
                parameters = np.array(parameters, dtype=np.float64)
                elements.append(
                    AndGate(nodes[prime_index][0], nodes[sub_index][0],
                            parameters))
                elements[-1].splittable_variables = splittable_variables
            nodes[index] = (OrGate(index, vtree_nodes[vtree_index],
                                   elements), variables)
            root = nodes[index][0]
            self._largest_index = max(self._largest_index, index)
            line = f.readline()

        if line[0] != "B":
            raise ValueError(
                "The last line in a circuit file must record the bias parameters."
            )
        self._bias = np.array([float(x) for x in line.strip().split(" ")[1:]],
                              dtype=np.float64)

        gc.collect()
        return root