示例#1
0
 def _add_sum_constraint(self, atom):
     if not isinstance(atom, ConstraintAtom):
         sum_con = ConstraintAtom.copy(atom)
     else:
         sum_con = atom
     for con in self._sum_constraints:
         if str(con) == str(sum_con):
             return con.literal
     if sum_con.literal is None:
         new_lit = self._add_atom()
         sum_con.literal = new_lit
     if self._appconfig.print_trans:
         print()
         print("% Adding sum constraint:", atom)
         print()
     self._sum_constraints.add(sum_con)
     defined = []
     for element in sum_con.elements:
         for var in self.vars(element.terms[0]):
             def_lit = self._add_defined(var)
             defined.append(def_lit)
             self._add_rule([], [sum_con.literal, -def_lit])
     for var in self.vars(sum_con.guard[1]):
         def_lit = self._add_defined(var)
         self._add_rule([], [sum_con.literal, -def_lit])
         defined.append(def_lit)
     if match(sum_con.term.arguments[0], "head", 0):
         self._define_variables(sum_con)
     elif match(sum_con.term.arguments[0], "body", 0):
         new_lit = self._add_atom()
         self._add_rule([new_lit], [], True)
         defined.append(new_lit)
         self._add_rule([sum_con.literal], defined)
         sum_con.literal = new_lit
     return sum_con.literal
示例#2
0
 def _define_variables(self, atom):
     assert match(atom.term.arguments[0], "head", 0) and match(
         atom.term, "sum", 1) and not self.conditional(atom)
     for var in self.vars(atom.guard[1]):
         self._add_defined(var, [atom.literal])
     for element in atom.elements:
         reason = [atom.literal]
         for var in self.vars(element.terms[0]):
             if element.condition:
                 reason.append(element.condition_id)
             self._add_defined(var, reason)
示例#3
0
 def _translate_constraint(self, atom):
     if match(atom.term, "sum",
              1) and not self.conditional(atom) and atom.guard[0] in (
                  "=", "<", ">", "<=", ">=", "!="):
         self._add_sum_constraint(atom)
     elif self.conditional(atom):
         self._translate_conditional(atom)
     elif atom.guard[0] == "=:":
         self._translate_assignment(atom)
     elif match(atom.term, "max", 1):
         self._translate_max(atom)
     elif match(atom.term, "min", 1):
         self._translate_min(atom)
     elif match(atom.term, "in", 1):
         self._translate_in(atom)
     else:
         self._aux_constraints.add(ConstraintAtom.copy(atom))
示例#4
0
    def _translate_min(self, atom):
        assert not self.conditional(atom)
        if self._appconfig.print_trans:
            print()
            print("% Translating min aggregate:", atom)
            print()
        min_var = self._add_auxvar()
        min_def = self._add_defined(min_var)
        def_fact = False
        beta_lit = self._add_atom()
        for element in atom.elements:
            body = []
            for var in self.vars(element.terms[0]):
                body.append(self._add_defined(var))
            if not def_fact:
                if len(body) == 0:
                    def_fact = True
                self._add_defined(min_var, body)
            body.append(min_def)

            check_lit = self._add_atom()
            self._add_sum_constraint(
                ConstraintAtom([ConstraintElement([min_var], None, None)],
                               ["<=", element.terms[0]], check_lit,
                               SUM_TERM_BODY))
            self._add_rule([], [-check_lit])

            check_lit = self._add_atom()
            self._add_sum_constraint(
                ConstraintAtom([ConstraintElement([min_var], None, None)],
                               ["=", element.terms[0]], check_lit,
                               SUM_TERM_BODY))
            self._add_rule([beta_lit], [check_lit])
        self._add_rule([], [-beta_lit, min_def])

        type_term = ConstraintTerm("sum", None, [atom.term.arguments[0]],
                                   clingo.TheoryTermType.Function)
        eq_lit = self._add_sum_constraint(
            ConstraintAtom([ConstraintElement([min_var], None, None)],
                           atom.guard, None, type_term))
        if match(atom.term.arguments[0], "head", 0):
            self._add_rule([eq_lit], [atom.literal])
            self._add_rule([atom.literal], [eq_lit])
        elif match(atom.term.arguments[0], "body", 0):
            self._add_rule([atom.literal], [eq_lit, min_def])
示例#5
0
def _parse_dom_elem(term):
    if match(term, "..", 2):
        a = _evaluate_term(term.arguments[0])
        if a.type != clingo.SymbolType.Number:
            raise RuntimeError("Invalid Syntax")

        b = _evaluate_term(term.arguments[1])
        if b.type != clingo.SymbolType.Number:
            raise RuntimeError("Invalid Syntax")

        return (a.number, b.number + 1)

    a = _evaluate_term(term)
    if a.type != clingo.SymbolType.Number:
        raise RuntimeError("Invalid Syntax")

    return (a.number, a.number + 1)
示例#6
0
def _parse_show_elem(builder, term):
    if match(term, "/", 2):
        a = _evaluate_term(term.arguments[0])
        if a.type != clingo.SymbolType.Function or a.arguments:
            raise RuntimeError("Invalid Syntax")

        b = _evaluate_term(term.arguments[1])
        if b.type != clingo.SymbolType.Number:
            raise RuntimeError("Invalid Syntax")

        builder.show_signature(a.name, b.number)
    else:
        a = _evaluate_term(term)
        if a.type == clingo.SymbolType.Number:
            raise RuntimeError("Invalid Syntax")

        builder.show_variable(a)
示例#7
0
def parse_theory(builder, theory_atoms):
    """
    Parse the atoms in the given theory and pass them to the builder.
    """
    for atom in theory_atoms:
        is_sum = match(atom.term, "sum", 1)
        is_diff = match(atom.term, "diff", 1)
        if is_sum or is_diff:
            body = match(atom.term.arguments[0], "body", 0)
            _parse_constraint(builder, atom, is_sum, body)
        elif match(atom.term, "distinct", 0):
            _parse_distinct(builder, atom)
        elif match(atom.term, "show", 0):
            _parse_show(builder, atom)
        elif match(atom.term, "dom", 0):
            _parse_dom(builder, atom)
        elif match(atom.term, "minimize", 0):
            _parse_objective(builder, atom, 1)
        elif match(atom.term, "maximize", 0):
            _parse_objective(builder, atom, -1)
示例#8
0
 def vars(self, term):
     """
     Return all variables in a term.
     """
     if term.type == clingo.SymbolType.Number:
         return set()
     if match(term, "-", 2) or match(term, "+", 2) or match(
             term, "*", 2) or match(term, "..", 2):
         return self.vars(term.arguments[0]).union(
             self.vars(term.arguments[1]))
     if match(term, "-", 1) or match(term, "+", 1):
         return self.vars(term.arguments[0])
     if term.type in (clingo.TheoryTermType.Symbol,
                      clingo.TheoryTermType.Function,
                      clingo.TheoryTermType.Tuple):
         return {term}
     return set()
示例#9
0
    def _translate_conditional(self, atom):
        if self._appconfig.print_trans:
            print()
            print("% Translating conditionals:", atom)
            print()
        elements = []
        neutral = ZERO
        if match(atom.term, "sum", 1):
            neutral = ZERO
        elif match(atom.term, "min", 1):
            neutral = ConstraintTerm(None, self._propconfig.max_int, None,
                                     clingo.TheoryTermType.Number)
        elif match(atom.term, "max", 1):
            neutral = ConstraintTerm(None, self._propconfig.min_int, None,
                                     clingo.TheoryTermType.Number)
        for element in atom.elements:
            if element.condition_id:
                cond = element.condition_id
                aux_var = self._add_auxvar()
                terms = [aux_var]
                terms.extend(element.terms[1:])
                elements.append(ConstraintElement(terms, None, None))
                self._add_defined(aux_var)
                holds_def = [
                    self._add_defined(var)
                    for var in self.vars(element.terms[0])
                ]
                aux_var_elem = ConstraintElement([aux_var], None, None)
                holds_term = element.terms[0]
                holds = self._add_sum_constraint(
                    ConstraintAtom([aux_var_elem], ["=", holds_term], None,
                                   SUM_TERM_HEAD))
                nholds = self._add_sum_constraint(
                    ConstraintAtom([aux_var_elem], ["=", neutral], None,
                                   SUM_TERM_HEAD))
                body = [cond]
                body.extend(holds_def)
                self._add_rule([holds], body)

                body = [-cond]
                self._add_rule([nholds], body)

                body = [cond]
                body.append(self._defined[aux_var])
                self._add_rule([holds], body)

                body = [-cond]
                body.append(self._defined[aux_var])
                self._add_rule([nholds], body)

                self._add_rule([cond], [self._defined[aux_var]], True)
            else:
                elements.append(element)
        cond_free_lit = self._add_atom()
        type_term = ConstraintTerm(atom.term.name, None,
                                   [atom.term.arguments[0]],
                                   clingo.TheoryTermType.Function)
        self._add_rule([cond_free_lit], [atom.literal])
        self._add_rule([atom.literal], [cond_free_lit])
        self._translate_constraint(
            ConstraintAtom(elements, atom.guard, cond_free_lit, type_term))
示例#10
0
def _parse_constraint_elem(builder, term, is_sum):
    assert term is not None
    if not is_sum:
        if match(term, "-", 2):
            a = _evaluate_term(term.arguments[0])
            if a.type == clingo.SymbolType.Number:
                yield a.number, None
            else:
                yield 1, builder.add_variable(a)

            b = _evaluate_term(term.arguments[1])
            if b.type == clingo.SymbolType.Number:
                yield -b.number, None
            else:
                yield -1, builder.add_variable(b)

        else:
            raise RuntimeError("Invalid Syntax for difference constraint")

    else:
        if match(term, "+", 2):
            for co, var in _parse_constraint_elem(builder, term.arguments[0],
                                                  True):
                yield co, var
            for co, var in _parse_constraint_elem(builder, term.arguments[1],
                                                  True):
                yield co, var

        elif match(term, "-", 2):
            for co, var in _parse_constraint_elem(builder, term.arguments[0],
                                                  True):
                yield co, var
            for co, var in _parse_constraint_elem(builder, term.arguments[1],
                                                  True):
                yield -co, var

        elif match(term, "*", 2):
            lhs = list(_parse_constraint_elem(builder, term.arguments[0],
                                              True))
            for co_prime, var_prime in _parse_constraint_elem(
                    builder, term.arguments[1], True):
                for co, var in lhs:
                    if var is None:
                        yield co * co_prime, var_prime
                    elif var_prime is None:
                        yield co * co_prime, var
                    else:
                        raise RuntimeError(
                            "Invalid Syntax, only linear constraints allowed")

        elif match(term, "-", 1):
            for co, var in _parse_constraint_elem(builder, term.arguments[0],
                                                  True):
                yield -co, var

        elif match(term, "+", 1):
            for co, var in _parse_constraint_elem(builder, term.arguments[0],
                                                  True):
                yield co, var

        elif term.type == clingo.TheoryTermType.Number:
            yield term.number, None

        elif term.type in (clingo.TheoryTermType.Symbol,
                           clingo.TheoryTermType.Function,
                           clingo.TheoryTermType.Tuple):
            yield 1, builder.add_variable(_evaluate_term(term))

        else:
            raise RuntimeError("Invalid Syntax for linear constraint")