Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

## Ongoing

## v0.0.8

- - update `set_assign` to take a condition argument. `set_assign(VAR,E,C,LBL)`
will add `E` to `VAR` only when `COND` evaluates to true.
- add support for preferences in the propagator engine
- - swap argument order of `engine_request/2` to `engine_request(ENG,LBL)`
- - rename input predicate `engine_default(ENG)` to `engine_request(ENG)`
- - replace the `api` argument of `add_to_control` with `engine`; select Flat
CH with `engine=constraint_handler.engine.fch` instead of `api="fch"`.
- add `Engine` configurations and an `engine` argument to `add_to_control`; the
Expand Down
3 changes: 2 additions & 1 deletion docs/developer/fact-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ This page describes the EBNF grammar for the fact format used by the constraint

<set-atom> ::=
| "set_assign" "(" <variable> "," <expression> ")"
| "set_assign" "(" <variable> "," <expression> "," <label> ")"
| "set_assign" "(" <variable> "," <expression> "," <expression> ")"
| "set_assign" "(" <variable> "," <expression> "," <expression> "," <label> ")"
| "set_baseDomain" "(" <variable> "," <expression> ")"
| "set_baseDomain" "(" <variable> "," <expression> "," <label> ")"

Expand Down
5 changes: 4 additions & 1 deletion docs/reference/collections.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,19 +93,22 @@ value(set_name, ref(set, variable(set_name)))

### Assign

To add elements to a set, use the `set_assign/2` predicate:
To add elements to a set, use `set_assign/2` or `set_assign/3`. The optional condition must evaluate to `val(bool,true)` for the value to be added; `set_assign/2` defaults it to `val(bool,true)`.

#### Input

**[Declaration]**{.badge .declaration } **[Label Support]**{.badge .label-support }

```prolog
set_assign(Name, Value).
set_assign(Name, Value, Condition).
```

| Name | Description |
| :--- | :--- |
| `Name` | The unique identifier of the set to which the value will be added
| `Value` | The value to be added to the set. |
| `Condition` | Optional Boolean expression that controls whether `Value` is added. |

#### Output

Expand Down
2 changes: 1 addition & 1 deletion src/constraint_handler/PropagatorConstants.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class OptimizationStrength(enum.Enum):
OPTIMIZATION_STAGE_ATOM: Literal["__opt_stage__"] = "__opt_stage__"
OPTIMIZATION_HELPER_PROGRAM = f"""
% Optimization helper atoms
1{{{OPTIMIZATION_STAGE_ATOM}(1;2)}} 1 :- propagator_optimize_maximizeSum(_,_,_,CNAME), _engine(CNAME, propagator).
1{{{OPTIMIZATION_STAGE_ATOM}(1;2)}} 1 :- propagator_optimize_maximizeSum(_,_,_,CNAME), _engine(propagator,CNAME).
#heuristic {OPTIMIZATION_STAGE_ATOM}(1). [990,true]

% #show {OPTIMIZATION_STAGE_ATOM}/3.
Expand Down
62 changes: 31 additions & 31 deletions src/constraint_handler/arithmetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,91 +2,91 @@

import math

import constraint_handler.schemas.atom as atom
import constraint_handler.schemas.operators as operators
import constraint_handler.schemas.result as result
import constraint_handler.schemas.warning as warning
import constraint_handler.utils.common as common

NO_ERRORS: tuple[tuple[warning.Kind, str], ...] = ()


def evaluate_operator(o, args) -> atom.EvalResult:
def evaluate_operator(o, args) -> result.EvalResult:
foldable = {operators.ArithmeticOperator.add: sum, operators.ArithmeticOperator.mult: math.prod}
if o in foldable:
return atom.EvalResult(foldable[o](args), NO_ERRORS)
return result.EvalResult(foldable[o](args), NO_ERRORS)
assert args
if len(args) == 1:
val = args[0]
match o:
case operators.ArithmeticOperator.sqrt:
return atom.EvalResult(math.sqrt(val), NO_ERRORS)
return result.EvalResult(math.sqrt(val), NO_ERRORS)
case operators.ArithmeticOperator.cos:
return atom.EvalResult(math.cos(val), NO_ERRORS)
return result.EvalResult(math.cos(val), NO_ERRORS)
case operators.ArithmeticOperator.sin:
return atom.EvalResult(math.sin(val), NO_ERRORS)
return result.EvalResult(math.sin(val), NO_ERRORS)
case operators.ArithmeticOperator.tan:
return atom.EvalResult(math.tan(val), NO_ERRORS)
return result.EvalResult(math.tan(val), NO_ERRORS)
case operators.ArithmeticOperator.abs:
return atom.EvalResult(abs(val), NO_ERRORS)
return result.EvalResult(abs(val), NO_ERRORS)
case operators.ArithmeticOperator.acos:
return atom.EvalResult(math.acos(val), NO_ERRORS)
return result.EvalResult(math.acos(val), NO_ERRORS)
case operators.ArithmeticOperator.asin:
return atom.EvalResult(math.asin(val), NO_ERRORS)
return result.EvalResult(math.asin(val), NO_ERRORS)
case operators.ArithmeticOperator.atan:
return atom.EvalResult(math.atan(val), NO_ERRORS)
return result.EvalResult(math.atan(val), NO_ERRORS)
case operators.ArithmeticOperator.minus:
return atom.EvalResult(-val, NO_ERRORS)
return result.EvalResult(-val, NO_ERRORS)
case operators.ArithmeticOperator.ceil:
return atom.EvalResult(math.ceil(val), NO_ERRORS)
return result.EvalResult(math.ceil(val), NO_ERRORS)
case operators.ArithmeticOperator.floor:
return atom.EvalResult(math.floor(val), NO_ERRORS)
return result.EvalResult(math.floor(val), NO_ERRORS)
case operators.ArithmeticOperator.float_from_int:
return atom.EvalResult(float(val), NO_ERRORS)
return result.EvalResult(float(val), NO_ERRORS)
case operators.ArithmeticOperator.int_from_float:
return atom.EvalResult(int(val), NO_ERRORS)
return result.EvalResult(int(val), NO_ERRORS)
else:
lval = args[0]
rval = args[1]
match o:
case operators.ArithmeticOperator.sub:
return atom.EvalResult(lval - rval, NO_ERRORS)
return result.EvalResult(lval - rval, NO_ERRORS)
case operators.ArithmeticOperator.int_div:
if rval == 0:
return atom.EvalResult(
return result.EvalResult(
common.Bad.bad,
((warning.Expression(warning.ExpressionWarning.zeroDivisionError), f"{lval}/{rval}"),),
)
return atom.EvalResult(int(lval // rval), NO_ERRORS)
return result.EvalResult(int(lval // rval), NO_ERRORS)
case operators.ArithmeticOperator.float_div:
if rval == 0:
return atom.EvalResult(
return result.EvalResult(
common.Bad.bad,
((warning.Expression(warning.ExpressionWarning.zeroDivisionError), f"{lval}/{rval}"),),
)
return atom.EvalResult(lval / rval, NO_ERRORS)
return result.EvalResult(lval / rval, NO_ERRORS)
case operators.ArithmeticOperator.mod:
if rval == 0:
return atom.EvalResult(
return result.EvalResult(
common.Bad.bad,
((warning.Expression(warning.ExpressionWarning.zeroDivisionError), f"{lval}%{rval}"),),
)
return atom.EvalResult(lval % rval, NO_ERRORS)
return result.EvalResult(lval % rval, NO_ERRORS)
case operators.ArithmeticOperator.pow:
if rval == 0:
return atom.EvalResult(1, NO_ERRORS)
return result.EvalResult(1, NO_ERRORS)
if common.Bad.bad in args:
return atom.EvalResult(common.Bad.bad, NO_ERRORS)
return atom.EvalResult(lval ** rval, NO_ERRORS) # fmt: skip
return result.EvalResult(common.Bad.bad, NO_ERRORS)
return result.EvalResult(lval ** rval, NO_ERRORS) # fmt: skip
case operators.ArithmeticOperator.leq:
return atom.EvalResult(lval <= rval, NO_ERRORS)
return result.EvalResult(lval <= rval, NO_ERRORS)
case operators.ArithmeticOperator.lt:
return atom.EvalResult(lval < rval, NO_ERRORS)
return result.EvalResult(lval < rval, NO_ERRORS)
case operators.ArithmeticOperator.geq:
return atom.EvalResult(lval >= rval, NO_ERRORS)
return result.EvalResult(lval >= rval, NO_ERRORS)
case operators.ArithmeticOperator.gt:
return atom.EvalResult(lval > rval, NO_ERRORS)
return result.EvalResult(lval > rval, NO_ERRORS)

return atom.EvalResult(
return result.EvalResult(
common.Bad.bad,
((warning.Expression(warning.ExpressionWarning.notImplemented), f"{o}"),),
)
18 changes: 9 additions & 9 deletions src/constraint_handler/comparison.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import constraint_handler.schemas.atom as atom
import constraint_handler.schemas.expression as expression
import constraint_handler.schemas.operators as operators
import constraint_handler.schemas.result as result
import constraint_handler.schemas.warning as warning

NO_ERRORS: tuple[tuple[warning.Kind, str], ...] = ()


def evaluate_operator(o, args) -> atom.EvalResult:
def evaluate_operator(o, args) -> result.EvalResult:
match o:
case operators.ComparisonOperator.eq:
if len(args) != 2:
return atom.EvalResult(
return result.EvalResult(
expression.Bad.bad,
(
(
Expand All @@ -19,10 +19,10 @@ def evaluate_operator(o, args) -> atom.EvalResult:
),
),
)
return atom.EvalResult(args[0] == args[1], NO_ERRORS)
return result.EvalResult(args[0] == args[1], NO_ERRORS)
case operators.ComparisonOperator.neq:
if len(args) != 2:
return atom.EvalResult(
return result.EvalResult(
expression.Bad.bad,
(
(
Expand All @@ -31,15 +31,15 @@ def evaluate_operator(o, args) -> atom.EvalResult:
),
),
)
return atom.EvalResult(args[0] != args[1], NO_ERRORS)
return result.EvalResult(args[0] != args[1], NO_ERRORS)
case operators.ComparisonOperator.max:
assert len(args) # TODO
return atom.EvalResult(max(args), NO_ERRORS)
return result.EvalResult(max(args), NO_ERRORS)
case operators.ComparisonOperator.min:
assert len(args)
return atom.EvalResult(min(args), NO_ERRORS)
return result.EvalResult(min(args), NO_ERRORS)
case _:
return atom.EvalResult(
return result.EvalResult(
expression.Bad.bad,
((warning.Expression(warning.ExpressionWarning.notImplemented), f"comparison operator {o}"),),
)
22 changes: 11 additions & 11 deletions src/constraint_handler/conditional.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
import constraint_handler.schemas.atom as atom
import constraint_handler.schemas.expression as expression
import constraint_handler.schemas.operators as operators
import constraint_handler.schemas.result as result
import constraint_handler.schemas.warning as warning

NO_ERRORS: tuple[tuple[warning.Kind, str], ...] = ()


def evaluate_operator(o, args) -> atom.EvalResult:
def evaluate_operator(o, args) -> result.EvalResult:
match o:
case operators.ConditionalOperator.getOrElse:
return atom.EvalResult(args[0] if args[0] is not None else args[1], NO_ERRORS)
return result.EvalResult(args[0] if args[0] is not None else args[1], NO_ERRORS)
case operators.ConditionalOperator.IF:
if args[0] is expression.Bad.bad:
return atom.EvalResult(expression.Bad.bad, NO_ERRORS)
return result.EvalResult(expression.Bad.bad, NO_ERRORS)
if args[0] is True:
return atom.EvalResult(args[1], NO_ERRORS)
return atom.EvalResult(None, NO_ERRORS)
return result.EvalResult(args[1], NO_ERRORS)
return result.EvalResult(None, NO_ERRORS)
case operators.ConditionalOperator.ite:
assert len(args) == 3
if args[0] is None:
return atom.EvalResult(None, NO_ERRORS)
return result.EvalResult(None, NO_ERRORS)
if args[0] is expression.Bad.bad:
return atom.EvalResult(expression.Bad.bad, NO_ERRORS)
return atom.EvalResult(args[1] if args[0] else args[2], NO_ERRORS)
return result.EvalResult(expression.Bad.bad, NO_ERRORS)
return result.EvalResult(args[1] if args[0] else args[2], NO_ERRORS)
case operators.ConditionalOperator.hasValue:
return atom.EvalResult(args[0] is not None, NO_ERRORS)
return result.EvalResult(args[0] is not None, NO_ERRORS)
case _:
return atom.EvalResult(
return result.EvalResult(
expression.Bad.bad,
((warning.Expression(warning.ExpressionWarning.notImplemented), f"conditional operator {o}"),),
)
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,13 @@ _passed(defaultArgs,LBL,multimap_assign(X,EKEY,EVAL)) :- multimap_assign(X,EKEY,
%%%%% set atoms
#defined set_assign/2.
#defined set_assign/3.
#defined set_assign/4.
#defined set_baseDomain/2.
#defined set_baseDomain/3.

_passed(defaultArgs,_label_anonymous,set_assign(X,E)) :- set_assign(X,E).
_passed(defaultArgs,LBL,set_assign(X,E)) :- set_assign(X,E,LBL).
_passed(defaultArgs,_label_anonymous,set_assign(X,E,val(bool,true))) :- set_assign(X,E).
_passed(defaultArgs,_label_anonymous,set_assign(X,E,C)) :- set_assign(X,E,C).
_passed(defaultArgs,LBL,set_assign(X,E,C)) :- set_assign(X,E,C,LBL).
_passed(defaultArgs,_label_anonymous,set_baseDomain(X,V)) :- set_baseDomain(X,V).
_passed(defaultArgs,LBL,set_baseDomain(X,V)) :- set_baseDomain(X,V,LBL).

Expand Down Expand Up @@ -131,14 +133,3 @@ _passed(defaultArgs,LBL,preference_holds(E,K)) :- preference_holds(E,K,LBL).
_passed(defaultArgs,_label_anonymous,preference_variableValue(X,E,1)) :- preference_variableValue(X,E).
_passed(defaultArgs,_label_anonymous,preference_variableValue(X,E,K)) :- preference_variableValue(X,E,K).
_passed(defaultArgs,LBL,preference_variableValue(X,E,K)) :- preference_variableValue(X,E,K,LBL).

%%%%%% warning atoms
#defined warning_forbid/1.
#defined warning_forbid/2.
#defined warning_ignore/1.
#defined warning_ignore/2.

_passed(defaultArgs,_label_anonymous,warning_forbid(KIND,_internal(all))) :- warning_forbid(KIND).
_passed(defaultArgs,_label_anonymous,warning_forbid(KIND,LBL)) :- warning_forbid(KIND,LBL).
_passed(defaultArgs,_label_anonymous,warning_ignore(KIND,_internal(all))) :- warning_ignore(KIND).
_passed(defaultArgs,_label_anonymous,warning_ignore(KIND,LBL)) :- warning_ignore(KIND,LBL).
35 changes: 3 additions & 32 deletions src/constraint_handler/data/3_sugar/sugar.lp
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
%%%%%%%%%%%%%%%%% semantic expression atoms
_passed(sugar,LBL,bool_evaluate(E)) :- _passed(defaultArgs,LBL,bool_evaluate(E)).
_passed(sugar,LBL,share_value(E)) :- _passed(defaultArgs,LBL,bool_evaluate(E)).

_passed(sugar,LBL,ensure(E)) :- _passed(defaultArgs,LBL,ensure(E)).
_passed(sugar,LBL,share_value(E)) :- _passed(defaultArgs,LBL,ensure(E)).
_passed(sugar,LBL,share_value(E)) :- _passed(ssa,LBL,ensure(E)).

_passed(sugar,LBL,evaluate(E,E)) :- _passed(defaultArgs,LBL,evaluate(E)).
_passed(sugar,LBL,share_value(E)) :- _passed(defaultArgs,LBL,evaluate(E)).


_sugar_userVariable(LBL,X) :- _passed(defaultArgs,LBL,variable_declare(X,(boolDomain;definition;fromFacts;open;set;multimap))).

%%%%%% variable fromFacts atoms
_passed(sugar,LBL,variable_declare(X,D)) :- _passed(defaultArgs,LBL,variable_declare(X,D)), D=(definition;fromFacts;open;set;multimap).
Expand All @@ -20,45 +13,35 @@ _passed(sugar,LBL,variable_domain(X,val(bool,(false;true)))) :- _passed(defaultA
%%%%%% variable define
_passed(sugar,LBL,variable_declare(X,definition)) :- _passed(defaultArgs,LBL,variable_define(X,E)), not _defaultArgs_variableDeclared(X).
_passed(sugar,LBL,variable_define(X,E)) :- _passed(defaultArgs,LBL,variable_define(X,E)).
_sugar_userVariable(LBL,X) :- _passed(defaultArgs,LBL,variable_define(X,E)).

%%%%%% variable domain
_passed(sugar,LBL,variable_domain(X,E)) :- _passed(defaultArgs,LBL,variable_domain(X,E)).
_sugar_userVariable(LBL,X) :- _passed(defaultArgs,LBL,variable_domain(X,E)).

%%%%%% variable assign
_passed(sugar,LBL,variable_assign(X,E)) :- _passed(defaultArgs,LBL,variable_assign(X,E)).
_sugar_userVariable(LBL,X) :- _passed(defaultArgs,LBL,variable_assign(X,E)).

%%%%%% variable choice
_passed(sugar,LBL,variable_choice(X,E)) :- _passed(defaultArgs,LBL,variable_choice(X,E)).
_sugar_userVariable(LBL,X) :- _passed(defaultArgs,LBL,variable_choice(X,E)).

%%%%%% variable default
_passed(sugar,LBL,variable_default(X,D,C,P)) :- _passed(defaultArgs,LBL,variable_default(X,D,C,P)).
_sugar_userVariable(LBL,X) :- _passed(defaultArgs,LBL,variable_default(X,D,C,P)).


%%%%%% multimap atoms
_passed(sugar,LBL,multimap_assign(X,EKEY,EVAL)) :- _passed(defaultArgs,LBL,multimap_assign(X,EKEY,EVAL)).
_sugar_userVariable(LBL,X) :- _passed(defaultArgs,LBL,multimap_assign(X,EKEY,EVAL)).


%%%%%% set atoms
_passed(sugar,LBL,set_assign(X,E)) :- _passed(defaultArgs,LBL,set_assign(X,E)).
_passed(sugar,LBL,set_assign(X,E,C)) :- _passed(defaultArgs,LBL,set_assign(X,E,C)).
_passed(sugar,LBL,set_baseDomain(X,E)) :- _passed(defaultArgs,LBL,set_baseDomain(X,E)).

_sugar_userVariable(LBL,X) :- _passed(defaultArgs,LBL,set_assign(X,E)).
_sugar_userVariable(LBL,X) :- _passed(defaultArgs,LBL,set_baseDomain(X,E)).

%%%%%% optimize atoms
_sugar_aux(LBL,optimize_component(EXPR,E,PREC,ID,PRIO)) :-
_passed(defaultArgs,LBL,optimize_maximizeSum(E,ID,PRIO)),
_passed(defaultArgs,LBL2,optimize_precision(PREC,PRIO)),
EXPR=operation(floor,(operation(mult,(E,(PREC,()))),())).

_passed(sugar,LBL,optimize_component(E,O,P,ID,PRIORITY)) :- _sugar_aux(LBL,optimize_component(E,O,P,ID,PRIORITY)).
_passed(sugar,LBL,share_value(E;O;P)) :- _sugar_aux(LBL,optimize_component(E,O,P,ID,PRIORITY)).

%%%%%% preference atoms
_sugar_aux(LBL,preference_holds(operation(eq,(variable(X),(E,()))),K)) :- _passed(defaultArgs,LBL,preference_variableValue(X,E,K)), K > 0.
Expand All @@ -67,24 +50,12 @@ _sugar_aux(LBL,preference_holds(E,K)) :- _passed(defaultArgs,LBL,preference_hold
_sugar_aux(LBL,preference_holds(operation(wnot,(E,())),-K)) :- _passed(defaultArgs,LBL,preference_holds(E,K)), K < 0.

_passed(sugar,LBL,preference_holds(E,K)) :- _sugar_aux(LBL,preference_holds(E,K)).
_passed(sugar,LBL,share_value(E)) :- _sugar_aux(LBL,preference_holds(E,K)).

%%%%%% ssa atoms
_passed(sugar,LBL,DEC) :- _passed(ssa,LBL,DEC).
_variable(sugar,X) :- _variable(ssa,X).

_sugar_userVariable(LBL,X) :- _execution_inputVar(LBL,PRG,N,X).
_sugar_userVariable(LBL,X) :- _execution_outputVar(LBL,PRG,N,X).

%%%%%% warning atoms
_passed(sugar,LBL,warning_forbid(KIND,TARGET)) :- _passed(defaultArgs,LBL,warning_forbid(KIND,TARGET)).
_passed(sugar,LBL,warning_ignore(KIND,TARGET)) :- _passed(defaultArgs,LBL,warning_ignore(KIND,TARGET)).


%%%%%% interface variables
_passed(sugar,LBL,variable_interface(X)) :- _sugar_userVariable(LBL,X).

%%%%%% internal declarations
_passed(internal_declaration,LBL,variable_declare(X,DOM)) :- _passed(ssa,LBL,variable_declare(X,DOM)), _sugar_userVariable(LBL,X).
_passed(internal_declaration,LBL,variable_define(X,DEF)) :- _passed(ssa,LBL,variable_define(X,DEF)), _sugar_userVariable(LBL,X).
_passed(internal_declaration,LBL,variable_declare(X,DOM)) :- _passed(ssa,LBL,variable_declare(X,DOM)), _execution_outputVar(LBL,PRG,N,X).
_passed(internal_declaration,LBL,variable_define(X,DEF)) :- _passed(ssa,LBL,variable_define(X,DEF)), _execution_outputVar(LBL,PRG,N,X).
_passed(internal_declaration,LBL,ensure(E)) :- _passed(ssa,LBL,ensure(E)).
Loading
Loading