Exemplo n.º 1
0
    def on_start(self):

        if self.is_leaf and not self.is_root:
            # If we are a leaf in the DFS Tree we can immediately compute
            # our util and send it to our parent.
            # Note: as a leaf, our separator is the union of our parents and
            # pseudo-parents
            util = self._compute_utils_msg()
            self.logger.info(
                f"Leaf {self._variable.name} init message {self._variable.name} -> {self._parent} : {util}"
            )
            msg = DpopMessage("UTIL", util)
            self.post_msg(self._parent, msg)

        elif self.is_leaf:
            # we are both root and leaf : means we are a isolated variable we
            #  can select our own value alone:
            if self._constraints:
                for r in self._constraints:
                    self._joined_utils = join(self._joined_utils, r)

                values, current_cost = find_arg_optimal(
                    self._variable, self._joined_utils, self._mode)

                self.select_value_and_finish(values[0], float(current_cost))
            else:
                # If the variable is not constrained, we can simply take a value at
                # random:
                value = choice(self._variable.domain)
                self.select_value_and_finish(value, 0.0)
Exemplo n.º 2
0
    def _compute_utils_msg(self):

        for r in self._constraints:
            self._joined_utils = join(self._joined_utils, r)

        # use projection to eliminate self out of the message to our parent
        util = projection(self._joined_utils, self._variable, self._mode)

        return util
Exemplo n.º 3
0
    def on_start(self):

        if self.is_leaf and not self.is_root:
            # If we are a leaf in the DFS Tree we can immediately compute
            # our util and send it to our parent.
            # Note: as a leaf, our separator is the union of our parents and
            # pseudo-parents
            util = self._compute_utils_msg()
            self.logger.info(
                f"Leaf {self._variable.name} init message {self._variable.name} -> {self._parent} : {util}"
            )
            msg = DpopMessage("UTIL", util)
            self.post_msg(self._parent, msg)

        elif self.is_leaf:
            # we are both root and leaf : means we are a isolated variable we
            #  can select our own value alone:
            if self._constraints:
                for r in self._constraints:
                    self._joined_utils = join(self._joined_utils, r)

                values, current_cost = find_arg_optimal(
                    self._variable, self._joined_utils, self._mode
                )

                self.select_value_and_finish(values[0], float(current_cost))
            elif hasattr(self._variable, "cost_for_val"):
                # The variable has no constraint with other variable but has a cost function,
                # (i.e a unary constraint) : select the value that optimize that constraint.

                self.logger.debug(
                    f"Selecting value for {self._variable.name} based only on cost function"
                )
                values, current_cost = find_arg_optimal(
                    self._variable, self._joined_utils, self._mode
                )
                self.select_value_and_finish(values[0], float(current_cost))

            else:
                # If the variable is not constrained, we can simply take a value at
                # random:
                self.logger.debug(
                    f"Selecting random value for {self._variable.name} (not constrained)"
                )
                value = choice(self._variable.domain)
                self.select_value_and_finish(value, 0.0)
Exemplo n.º 4
0
    def _on_util_message(self, variable_name, recv_msg, t) -> None:
        """
        Message handler for UTIL messages.

        Parameters
        ----------
        variable_name: str
            name of the variable that sent the message
        recv_msg: DpopMessage
            received message
        t: int
            message timestamp

        """
        self.logger.debug(
            f"UTIL from {variable_name} : {recv_msg.content} at {t}")
        utils = recv_msg.content

        # accumulate util messages until we got the UTIL from all our children
        self._joined_utils = join(self._joined_utils, utils)
        try:
            self._waited_children.remove(variable_name)
        except ValueError as e:
            self.logger.error(
                f"Unexpected UTIL message from {variable_name} on {self.name} : {recv_msg} "
            )
            raise e
        # keep a reference of the separator of this children, we need it when
        # computing the value message
        self._children_separator[variable_name] = utils.dimensions

        if len(self._waited_children) == 0:

            if self.is_root:
                # We are the root of the DFS tree and have received all utils
                # we can select our own value and start the VALUE phase.

                # The root obviously has no parent nor pseudo parent, yet it
                # may have unary relations (with it-self!)
                for r in self._constraints:
                    self._joined_utils = join(self._joined_utils, r)

                values, current_cost = find_arg_optimal(
                    self._variable, self._joined_utils, self._mode)
                selected_value = values[0]

                self.logger.info(
                    f"ROOT: On UTIL from {variable_name}, send VALUE to childrens {self._children} "
                )
                for c in self._children:
                    msg = DpopMessage("VALUE",
                                      ([self._variable], [selected_value]))
                    self.post_msg(c, msg)

                self.select_value_and_finish(selected_value,
                                             float(current_cost))
            else:
                # We have received the Utils msg from all our children, we can
                # now compute our own utils relation by joining the accumulated
                # util with the relations with our parent and pseudo_parents.
                util = self._compute_utils_msg()
                msg = DpopMessage("UTIL", util)
                self.logger.info(
                    f"On UTIL from {variable_name}, send UTIL to parent {self._parent} "
                )
                self.post_msg(self._parent, msg)