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))
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}" )
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()}" )
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
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))
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))