Esempio n. 1
0
    def test_nomatch2(self):
        c1 = {
            0: -46.0,
            1: -46.5,
            2: -55.5,
            3: -56.0,
            4: -56.5,
            5: -65.5,
            6: -66.0,
            7: -66.5,
            8: -67.0,
            9: -67.5,
        }
        c2 = {
            0: 0.0,
            1: 0.0,
            2: 0.0,
            3: 0.0,
            4: 0.0,
            5: 0.0,
            6: 0.0,
            7: 0.0,
            8: 0.0,
            9: 0.0,
        }

        self.assertFalse(approx_match(c1, c2, 0.1))
Esempio n. 2
0
    def _on_maxsum_msg(self, factor_name, msg, t):
        """
        Handling cost message from a neighbor factor.

        Parameters
        ----------
        factor_name: str
            the name of that factor that sent us this message.
        msg: MaxSumMessage
            a message whose content is a map { d -> cost } where:
            * d is a value from the domain of this variable
            * cost if the minimum cost of the factor when taking value d
        """
        self._costs[factor_name] = msg.costs

        # select our value
        self.value_selection(
            *maxsum.select_value(self.variable, self._costs, self.mode))

        # Compute and send our own costs to all other factors.
        # If our variable has his own costs, we must sent them back even
        # to the factor which sent us this message, as integrated costs are
        # similar to an unary factor and with an unary factor we would have
        # sent these costs back to the original sender:
        # factor -> variable -> unary_cost_factor -> variable -> factor
        for f_name in self._factors:
            if f_name == factor_name:
                continue
            costs_f = maxsum.costs_for_factor(self.variable, f_name,
                                              self._factors, self._costs)
            prev_costs, count = self._prev_messages[f_name]

            # Apply damping to computed costs:
            if self.damping_nodes in ["vars", "both"]:
                costs_f = maxsum.apply_damping(costs_f, prev_costs,
                                               self.damping)

            # Check if there was enough change to send the message
            if not maxsum.approx_match(costs_f, prev_costs,
                                       self.stability_coef):
                # Not same as previous : send
                self.logger.debug(
                    f"Sending first time from variable {self.name} -> {f_name} : {costs_f}"
                )
                self.post_msg(f_name, maxsum.MaxSumMessage(costs_f))
                self._prev_messages[f_name] = costs_f, 1

            elif count < maxsum.SAME_COUNT:
                # Same as previous, but not yet sent SAME_COUNT times: send
                self.logger.debug(
                    f"Sending {count} time from variable {self.name} -> {f_name} : {costs_f}"
                )
                self.post_msg(f_name, maxsum.MaxSumMessage(costs_f))
                self._prev_messages[f_name] = costs_f, count + 1
            else:
                # Same and already sent SAME_COUNT times: no-send
                self.logger.debug(
                    f"Not sending (similar) from {self.name} -> {f_name} : {costs_f}"
                )
Esempio n. 3
0
    def _on_maxsum_msg(self, var_name, msg, t):
        """
        Handling messages from variables nodes.

        :param var_name: name of the variable node that sent this messages
        :param msg: the cost sent by the variable var_name
        a d -> cost table, where
          * d is a value from the domain of var_name
          * cost is the sum of the costs received from all other factors
            except f for this value d for the domain.
        """
        self._costs[var_name] = msg.costs

        # Wait until we received costs from all our variables before sending
        # our own costs (if works without doing that, but results are worse)
        if len(self._costs) == len(self.factor.dimensions):
            for v in self.variables:
                if v.name != var_name:
                    costs_v = maxsum.factor_costs_for_var(
                        self.factor, v, self._costs, self.mode)

                    prev_costs, count = self._prev_messages[v.name]

                    # Apply damping to computed costs:
                    if self.damping_nodes in ["factors", "both"]:
                        costs_v = maxsum.apply_damping(costs_v, prev_costs,
                                                       self.damping)

                    # Check if there was enough change to send the message
                    if not maxsum.approx_match(costs_v, prev_costs,
                                               self.stability_coef):
                        # Not same as previous : send
                        self.logger.debug(
                            f"Sending first time from factor {self.name} -> {v.name} : {costs_v}"
                        )
                        self.post_msg(v.name, maxsum.MaxSumMessage(costs_v))
                        self._prev_messages[v.name] = costs_v, 1

                    elif count < maxsum.SAME_COUNT:
                        # Same as previous, but not yet sent SAME_COUNT times: send
                        self.logger.debug(
                            f"Sending {count} time from variable {self.name} -> {v.name} : {costs_v}"
                        )
                        self.post_msg(v.name, maxsum.MaxSumMessage(costs_v))
                        self._prev_messages[v.name] = costs_v, count + 1
                    else:
                        # Same and already sent SAME_COUNT times: no-send
                        self.logger.debug(
                            f"Not sending (similar) from {self.name} -> {v.name} : {costs_v}"
                        )

        else:
            self.logger.debug(
                f" Still waiting for costs from all  the variables {self._costs.keys()}"
            )
Esempio n. 4
0
    def _match_previous(self, f_name, costs):
        """
        Check if a cost message for a factor f_name match the previous message
        sent to that factor.

        :param f_name: factor name
        :param costs: costs sent to this factor
        :return:
        """
        prev_costs, count = self._prev_messages[f_name]
        if prev_costs is not None:
            same = maxsum.approx_match(costs, prev_costs)
            return same, count
        else:
            return False, 0
Esempio n. 5
0
    def test_nomatch(self):
        c1 = {0: 0, 1: 0, 2: 0}
        c2 = {0: 0, 1: 1, 2: 0}

        self.assertFalse(approx_match(c1, c2, 0.1))
Esempio n. 6
0
    def test_match_exact(self):
        c1 = {0: 0, 1: 0, 2: 0}
        c2 = {0: 0, 1: 0, 2: 0}

        self.assertTrue(approx_match(c1, c2, 0.1))