<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _is_converged(self, operation):
 """ Checks whether the calibration has converged or not. At convergence the sepset belief would be precisely the sepset marginal. Parameters operation: str ('marginalize' | 'maximize') The operation to do for passing messages between nodes. if operation == marginalize, it checks whether the junction tree is calibrated or not else if operation == maximize, it checks whether the juction tree is max calibrated or not Formally, at convergence or at calibration this condition would be satisified for .. math:: \sum_{C_i - S_{i, j}} \beta_i = \sum_{C_j - S_{i, j}} \beta_j = \mu_{i, j} and at max calibration this condition would be satisfied .. math:: \max_{C_i - S_{i, j}} \beta_i = \max_{C_j - S_{i, j}} \beta_j = \mu_{i, j} """

        # If no clique belief, then the clique tree is not calibrated
        if not self.clique_beliefs:
            return False

        for edge in self.junction_tree.edges():
            sepset = frozenset(edge[0]).intersection(frozenset(edge[1]))
            sepset_key = frozenset(edge)
            if (edge[0] not in self.clique_beliefs or edge[1] not in self.clique_beliefs or
                    sepset_key not in self.sepset_beliefs):
                return False

            marginal_1 = getattr(self.clique_beliefs[edge[0]], operation)(list(frozenset(edge[0]) - sepset),
                                                                          inplace=False)
            marginal_2 = getattr(self.clique_beliefs[edge[1]], operation)(list(frozenset(edge[1]) - sepset),
                                                                          inplace=False)
            if marginal_1 != marginal_2 or marginal_1 != self.sepset_beliefs[sepset_key]:
                return False
        return True