Esempio n. 1
0
    def assert_disequality(self, i, coeff, j):
        """
        Adds the equality "ti != coeff * tj"
        This should never be called directly; rather, assert_comparison should be used.
        """
        # Print this now, in case the disequality is superseded; we want to see this first.
        self.announce_comparison(i, terms.NE, coeff, j)

        superseded = False
        if (i, j) in self.inequalities:
            for c in self.inequalities[i, j]:
                comp = c.to_comp(terms.IVar(i), terms.IVar(j))
                comp1, coeff1 = comp.comp, comp.term2.coeff
                if coeff1 == coeff:
                    if comp1 == terms.GE:
                        self.assert_inequality(i, terms.GT, coeff, j)
                        superseded = True
                    elif comp1 == terms.LE:
                        self.assert_inequality(i, terms.LT, coeff, j)
                        superseded = True

        if not superseded:
            if (i, j) in self.disequalities:
                if coeff not in self.disequalities[i, j]:
                    self.disequalities[i, j].add(coeff)
            else:
                self.disequalities[i, j] = {coeff}

            self.update_clause(i, j)
            self.tracker.update((i, j))
Esempio n. 2
0
    def info_dump(self):
        """
        For debugging purposes.
        Prints out all information known by the Blackboard.
        """
        st = '\n******\n'
        for i in self.term_defs:
            st += '{0!s} := {1!s}\n'.format(terms.IVar(i), self.term_defs[i])

        for i in self.zero_equalities:
            st += '{0!s} = 0\n'.format(terms.IVar(i))

        for i in self.zero_inequalities:
            st += '{0!s} {1!s} 0\n'.format(
                terms.IVar(i), terms.comp_str[self.zero_inequalities[i]])

        for i in self.zero_disequalities:
            st += '{0!s} != 0\n'.format(terms.IVar(i))

        for (i, j) in sorted(self.equalities.keys()):
            st += '{0!s} = {1!s}\n'.format(
                terms.IVar(i), self.equalities[i, j] * terms.IVar(j))

        for (i, j) in sorted(self.inequalities.keys()):
            for c in self.inequalities[i, j]:
                if c.a != 0 and c.b != 0:
                    st += str(c.to_comp(terms.IVar(i), terms.IVar(j))) + '\n'

        for (i, j) in sorted(self.disequalities.keys()):
            for val in self.disequalities[i, j]:
                st += '{0!s} != {1!s}\n'.format(terms.IVar(i),
                                                val * terms.IVar(j))

        st += '\n******\n'
        return st
Esempio n. 3
0
def one_comparison_to_comparison(c, B):
    """
    Converts a one comparison to a blackboard comparison between IVars, or None if
    the comparison is not of that form.
    """
    p = c.term
    l = len(p.args)
    comp = terms.GT if c.strong else terms.GE
    if l == 0:
        #print c
        #return mul_util.process_mul_comp(mulpair_one, mulpair_one, p.coeff, comp, B)
        return terms.comp_eval[comp](
            terms.IVar(0),
            mul_util.round_coeff(fractions.Fraction(1, p.coeff), comp) *
            terms.IVar(0))

        #assert c.strong  # comparisons 1 >= 1 should have been eliminated
        #return p.coeff*terms.IVar(0) > 0
#        return None
    if l == 1:
        m = multiplicand_to_mulpair(p.args[0])
        return mul_util.process_mul_comp(m, mulpair_one, p.coeff, comp, B)


#        return None
    elif l == 2:
        m1 = multiplicand_to_mulpair(p.args[0])
        m2 = multiplicand_to_mulpair(p.args[1])
        return mul_util.process_mul_comp(m1, m2, p.coeff, comp, B)
    else:
        return None
Esempio n. 4
0
 def get_equalities(self):
     """
     Returns a list of equalities t_i == c*t_j or ti == 0. Does not include definitional eqs.
     """
     equalities = [terms.IVar(i) == 0 for i in self.zero_equalities]
     for p in self.equalities:
         coeff = self.equalities[p]
         equalities.append(terms.IVar(p[0]) == coeff * terms.IVar(p[1]))
     return equalities
Esempio n. 5
0
 def raise_contradiction(self, i, comp, coeff, j):
     """
     Called when the given information contradicts something already known.
     """
     msg = 'Contradiction: {0!s}\n'.format(
         terms.TermComparison(terms.IVar(i), comp, coeff * terms.IVar(j)))
     msg += '  := {0!s}'.format(
         terms.TermComparison(self.terms[i], comp, coeff * self.terms[j]))
     raise terms.Contradiction(msg)
Esempio n. 6
0
def derive_info_from_definitions(B):
    def mulpair_sign(p):
        if p.exponent % 2 == 0:
            return GT if B.implies(p.term.index, terms.NE, 0, 0) else GE
            # return 1 if B.sign(p.term.index) != 0 else 0
        else:
            s = B.zero_inequalities.get(p.term.index, None)
            return comp_to_sign[s] if s is not None else 0
            # return B.sign(p.term.index)

    # def weak_mulpair_sign(p):
    #     if p.exponent % 2 == 0:
    #         return 1
    #     else:
    #         return B.weak_sign(p.term.index)

    for key in (k for k in B.term_defs if isinstance(B.term_defs[k], terms.MulTerm)):
        #signs = [mulpair_sign(p) for p in B.term_defs[key].args]
        #s = reduce(lambda x, y: x*y, signs)

        if any((B.implies(p.term.index, terms.EQ, 0, 0) and p.exponent >= 0)
               for p in B.term_defs[key].args):  # This term is 0 * something else.
            B.assert_comparison(terms.IVar(key) == 0)

        if B.implies(key, terms.NE, 0, 0) and all((p.exponent > 0 or
                                                       B.implies(p.term.index, terms.NE, 0, 0))
                                                  for p in B.term_defs[key].args):
            # we have strict information about key already. So everything must have a strict sign.
            for p in B.term_defs[key].args:
                #print 'from {0} != 0, we get {1} != 0'.format(B.term_defs[key], p.term)
                B.assert_comparison(p.term != 0)

        signs = [mulpair_sign(p) for p in B.term_defs[key].args]
        unsigned = [i for i in range(len(signs)) if signs[i] == 0]
        if B.weak_sign(key) != 0:
            if len(unsigned) == 0:
                s = reduce(lambda x, y: x*y, signs)
                B.assert_comparison(terms.comp_eval[sign_to_comp[s.dir, s.strong]](terms.IVar(key),
                                                                                   0))

            if len(unsigned) == 1:
                ind = unsigned[0]
                s = reduce(lambda x, y: x*y, [signs[i] for i in range(len(signs)) if i is not ind],
                           GT)
                if s.dir == B.weak_sign(key):
                    # remaining arg is pos
                    dir = terms.GT if B.sign(key) != 0 else terms.GE
                else:
                    dir = terms.LT if B.sign(key) != 0 else terms.LE
                B.assert_comparison(terms.comp_eval[dir](B.term_defs[key].args[ind].term, 0))

        elif len(unsigned) == 0:
            # we don't know any information about the sign of key.
            s = reduce(lambda x, y: x*y, signs)
            B.assert_comparison(terms.comp_eval[sign_to_comp[s.dir, s.strong]](terms.IVar(key), 0))
Esempio n. 7
0
 def get_disequalities(self):
     """
     Returns a list of disequalities t_i != c*t_j or t_i != 0.
     """
     disequalities = [terms.IVar(i) != 0 for i in self.zero_disequalities]
     for p in self.disequalities:
         coeff_list = self.disequalities[p]
         for coeff in coeff_list:
             disequalities.append(
                 terms.IVar(p[0]) != coeff * terms.IVar(p[1]))
     return disequalities
Esempio n. 8
0
 def abs_of(i):
     """
     Assuming abs_present(i), returns an expression equal to abs(t_i).
     """
     if B.weak_sign(i) == 1:
         return terms.IVar(i)
     elif B.weak_sign(i) == -1:
         return terms.IVar(i) * -1
     else:
         return terms.IVar(
             next(j for j in abs_indices if abs_arg_index(j) == i))
Esempio n. 9
0
 def announce_comparison(self, i, comp, coeff, j):
     """
     Reports a successful assertion to the user.
     """
     if messages.visible(messages.ASSERTION):
         messages.announce_strong('Asserting {0!s}'.format(
             terms.TermComparison(terms.IVar(i), comp,
                                  coeff * terms.IVar(j))))
     if messages.visible(messages.ASSERTION_FULL):
         messages.announce_strong('  := {0!s}'.format(
             terms.TermComparison(self.terms[i], comp,
                                  coeff * self.terms[j])))
Esempio n. 10
0
 def assert_zero_equality(self, i):
     """
     Adds the equality "ti = 0"
     This should never be called directly; rather, assert_comparison should be used.
     """
     for k in self.zero_equalities:
         self.assert_comparison(terms.IVar(i) == terms.IVar(k))
     self.zero_equalities.add(i)
     # todo: there's a lot of simplification that could happen if a term is equal to 0
     self.announce_zero_comparison(i, terms.EQ)
     self.update_clause(i)
     self.tracker.update(i)
Esempio n. 11
0
 def get_inequalities(self):
     """
     Returns a list of comparisons t_i <> c*t_j or t_i <> 0.
     """
     inequalities = []
     for i in self.zero_inequalities:
         comp = self.zero_inequalities[i]
         inequalities.append(terms.comp_eval[comp](terms.IVar(i), 0))
     for (i, j) in self.inequalities:
         for hp in self.inequalities[i, j]:
             if hp.a != 0 and hp.b != 0:
                 inequalities.append(
                     hp.to_comp(terms.IVar(i), terms.IVar(j)))
     return inequalities
Esempio n. 12
0
 def term_name(self, ti):
     """
     Assumes ti is a canonized term without IVars. Returns an IVar that represents t, if
     there is one. If not, recursively creates indices representing t and all its subterms, as
     needed.
     """
     t = self.expand_term(ti)
     if isinstance(t, terms.IVar):
         return t
     if t.key in self.term_names:
         return terms.IVar(self.term_names[t.key])
     else:
         if isinstance(t, terms.Var):
             new_def = t
         elif isinstance(t, terms.AddTerm):
             new_def = terms.AddTerm([
                 terms.STerm(a.coeff, self.term_name(a.term))
                 for a in t.args
             ])
         elif isinstance(t, terms.MulTerm):
             new_def = terms.MulTerm([
                 terms.MulPair(self.term_name(a.term), a.exponent)
                 for a in t.args
             ])
         elif isinstance(t, terms.FuncTerm):
             new_def = t.func(*[
                 terms.STerm(a.coeff, self.term_name(a.term))
                 for a in t.args
             ])
             #new_def = terms.FuncTerm(t.func_name, [terms.STerm(a.coeff, self.term_name(a.term))
             #                                        for a in t.args])
         else:
             print isinstance(t, terms.STerm)
             raise Error('cannot create name for {0!s}'.format(t))
         i = self.num_terms  # index of the new term
         self.term_defs[i] = new_def
         self.terms[i] = t
         self.term_names[t.key] = i
         self.num_terms += 1
         if messages.visible(messages.DEF):
             messages.announce_strong('Defining t{0!s} := {1!s}'.format(
                 i, new_def))
         if messages.visible(messages.DEF_FULL):
             messages.announce_strong('  := {1!s}'.format(i, t))
         for j in self.zero_inequalities:
             hp = geometry.halfplane_of_comp(self.zero_inequalities[j], 0)
             self.inequalities[j, i] = [hp]
         return terms.IVar(i)
Esempio n. 13
0
 def expand_term(self, ti):
     """
     Expands a term with IVars into its full definition.
     """
     return ti.substitute(
         {terms.IVar(i).key: self.terms[i]
          for i in range(self.num_terms)})
Esempio n. 14
0
    def assert_comparison(self, c):
        """
        Take an instance of terms.TermComparison, and adds the comparison to the blackboard.
        If the comparison terms are not both IVars, finds or creates indices for the terms.
        """
        c = c.canonize()  # c is now of the form "term comp sterm"

        term1, comp, coeff, term2 = c.term1, c.comp, c.term2.coeff, c.term2.term
        if coeff == 0:
            term2 = terms.IVar(0)
        if not isinstance(term1, terms.IVar) or not isinstance(
                term2, terms.IVar):
            ivar1 = term1 if isinstance(term1,
                                        terms.IVar) else self.term_name(term1)
            ivar2 = term2 if isinstance(term2,
                                        terms.IVar) else self.term_name(term2)
            c = terms.TermComparison(ivar1, comp, coeff * ivar2).canonize()
            term1, comp, coeff, term2 = c.term1, c.comp, c.term2.coeff, c.term2.term
            if coeff == 0:
                term2 = terms.IVar(0)

        if self.implies(term1.index, comp, coeff, term2.index):
            return
        elif self.implies(term1.index, terms.comp_negate(comp), coeff,
                          term2.index):
            self.raise_contradiction(term1.index, comp, coeff, term2.index)

        if comp in (terms.GE, terms.GT, terms.LE, terms.LT):
            if coeff == 0:
                self.assert_zero_inequality(term1.index, comp)
            else:
                self.assert_inequality(term1.index, comp, coeff, term2.index)
        elif comp == terms.EQ:
            if coeff == 0:
                self.assert_zero_equality(term1.index)
            else:
                self.assert_equality(term1.index, coeff, term2.index)
        elif comp == terms.NE:
            if coeff == 0:
                self.assert_zero_disequality(term1.index)
            else:
                self.assert_disequality(term1.index, coeff, term2.index)
        else:
            raise Error('Unrecognized comparison: {0!s}'.format())
Esempio n. 15
0
def instantiate(axiom, used_envs, B):
    """
    Given an Axiom object, finds appropriate instantiations by unifying with B.
    Returns a list of clauses.
    """
    # Get a list of assignments that work for all of axiom's triggers.
    envs = unify(B, axiom.triggers, list(axiom.vars),
                 list(axiom.trig_arg_vars))
    messages.announce(' Environments:', messages.DEBUG)
    for e in envs:
        messages.announce('  ' + str(e), messages.DEBUG)

    # For each assignment, use it to instantiate a Clause from axiom and assert it in B.
    clauses = []
    astr = str(axiom)
    for env in [e for e in envs if (axiom, str(e)) not in used_envs]:
        literals = []
        for l in axiom.literals:
            comp = l.comp
            red = reduce_term(l.term1, env)[0].canonize()
            red_coeff, red_term = red.coeff, red.term
            try:
                lcoeff, lterm = find_problem_term(B, red_term)
                lcoeff *= red_coeff
            except NoTermException:
                lterm = B.term_name(red.term).index
                lcoeff = red.coeff

            red = reduce_term(l.term2.term, env)[0].canonize()
            red_coeff, red_term = red.coeff, red.term
            try:
                rcoeff, rterm = find_problem_term(B, red.term)
                rcoeff *= l.term2.coeff * red_coeff
            except NoTermException:
                #sred = red.canonize()
                rterm = B.term_name(red.term).index
                rcoeff = red.coeff * l.term2.coeff

            literals.append(terms.comp_eval[comp](lcoeff * terms.IVar(lterm),
                                                  rcoeff * terms.IVar(rterm)))
        clauses.append(literals)
        used_envs.add((axiom, str(env)))
    return clauses
Esempio n. 16
0
def exp_factor_both(B):
    """
    Adds axioms of the form exp(c1 * t1 + ... + cn * tn) = exp(t1)^c1 * ... * exp(tn)^cn (also
    when n = 1).
    """
    exp_inds = [i for i in range(B.num_terms) if (isinstance(B.term_defs[i], terms.FuncTerm)
                                                  and B.term_defs[i].func == terms.exp)]

    for i in exp_inds:
        coeff, t = B.term_defs[i].args[0].coeff, B.term_defs[B.term_defs[i].args[0].term.index]
        if isinstance(t, terms.AddTerm):
            margs = [B.term_name((terms.exp(a) ** coeff).canonize().term) for a in t.args]
            t2 = reduce(lambda x, y: x*y, margs, 1).canonize()
            n = B.term_name(t2.term)
            B.assert_comparison(terms.IVar(i) == t2.coeff * n)
        elif coeff != 1:
            term2 = (terms.exp(t)**coeff).canonize()
            n = B.term_name(term2.term)
            B.assert_comparison(terms.IVar(i) == term2.coeff * n)
Esempio n. 17
0
    def update_blackboard(self, B):
        """
        Checks the blackboard B for function terms with equal arguments, and asserts that the
        function terms are equal.
        """
        def eq_func_terms(f1, f2):
            """
            Returns true if f1 and f2 have the same name and arity, and all args are equal.
            """
            if f1.func_name != f2.func_name or len(f1.args) != len(f2.args):
                return False
            for i in range(len(f1.args)):
                arg1, arg2 = f1.args[i], f2.args[i]
                if arg1.coeff == 0:
                    eq = B.implies(arg2.term.index, terms.EQ, 0,
                                   0) or arg2.coeff == 0
                else:
                    eq = B.implies(arg1.term.index, terms.EQ,
                                   fractions.Fraction(arg2.coeff, arg1.coeff),
                                   arg2.term.index)
                if not eq:
                    return False
            return True

        timer.start(timer.CCM)
        messages.announce_module('congruence closure module')

        func_classes = {}
        for i in (d for d in range(B.num_terms)
                  if isinstance(B.term_defs[d], terms.FuncTerm)):
            name = B.term_defs[i].func_name
            func_classes[name] = func_classes.get(name, []) + [i]

        for name in func_classes:
            tinds = func_classes[name]
            for (i, j) in itertools.combinations(tinds, 2):
                # ti and tj are function terms with the same symbols. check if they're equal.
                f1, f2 = B.term_defs[i], B.term_defs[j]
                if eq_func_terms(f1, f2):
                    B.assert_comparison(terms.IVar(i) == terms.IVar(j))
        timer.stop(timer.CCM)
Esempio n. 18
0
def get_additive_information(B):
    """
    Retrieves the relevant information from the blackboard.
    """
    comparisons = B.get_inequalities() + B.get_equalities()

    for key in B.term_defs:
        if isinstance(B.term_defs[key], terms.AddTerm):
            comparisons.append(
                terms.TermComparison(B.term_defs[key], terms.EQ, terms.IVar(key))
            )

    return comparisons
Esempio n. 19
0
def exp_factor_constant(B):
    """
    Takes a Blackboard B. For each i,
    If B.term_defs[i] is of the form exp(c*t), will declare that it is equal to exp(t)**c
    """
    exp_inds = [i for i in range(B.num_terms) if (isinstance(B.term_defs[i], terms.FuncTerm)
                                                  and B.term_defs[i].func == terms.exp)]
    for i in exp_inds:
        exponent = B.term_defs[i].args[0]
        if exponent.coeff != 1:
            term2 = (terms.exp(exponent.term)**exponent.coeff).canonize()
            n = B.term_name(term2.term)
            B.assert_comparison(terms.IVar(i) == term2.coeff * n)
Esempio n. 20
0
def log_factor_exponent(B):
    """
    Takes a Blackboard B. Looks for terms of the form log(t**e), and asserts that they are equal to
    e*log(t).
    """
    log_inds = [i for i in range(B.num_terms) if (isinstance(B.term_defs[i], terms.FuncTerm)
                                                  and B.term_defs[i].func == terms.log)]

    for i in log_inds:
        coeff, t = B.term_defs[i].args[0].coeff, B.term_defs[B.term_defs[i].args[0].term.index]
        if (coeff == 1 and isinstance(t, terms.MulTerm)
             and len(t.args) == 1 and t.args[0].exponent != 1 and t.args[0].exponent != 0
            and B.implies_zero_comparison(t.args[0].term.index, terms.GT)):
            B.assert_comparison(terms.IVar(i) == t.args[0].exponent * terms.log(t.args[0].term))
Esempio n. 21
0
def reduce_mul_term(t):
    """
    Takes a MulTerm t in which variables t_j could appear multiple times: t_j^3 * t_j^-2 * t_j^-1
    Since t_j is assumed to be positive, combines these so that each t_j appears once
    """
    inds = set(a.term.index for a in t.args)
    ind_lists = [[i for i in range(len(t.args)) if t.args[i].term.index == j] for j in inds]
    rt = terms.One()
    for l in ind_lists:
        exp = sum(t.args[k].exponent for k in l)
        if exp != 0:
            rt *= t.args[l[0]].term ** exp
    if isinstance(rt, terms.One):
        return terms.IVar(0)
    return rt
Esempio n. 22
0
    def implies_comparison(self, c):
        """
        Takes an instance of terms.TermComparison, and assume the comparison canonizes to
        a comparison between IVars. Determines whether the comparison is implied by
        information in the blackboard.
        """
        c = c.canonize()

        term1, comp, coeff, term2 = c.term1, c.comp, c.term2.coeff, c.term2.term
        if coeff == 0:
            term2 = terms.IVar(0)
        if isinstance(term1, terms.IVar) and isinstance(term2, terms.IVar):
            return self.implies(term1.index, comp, coeff, term2.index)
        else:
            return False
Esempio n. 23
0
def get_additive_information(B):
    """
    Retrieves known additive comparisons and inequalities from the blackboard B.
    """
    zero_equalities = [
        equality_to_zero_equality(c) for c in B.get_equalities()
    ]
    zero_comparisons = [
        inequality_to_zero_comparison(c) for c in B.get_inequalities()
    ]
    # convert each definition ti = s0 + s1 + ... + sn to a zero equality
    for i in range(B.num_terms):
        if isinstance(B.term_defs[i], terms.AddTerm):
            zero_equalities.append(cast_to_sum(terms.IVar(i) - B.term_defs[i]))
    return zero_equalities, zero_comparisons
Esempio n. 24
0
def reduce_term(term, env):
    """
    env maps UVar indices to (coeff, IVar index) pairs.
    Replaces all defined UVars in term with their designated values.
    Returns a pair of a new STerm and a flag whether all UVars have been replaced.
    """
    # TODO: this duplicates some functionality of Term.substitute(), but adds the check for UVars.
    # can we recover this some other way?
    if isinstance(term, terms.STerm):
        l = reduce_term(term.term, env)
        return terms.STerm(term.coeff * l[0].coeff, l[0].term), l[1]
    if isinstance(term, terms.UVar):
        if term.index in env:
            c, j = env[term.index]
            return terms.STerm(c, terms.IVar(j)), True
        else:
            return terms.STerm(1, term), False

    elif isinstance(term, terms.Atom):
        return terms.STerm(1, term), True

    elif isinstance(term, terms.AddTerm):
        rfunc = lambda (s1, flag1), (s2, flag2): (s1 + s2, flag1 and flag2)
        t = reduce(rfunc, [(lambda a:
                            (ap.coeff * a[0], a[1]))(reduce_term(ap.term, env))
                           for ap in term.args])
        return terms.STerm(1, t[0]), t[1]
    elif isinstance(term, terms.MulTerm):
        rfunc = lambda (s1, flag1), (s2, flag2): (s1 * s2, flag1 and flag2)
        t = reduce(rfunc,
                   [(lambda a:
                     (a[0]**mp.exponent, a[1]))(reduce_term(mp.term, env))
                    for mp in term.args])
        return terms.STerm(1, t[0]), t[1]
    elif isinstance(term, terms.FuncTerm):
        flag1 = True
        nargs = []
        for a in term.args:
            t = reduce_term(a.term, env)
            s, flag2 = t[0], t[1]
            nargs.append(a.coeff * s)
            flag1 = flag1 and flag2
        #return terms.STerm(1, terms.FuncTerm(term.func_name, nargs)), flag1
        return terms.STerm(1, term.func(*nargs)), flag1

    else:
        raise Exception('Unknown term type encountered in reduce_term: ' +
                        str(term))
Esempio n. 25
0
def log_factor_product(B):
    """
    Takes a Blackboard and looks for terms of the form log(a*b*...).
    Asserts that they are equal to log(a)+log(b)+...
    """
    def is_pos(mulpair):
        return (B.implies_zero_comparison(mulpair.term.index, terms.GT) or
            (mulpair.exponent % 2 == 0 and B.implies_zero_comparison(mulpair.term.index, terms.NE)))

    log_inds = [i for i in range(B.num_terms) if (isinstance(B.term_defs[i], terms.FuncTerm)
                                                  and B.term_defs[i].func == terms.log)]
    for i in log_inds:
        coeff, t = B.term_defs[i].args[0].coeff, B.term_defs[B.term_defs[i].args[0].term.index]
        if coeff == 1 and isinstance(t, terms.MulTerm) and all(is_pos(a) for a in t.args):
            margs = [terms.log(p.term**p.exponent) for p in t.args]
            t2 = reduce(lambda x, y: x+y, margs, 0).canonize()
            B.assert_comparison(terms.IVar(i) == t2)
Esempio n. 26
0
def exp_factor_sum(B):
    """
    Takes a Blackboard and a list of IVar indices, s.t. i in exp_inds implies B.term_defs[i] is an
    exponential function.
    Asserts a number of comparisons to B.
    If B.term_defs[i] is of the form exp(t_1 + ct_2 + ...), will declare that it is equal to
    exp(t_1)*exp(ct_2)*...
    """

    exp_inds = [i for i in range(B.num_terms) if (isinstance(B.term_defs[i], terms.FuncTerm)
                                                  and B.term_defs[i].func == terms.exp)]
    for i in exp_inds:
        coeff, t = B.term_defs[i].args[0].coeff, B.term_defs[B.term_defs[i].args[0].term.index]
        if isinstance(t, terms.AddTerm) and coeff == 1:
            margs = [B.term_name(terms.exp(a).canonize().term) for a in t.args]
            t2 = reduce(lambda x, y: x*y, margs, 1).canonize()
            n = B.term_name(t2.term)
            B.assert_comparison(terms.IVar(i) == t2.coeff * n)
Esempio n. 27
0
def zero_comparison_to_comparison(c):
    """
    Converts a zero comparison to a blackboard comparison between IVars, or None if
    the comparison is not of that form.
    """
    s = c.term
    l = len(s.args)
    if l == 0:
        assert c.strong  # comparisons 0 >= 0 should have been eliminated
        return terms.IVar(
            0) < 0  # TODO: is the a better way of returning a contradiction?
    if l == 1:
        t = summand_to_sterm(s.args[0])
        return t > 0 if c.strong else t >= 0
    elif l == 2:
        t1 = summand_to_sterm(s.args[0])
        t2 = summand_to_sterm(s.args[1])
        return t1 > -t2 if c.strong else t1 >= -t2
    else:
        return None
Esempio n. 28
0
def get_multiplicative_information(B):
    """
    Retrieves the relevant information from the blackboard.
    Filters to only comparisons and equations where sign information is known, and converts to
    absolute value form.
    Note: in the returned comparisons, t_j represents |t_j|
    """

    comparisons = []
    for c in (c for c in B.get_inequalities() + B.get_equalities()
              if c.term2.coeff != 0):
        ind1 = c.term1.index
        ind2 = c.term2.term.index
        if B.sign(ind1) != 0 and B.sign(ind2) != 0:
            comparisons.append(make_term_comparison_abs(c, B))

    for key in B.term_defs:
        if (isinstance(B.term_defs[key], terms.MulTerm) and B.sign(key) != 0 and
                all(B.sign(p.term.index) != 0 for p in B.term_defs[key].args)):
            lhs, rhs = reduce_mul_term(B.term_defs[key]), terms.IVar(key)
            comparisons.append(
                terms.TermComparison(lhs, terms.EQ, rhs)
            )
    return comparisons
Esempio n. 29
0
def multiplicand_to_mulpair(m):
    return terms.MulPair(terms.IVar(m.index), m.exp)
Esempio n. 30
0
    Retrieves known multiplicative equalities and inequalities from the blackboard B.
    """
    m_comparisons = mul_util.get_multiplicative_information(B)
    # Each ti in m_comparisons really represents |t_i|.
    one_equalities = [
        equality_to_one_equality(c) for c in m_comparisons
        if c.comp == terms.EQ
    ]
    one_comparisons = [
        inequality_to_one_comparison(c) for c in m_comparisons
        if c.comp in (terms.GT, terms.GE, terms.LT, terms.LE)
    ]
    return one_equalities, one_comparisons


mulpair_one = terms.MulPair(terms.IVar(0), 1)


def one_equality_to_comparison(e, B):
    """
    Converts an equation e == 0 to a blackboard comparison between IVars, or None if
    the equation is not of that form. Restores sign information from the Blackboard.
    """
    l = len(e.args)
    if l == 1:
        m = multiplicand_to_mulpair(e.args[0])
        return mul_util.process_mul_comp(m, mulpair_one, e.coeff, terms.EQ, B)
    elif l == 2:
        m1 = multiplicand_to_mulpair(e.args[0])
        m2 = multiplicand_to_mulpair(e.args[1])
        return mul_util.process_mul_comp(m1, m2, e.coeff, terms.EQ, B)