From d7844fd1d81e36582ff1b6902adb3e6ebb63cae0 Mon Sep 17 00:00:00 2001 From: Abdallah Saffidine Date: Wed, 16 Sep 2026 19:15:14 +1000 Subject: [PATCH 01/18] merge engine_default and engine_request, and clean-up warning declaration passing --- CHANGES.md | 1 + .../1_default_arguments/default_arguments.lp | 11 ----------- src/constraint_handler/data/3_sugar/sugar.lp | 4 ---- src/constraint_handler/data/5_presolve/engine.lp | 7 ++++--- .../data/6_solve/propagator/README.md | 4 ++-- .../data/6_solve/propagator/propagator.lp | 5 ++--- src/constraint_handler/data/7_output/warning.lp | 16 ++++++++++++---- src/constraint_handler/main.py | 1 + tests/correctness/type/warning/python.lp | 3 --- tests/investigate/slowdown.1000.next.lp | 2 +- tests/investigate/slowdown.1000.yext.lp | 2 +- tests/investigate/slowdown.16.next.lp | 2 +- tests/investigate/slowdown.16.yext.lp | 2 +- tests/investigate/slowdown.17.next.lp | 2 +- tests/investigate/slowdown.17.yext.lp | 2 +- tests/test_api.py | 1 - 16 files changed, 28 insertions(+), 37 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 2d0703e8..357c2710 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,7 @@ ## Ongoing +- - 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 diff --git a/src/constraint_handler/data/1_default_arguments/default_arguments.lp b/src/constraint_handler/data/1_default_arguments/default_arguments.lp index ac2dc3a0..c2ace661 100644 --- a/src/constraint_handler/data/1_default_arguments/default_arguments.lp +++ b/src/constraint_handler/data/1_default_arguments/default_arguments.lp @@ -131,14 +131,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). diff --git a/src/constraint_handler/data/3_sugar/sugar.lp b/src/constraint_handler/data/3_sugar/sugar.lp index 70571017..fc6ef60d 100644 --- a/src/constraint_handler/data/3_sugar/sugar.lp +++ b/src/constraint_handler/data/3_sugar/sugar.lp @@ -76,10 +76,6 @@ _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). diff --git a/src/constraint_handler/data/5_presolve/engine.lp b/src/constraint_handler/data/5_presolve/engine.lp index eedc27c3..bfb62379 100644 --- a/src/constraint_handler/data/5_presolve/engine.lp +++ b/src/constraint_handler/data/5_presolve/engine.lp @@ -1,4 +1,4 @@ -#defined engine_default/1. +#defined engine_request/1. #defined engine_request/2. %%%%%%%%%%%%%%%%% engines @@ -6,8 +6,9 @@ _engine_supportOptimization(compile;compile2;ground;propagator). _engine(compile;compile2;ground;propagator;none). _engine_grounding(compile;compile2;ground). -_engine_default(ENG) :- engine_default(ENG), _engine(ENG). -_engine_defaultProvided :- engine_default(ENG), _engine(ENG). +_engine_default(ENG) :- engine_request(ENG,_label_anonymous), _engine(ENG). +_engine_default(ENG) :- engine_request(ENG), _engine(ENG). +_engine_defaultProvided :- engine_request(ENG), _engine(ENG). _engine_default(compile) :- not _engine_defaultProvided. _label(LBL) :- _label(LBL,DECL). diff --git a/src/constraint_handler/data/6_solve/propagator/README.md b/src/constraint_handler/data/6_solve/propagator/README.md index c0529504..e60b6a05 100644 --- a/src/constraint_handler/data/6_solve/propagator/README.md +++ b/src/constraint_handler/data/6_solve/propagator/README.md @@ -15,8 +15,8 @@ _passed(propagator,LBL,set_baseDomain/2). _passed(propagator,LBL,multimap_assign/3). _passed(propagator,LBL,optimize_component/5). _passed(propagator,LBL,share_value/1). -_passed(propagator,LBL,warning_forbid/2). -_passed(propagator,LBL,warning_ignore/2). +_warning_forbid/2. +_warning_ignore/2. ### Intermediate predicates diff --git a/src/constraint_handler/data/6_solve/propagator/propagator.lp b/src/constraint_handler/data/6_solve/propagator/propagator.lp index 2bc5ade0..9c8f16dd 100644 --- a/src/constraint_handler/data/6_solve/propagator/propagator.lp +++ b/src/constraint_handler/data/6_solve/propagator/propagator.lp @@ -50,8 +50,7 @@ propagator_multimap_declare(X,LBL) :- _passed(propagator,LBL,variable_declare(X, propagator_optimize_maximizeSum(E,ID,PRIO,LBL) :- _passed(propagator,LBL,optimize_component(E,ORIG,PREC,ID,PRIO)). propagator_share_value(E,LBL) :- _passed(propagator,LBL,share_value(E)). -propagator_warning_forbid(W,LBL) :- _passed(propagator,LBL,warning_forbid(W,_internal(all))). -propagator_warning_ignore(W,LBL) :- _passed(propagator,LBL,warning_ignore(W,_internal(all))). - +propagator_warning_forbid(KIND,LBL) :- _warning_forbid(KIND,LBL). +propagator_warning_ignore(KIND,LBL) :- _warning_ignore(KIND,LBL). propagator_variable_interface(X,LBL) :- _passed(propagator,LBL,variable_interface(X)). diff --git a/src/constraint_handler/data/7_output/warning.lp b/src/constraint_handler/data/7_output/warning.lp index 63e2d5df..1291121f 100644 --- a/src/constraint_handler/data/7_output/warning.lp +++ b/src/constraint_handler/data/7_output/warning.lp @@ -1,7 +1,15 @@ -_warning_forbid(KIND,INFO) :- _passed(sugar,LBL,warning_forbid(KIND,INFO)). -_warning_ignore(KIND,INFO) :- _passed(sugar,LBL,warning_ignore(KIND,INFO)). -_warning_raised(KIND,INFO) :- _warning(KIND,INFO,MSG), not _warning_ignore(KIND,INFO), not _warning_ignore(KIND,_internal(all)). -:- _warning_raised(KIND,INFO), _warning_forbid(KIND,_internal(all)). +#defined warning_forbid/1. +#defined warning_forbid/2. +#defined warning_ignore/1. +#defined warning_ignore/2. + +_warning_forbid(KIND,LBL) :- warning_forbid(KIND,LBL). +_warning_ignore(KIND,LBL) :- warning_ignore(KIND,LBL). +_warning_forbid(KIND,_label_anonymous) :- warning_forbid(KIND). +_warning_ignore(KIND,_label_anonymous) :- warning_ignore(KIND). + +_warning_raised(KIND,INFO) :- _warning(KIND,INFO,MSG), not _warning_ignore(KIND,INFO), not _warning_ignore(KIND,_label_anonymous). +:- _warning_raised(KIND,INFO), _warning_forbid(KIND,_label_anonymous). :- _warning_raised(KIND,INFO), _warning_forbid(KIND,INFO). warning_raised :- _warning_raised(KIND,INFO). warning(KIND,INFO,MSG) :- _warning(KIND,INFO,MSG), _warning_raised(KIND,INFO). diff --git a/src/constraint_handler/main.py b/src/constraint_handler/main.py index 3538a97c..39493198 100644 --- a/src/constraint_handler/main.py +++ b/src/constraint_handler/main.py @@ -55,6 +55,7 @@ ] + m4_variable_safety_checks m5_presolve = [ +# "5_presolve/core", "5_presolve/dispatch", "5_presolve/engine", "5_presolve/presolve", diff --git a/tests/correctness/type/warning/python.lp b/tests/correctness/type/warning/python.lp index ba7ae90d..140d21bf 100644 --- a/tests/correctness/type/warning/python.lp +++ b/tests/correctness/type/warning/python.lp @@ -19,6 +19,3 @@ variable_define(good_y,GEQ) :- GEQ = operation(geq,(variable(y),(val(int,1),()))). evaluate(operation(limp,(variable(active),(variable(good_y),())))). -#show value/2. -#show warning/3. -%warning_ignore(type(failed_operation)). diff --git a/tests/investigate/slowdown.1000.next.lp b/tests/investigate/slowdown.1000.next.lp index a0bb9b96..b7db21bf 100644 --- a/tests/investigate/slowdown.1000.next.lp +++ b/tests/investigate/slowdown.1000.next.lp @@ -8,7 +8,7 @@ variable_define(y,operation(add,(variable(x),(val(int,1),())))). ensure(max_domain_value,operation(eq,(variable(y),(val(int,int_domain_size+1),())))). -engine_default(propagator). +engine_request(propagator). #script (python) import constraint_handler diff --git a/tests/investigate/slowdown.1000.yext.lp b/tests/investigate/slowdown.1000.yext.lp index a03aad3a..0a69c3f7 100644 --- a/tests/investigate/slowdown.1000.yext.lp +++ b/tests/investigate/slowdown.1000.yext.lp @@ -8,7 +8,7 @@ variable_define(y,operation(add,(variable(x),(val(int,1),())))). ensure(max_domain_value,operation(eq,(variable(y),(val(int,int_domain_size+1),())))). -engine_default(propagator). +engine_request(propagator). #script (python) import constraint_handler diff --git a/tests/investigate/slowdown.16.next.lp b/tests/investigate/slowdown.16.next.lp index 2bfb7510..de369eaf 100644 --- a/tests/investigate/slowdown.16.next.lp +++ b/tests/investigate/slowdown.16.next.lp @@ -8,7 +8,7 @@ variable_define(y,operation(add,(variable(x),(val(int,1),())))). ensure(max_domain_value,operation(eq,(variable(y),(val(int,int_domain_size+1),())))). -engine_default(propagator). +engine_request(propagator). #script (python) import constraint_handler diff --git a/tests/investigate/slowdown.16.yext.lp b/tests/investigate/slowdown.16.yext.lp index e290c6c4..59f6e0fe 100644 --- a/tests/investigate/slowdown.16.yext.lp +++ b/tests/investigate/slowdown.16.yext.lp @@ -8,7 +8,7 @@ variable_define(y,operation(add,(variable(x),(val(int,1),())))). ensure(max_domain_value,operation(eq,(variable(y),(val(int,int_domain_size+1),())))). -engine_default(propagator). +engine_request(propagator). #script (python) import constraint_handler diff --git a/tests/investigate/slowdown.17.next.lp b/tests/investigate/slowdown.17.next.lp index d17c19e0..e795c0e2 100644 --- a/tests/investigate/slowdown.17.next.lp +++ b/tests/investigate/slowdown.17.next.lp @@ -8,7 +8,7 @@ variable_define(y,operation(add,(variable(x),(val(int,1),())))). ensure(max_domain_value,operation(eq,(variable(y),(val(int,int_domain_size+1),())))). -engine_default(propagator). +engine_request(propagator). #script (python) import constraint_handler diff --git a/tests/investigate/slowdown.17.yext.lp b/tests/investigate/slowdown.17.yext.lp index cd2a7b4f..ff6c470e 100644 --- a/tests/investigate/slowdown.17.yext.lp +++ b/tests/investigate/slowdown.17.yext.lp @@ -8,7 +8,7 @@ variable_define(y,operation(add,(variable(x),(val(int,1),())))). ensure(max_domain_value,operation(eq,(variable(y),(val(int,int_domain_size+1),())))). -engine_default(propagator). +engine_request(propagator). #script (python) import constraint_handler diff --git a/tests/test_api.py b/tests/test_api.py index d8e62bf7..f505c1c7 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -7,7 +7,6 @@ from clingo import Control, Symbol import constraint_handler -import constraint_handler.engine as engine def test_add_ctrl(): From 7051c288bc0635faebe7e558346f660e8d7b8ac1 Mon Sep 17 00:00:00 2001 From: Abdallah Saffidine Date: Thu, 17 Sep 2026 12:04:40 +1000 Subject: [PATCH 02/18] Split result atom schemas into their own file and add core atom schema file --- src/constraint_handler/arithmetic.py | 62 ++++++------ src/constraint_handler/comparison.py | 18 ++-- src/constraint_handler/conditional.py | 22 ++--- .../data/5_presolve/core.lp | 25 +++++ src/constraint_handler/evaluator.py | 50 +++++----- src/constraint_handler/logic.py | 52 +++++----- src/constraint_handler/main.py | 6 +- src/constraint_handler/multimap.py | 32 +++---- src/constraint_handler/post_processor.py | 6 +- src/constraint_handler/propagator.py | 20 ++-- src/constraint_handler/schemas/atom.py | 68 ++----------- src/constraint_handler/schemas/core.py | 95 +++++++++++++++++++ .../schemas/propagator_atom.py | 11 ++- src/constraint_handler/schemas/result.py | 65 +++++++++++++ src/constraint_handler/set.py | 56 +++++------ src/constraint_handler/string.py | 12 +-- tests/test_from_python.py | 13 ++- 17 files changed, 375 insertions(+), 238 deletions(-) create mode 100644 src/constraint_handler/data/5_presolve/core.lp create mode 100644 src/constraint_handler/schemas/core.py create mode 100644 src/constraint_handler/schemas/result.py diff --git a/src/constraint_handler/arithmetic.py b/src/constraint_handler/arithmetic.py index 6ddb4f86..ac5a1d28 100644 --- a/src/constraint_handler/arithmetic.py +++ b/src/constraint_handler/arithmetic.py @@ -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}"),), ) diff --git a/src/constraint_handler/comparison.py b/src/constraint_handler/comparison.py index 2a46df81..92eb5e1e 100644 --- a/src/constraint_handler/comparison.py +++ b/src/constraint_handler/comparison.py @@ -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, ( ( @@ -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, ( ( @@ -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}"),), ) diff --git a/src/constraint_handler/conditional.py b/src/constraint_handler/conditional.py index e88532cb..178da1c1 100644 --- a/src/constraint_handler/conditional.py +++ b/src/constraint_handler/conditional.py @@ -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}"),), ) diff --git a/src/constraint_handler/data/5_presolve/core.lp b/src/constraint_handler/data/5_presolve/core.lp new file mode 100644 index 00000000..d18c7b76 --- /dev/null +++ b/src/constraint_handler/data/5_presolve/core.lp @@ -0,0 +1,25 @@ +_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=bool_evaluate(E). +_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=ensure(E). +_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=evaluate(REF,E). +_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=variable_assign(X,E). +_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=variable_choice(X,E). +_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=variable_declare(X,D). +_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=variable_default(X,D,C,P). +_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=variable_define(X,E). +_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=variable_domain(X,E). +_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=set_assign(X,E). +_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=set_baseDomain(X,E). +_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=multimap_assign(X,K,B). +_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=share_value(E). +_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=optimize_component(E,O,P,X,PRIORITY). +_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=preference_holds(E,K). + + + +ch_core(engine_request(LBL,ENG)) :- engine_request(LBL,ENG). +%%%ch_core(engine_default(ENG)) :- engine_default(ENG). +%% ch_core(engine_request(LBL,ENG)). +%%%% ch_core(engine_default(ENG)). + +ch_core(warning_forbid(KIND,LBL)) :- warning_forbid(KIND,LBL). +ch_core(warning_ignore(KIND,LBL)) :- warning_ignore(KIND,LBL). diff --git a/src/constraint_handler/evaluator.py b/src/constraint_handler/evaluator.py index 1bbc1cb4..122fc755 100644 --- a/src/constraint_handler/evaluator.py +++ b/src/constraint_handler/evaluator.py @@ -11,9 +11,9 @@ import constraint_handler.logic as logic import constraint_handler.multimap as multimap import constraint_handler.myClorm as myClorm -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.statement as statement import constraint_handler.schemas.warning as warning import constraint_handler.set as myset @@ -159,10 +159,10 @@ def python_operator(fn, args, globals_id, locals_env): try: globals_ = get_environment(globals_id) call = eval(fn, globals_, locals_env) - return atom.EvalResult(call(*args), NO_ERRORS) + return result.EvalResult(call(*args), NO_ERRORS) except Exception as exn: kind = warning.Expression(warning.ExpressionWarning.pythonError) - return atom.EvalResult(None, ((kind, repr(exn)),)) + return result.EvalResult(None, ((kind, repr(exn)),)) @cache @@ -189,21 +189,21 @@ def cached_exec(stmt: str, vars_mapping: tuple, globals_id: myClorm.ImmutableLis def pythonExtract_operator(stmt: str, expr_code: str, vars_mapping: tuple, globals_id): succ, warns = cached_exec(stmt, vars_mapping, globals_id) if succ is None: - return atom.EvalResult(expression.Bad.bad, warns) + return result.EvalResult(expression.Bad.bad, warns) if expr_code == "__succeeds": - return atom.EvalResult(warns is not None, NO_ERRORS) + return result.EvalResult(warns is not None, NO_ERRORS) nested_locals = dict(succ) try: globals_env = get_environment(globals_id) - return atom.EvalResult( + return result.EvalResult( eval(get_compiled_eval(expr_code), globals_env, nested_locals), NO_ERRORS, ) except Exception as exn: kind = warning.Expression(warning.ExpressionWarning.pythonError) - return atom.EvalResult(expression.Bad.bad, ((kind, repr(exn)),)) + return result.EvalResult(expression.Bad.bad, ((kind, repr(exn)),)) def operator(o, args: tuple, globals_id, locals_env): @@ -212,14 +212,14 @@ def apply_nested_operator(inner_o, inner_args): match o: case expression.Bad.bad: - return atom.EvalResult(o, NO_ERRORS) + return result.EvalResult(o, NO_ERRORS) case expression.Python(fn): return python_operator(fn, args, globals_id, locals_env) case expression.PythonExtract(stmt, e): return pythonExtract_operator(stmt, e, args, globals_id) case expression.Lambda(vars, expr_body): if len(vars) != len(args): - return atom.EvalResult( + return result.EvalResult( expression.Bad.bad, ( ( @@ -250,9 +250,9 @@ def apply_nested_operator(inner_o, inner_args): return conditional.evaluate_operator(o, args) case _: if callable(o): - return atom.EvalResult(o(*args), NO_ERRORS) + return result.EvalResult(o(*args), NO_ERRORS) print(o, type(o)) - return atom.EvalResult( + return result.EvalResult( expression.Bad.bad, ((warning.Expression(warning.ExpressionWarning.notImplemented), f"operator {o}"),), ) @@ -266,43 +266,43 @@ def expr(expr_, globals_id, locals_env): o = op_result.value if expression.Bad.bad == eo or (expression.Bad.bad in args and o not in RECOVERABLE_OPERATORS): - return atom.EvalResult(expression.Bad.bad, op_result.errors + args_errors) + return result.EvalResult(expression.Bad.bad, op_result.errors + args_errors) applied = operator(o, args, globals_id, locals_env) - return atom.EvalResult(applied.value, op_result.errors + args_errors + applied.errors) + return result.EvalResult(applied.value, op_result.errors + args_errors + applied.errors) case expression.Variable(a): if a in locals_env: - return atom.EvalResult(locals_env[a], NO_ERRORS) - return atom.EvalResult( + return result.EvalResult(locals_env[a], NO_ERRORS) + return result.EvalResult( expression.Bad.bad, ((warning.Variable(warning.VariableWarning.undeclared), f"{a}"),), ) case expression.Python(code): try: globals_ = get_environment(globals_id) - return atom.EvalResult(eval(get_compiled_eval(code), globals_, locals_env), NO_ERRORS) + return result.EvalResult(eval(get_compiled_eval(code), globals_, locals_env), NO_ERRORS) except Exception as exn: kind = warning.Expression(warning.ExpressionWarning.pythonError) - return atom.EvalResult(expression.Bad.bad, ((kind, repr(exn)),)) + return result.EvalResult(expression.Bad.bad, ((kind, repr(exn)),)) case expression.Val(type_, val): - return atom.EvalResult(val, NO_ERRORS) + return result.EvalResult(val, NO_ERRORS) case expression.Lambda(vars, body): nsymbols = {x: v for x, v in locals_env.items() if x not in vars} - return atom.EvalResult(expression.Lambda(vars, beta_reduction(nsymbols, body)), NO_ERRORS) + return result.EvalResult(expression.Lambda(vars, beta_reduction(nsymbols, body)), NO_ERRORS) case o if isinstance(o, expression.Operator): - return atom.EvalResult(expr_, NO_ERRORS) + return result.EvalResult(expr_, NO_ERRORS) case tuple(eargs): values, errors = exprs(eargs, globals_id, locals_env) - return atom.EvalResult(tuple(values), errors) + return result.EvalResult(tuple(values), errors) case set(eargs) | frozenset(eargs): values, errors = exprs(eargs, globals_id, locals_env) - return atom.EvalResult(frozenset(values), errors) + return result.EvalResult(frozenset(values), errors) case None: - return atom.EvalResult(None, NO_ERRORS) + return result.EvalResult(None, NO_ERRORS) case expression.Bad.bad: - return atom.EvalResult(expr_, NO_ERRORS) + return result.EvalResult(expr_, NO_ERRORS) case _: - return atom.EvalResult( + return result.EvalResult( expression.Bad.bad, ((warning.Expression(warning.ExpressionWarning.notImplemented), f"expr {expr_}"),), ) diff --git a/src/constraint_handler/logic.py b/src/constraint_handler/logic.py index 8cf49209..062b0e86 100644 --- a/src/constraint_handler/logic.py +++ b/src/constraint_handler/logic.py @@ -3,70 +3,70 @@ import functools import operator -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: match o: case operators.LogicOperator.conj: if False in args: - return atom.EvalResult(False, NO_ERRORS) + return result.EvalResult(False, NO_ERRORS) if common.Bad.bad in args: - return atom.EvalResult(common.Bad.bad, NO_ERRORS) + return result.EvalResult(common.Bad.bad, NO_ERRORS) if None in args: - return atom.EvalResult(None, NO_ERRORS) - return atom.EvalResult(True, NO_ERRORS) + return result.EvalResult(None, NO_ERRORS) + return result.EvalResult(True, NO_ERRORS) case operators.LogicOperator.disj: if True in args: - return atom.EvalResult(True, NO_ERRORS) + return result.EvalResult(True, NO_ERRORS) if common.Bad.bad in args: - return atom.EvalResult(common.Bad.bad, NO_ERRORS) + return result.EvalResult(common.Bad.bad, NO_ERRORS) if None in args: - return atom.EvalResult(None, NO_ERRORS) - return atom.EvalResult(False, NO_ERRORS) + return result.EvalResult(None, NO_ERRORS) + return result.EvalResult(False, NO_ERRORS) case operators.LogicOperator.leqv: if None in args: - return atom.EvalResult(common.Bad.bad, NO_ERRORS) - return atom.EvalResult(functools.reduce(operator.eq, args, True), NO_ERRORS) + return result.EvalResult(common.Bad.bad, NO_ERRORS) + return result.EvalResult(functools.reduce(operator.eq, args, True), NO_ERRORS) case operators.LogicOperator.limp: assert len(args) == 2 if args[0] is False or args[1] is True: - return atom.EvalResult(True, NO_ERRORS) + return result.EvalResult(True, NO_ERRORS) if args[0] is True and args[1] is False: - return atom.EvalResult(False, NO_ERRORS) + return result.EvalResult(False, NO_ERRORS) if common.Bad.bad in args: - return atom.EvalResult(common.Bad.bad, NO_ERRORS) + return result.EvalResult(common.Bad.bad, NO_ERRORS) if None in args: - return atom.EvalResult(None, NO_ERRORS) - return atom.EvalResult( + return result.EvalResult(None, NO_ERRORS) + return result.EvalResult( common.Bad.bad, ((warning.Expression(warning.ExpressionWarning.evaluatorError), f"operation {o,args}"),) ) case operators.LogicOperator.lnot: assert len(args) == 1 if None in args: - return atom.EvalResult(None, NO_ERRORS) - return atom.EvalResult(not args[0], NO_ERRORS) + return result.EvalResult(None, NO_ERRORS) + return result.EvalResult(not args[0], NO_ERRORS) case operators.LogicOperator.lxor: if None in args: - return atom.EvalResult(common.Bad.bad, NO_ERRORS) - return atom.EvalResult(functools.reduce(operator.xor, args, False), NO_ERRORS) + return result.EvalResult(common.Bad.bad, NO_ERRORS) + return result.EvalResult(functools.reduce(operator.xor, args, False), NO_ERRORS) case operators.LogicOperator.snot: assert len(args) == 1 if None in args: - return atom.EvalResult(False, NO_ERRORS) - return atom.EvalResult(not args[0], NO_ERRORS) + return result.EvalResult(False, NO_ERRORS) + return result.EvalResult(not args[0], NO_ERRORS) case operators.LogicOperator.wnot: assert len(args) == 1 if None in args: - return atom.EvalResult(True, NO_ERRORS) - return atom.EvalResult(not args[0], NO_ERRORS) + return result.EvalResult(True, NO_ERRORS) + return result.EvalResult(not args[0], NO_ERRORS) case _: - return atom.EvalResult( + return result.EvalResult( common.Bad.bad, ((warning.Expression(warning.ExpressionWarning.notImplemented), f"logic_operator {o}"),), ) diff --git a/src/constraint_handler/main.py b/src/constraint_handler/main.py index 39493198..d3bcf08d 100644 --- a/src/constraint_handler/main.py +++ b/src/constraint_handler/main.py @@ -8,7 +8,7 @@ import constraint_handler.myClorm as myClorm import constraint_handler.post_processor as post_processor import constraint_handler.propagator as propagator -import constraint_handler.schemas.atom as atom +import constraint_handler.schemas.result as result import constraint_handler.solver_environment as solver_environment import flat_ch.main as flat_main from constraint_handler.engine import Engine, compile @@ -55,7 +55,7 @@ ] + m4_variable_safety_checks m5_presolve = [ -# "5_presolve/core", + # "5_presolve/core", "5_presolve/dispatch", "5_presolve/engine", "5_presolve/presolve", @@ -242,4 +242,4 @@ def add_declarations(ctrl: clingo.Control, declarations): def find_values(model: clingo.Model): - return myClorm.findInModel(model, atom.ResultAtom) + return myClorm.findInModel(model, result.ResultAtom) diff --git a/src/constraint_handler/multimap.py b/src/constraint_handler/multimap.py index d621859b..0fe3fcd9 100644 --- a/src/constraint_handler/multimap.py +++ b/src/constraint_handler/multimap.py @@ -1,8 +1,8 @@ import typing from collections.abc import Callable, Iterator, Mapping -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.set as myset import constraint_handler.utils.common as common @@ -84,20 +84,20 @@ def compare(multimap: Multimap, op: Callable): return best_val, errors -def evaluate_operator(o, args, apply_operator=None) -> atom.EvalResult: +def evaluate_operator(o, args, apply_operator=None) -> result.EvalResult: match o: case operators.MultimapOperator.multimap_isin: assert len(args) == 2 - return atom.EvalResult(args[0] in args[1], NO_ERRORS) + return result.EvalResult(args[0] in args[1], NO_ERRORS) case operators.MultimapOperator.find: assert len(args) == 2 - return atom.EvalResult(args[1][args[0]] if args[0] in args[1] else frozenset(), NO_ERRORS) + return result.EvalResult(args[1][args[0]] if args[0] in args[1] else frozenset(), NO_ERRORS) case operators.MultimapOperator.find2: assert len(args) == 3 - return atom.EvalResult(args[1] in args[0] and args[2] in args[0][args[1]], NO_ERRORS) + return result.EvalResult(args[1] in args[0] and args[2] in args[0][args[1]], NO_ERRORS) case operators.MultimapOperator.multimap_fold: if apply_operator is None: - return atom.EvalResult( + return result.EvalResult( common.Bad.bad, ((warning.Expression(warning.ExpressionWarning.notImplemented), "multimap_fold missing callback"),), ) @@ -108,10 +108,10 @@ def step(*aaa): fold_errors.extend(applied.errors) return applied.value - return atom.EvalResult(fold(step, args[1], args[2]), tuple(fold_errors)) + return result.EvalResult(fold(step, args[1], args[2]), tuple(fold_errors)) case operators.MultimapOperator.multimap_fold_i: if apply_operator is None: - return atom.EvalResult( + return result.EvalResult( common.Bad.bad, ( ( @@ -127,29 +127,29 @@ def step(*aaa): fold_errors.extend(applied.errors) return applied.value - return atom.EvalResult(fold_i(step, args[1], args[2]), tuple(fold_errors)) + return result.EvalResult(fold_i(step, args[1], args[2]), tuple(fold_errors)) case operators.MultimapOperator.multimap_make: - return atom.EvalResult(Multimap.from_pairs(args), NO_ERRORS) + return result.EvalResult(Multimap.from_pairs(args), NO_ERRORS) case operators.MultimapOperator.countKeys: - return atom.EvalResult(len(args[0]), NO_ERRORS) + return result.EvalResult(len(args[0]), NO_ERRORS) case operators.MultimapOperator.countEntries: count = 0 for key, value in args[0].items(): count += len(value) - return atom.EvalResult(count, NO_ERRORS) + return result.EvalResult(count, NO_ERRORS) case operators.MultimapOperator.sumIntEntries: total = 0 for key, value in args[0].items(): total += sum(v for v in value if isinstance(v, int)) - return atom.EvalResult(total, NO_ERRORS) + return result.EvalResult(total, NO_ERRORS) case operators.MultimapOperator.maxEntries: __max, errors = compare(args[0], max) - return atom.EvalResult(__max, tuple((kind, str(msg)) for kind, msg in errors)) + return result.EvalResult(__max, tuple((kind, str(msg)) for kind, msg in errors)) case operators.MultimapOperator.minEntries: __min, errors = compare(args[0], min) - return atom.EvalResult(__min, tuple((kind, str(msg)) for kind, msg in errors)) + return result.EvalResult(__min, tuple((kind, str(msg)) for kind, msg in errors)) case _: - return atom.EvalResult( + return result.EvalResult( common.Bad.bad, ((warning.Expression(warning.ExpressionWarning.notImplemented), f"multimap.operator {o}"),), ) diff --git a/src/constraint_handler/post_processor.py b/src/constraint_handler/post_processor.py index 39712b1c..a26dabbc 100644 --- a/src/constraint_handler/post_processor.py +++ b/src/constraint_handler/post_processor.py @@ -7,7 +7,7 @@ import constraint_handler.evaluator as evaluator import constraint_handler.myClorm as myClorm -import constraint_handler.schemas.atom as atom +import constraint_handler.schemas.result as result import constraint_handler.schemas.warning as warning @@ -109,12 +109,12 @@ def _extend_optimize_values( for key, total in totals.items(): label, priority = key cTotal, errors = evaluator.reducedExpr(total) - results.append(atom.Optimize_value(label, priority, cTotal)) + results.append(result.Optimize_value(label, priority, cTotal)) results.extend(errors) for key, total in totals_real.items(): label, priority = key cTotal, errors = evaluator.reducedExpr(total) - results.append(atom.Optimize_modelValue(label, priority, cTotal)) + results.append(result.Optimize_modelValue(label, priority, cTotal)) results.extend(errors) return [myClorm.pytocl(atom) for atom in results] diff --git a/src/constraint_handler/propagator.py b/src/constraint_handler/propagator.py index e3687ce4..3ded67a7 100644 --- a/src/constraint_handler/propagator.py +++ b/src/constraint_handler/propagator.py @@ -9,10 +9,10 @@ import constraint_handler.evaluator as evaluator import constraint_handler.multimap as multimap import constraint_handler.myClorm as myClorm -import constraint_handler.schemas.atom as atom import constraint_handler.schemas.expression as expression import constraint_handler.schemas.internal as internal import constraint_handler.schemas.propagator_atom as prop_atom +import constraint_handler.schemas.result as result import constraint_handler.schemas.type_ as type_ import constraint_handler.schemas.warning as warning from constraint_handler.PropagatorConstants import ( @@ -103,7 +103,7 @@ def __init__(self): # this is used for cautious reasoning # for the first model, the set is assigned the first model # This is will hold the model which is then used to update the result - self.python_model: set[atom.ResultAtom] | None = None + self.python_model: set[result.ResultAtom] | None = None # variable lits is used for brave/cautious reasoning to create nogoods that force changes in the model between stages # There is one literal per variable. When it is true, it means that the variable has a different value than previous solutions # TODO: Check that the above explanation is true! @@ -794,7 +794,7 @@ def evaluate_model(self, ctl: clingo.PropagateControl) -> bool: return self.add_nogoods_from_queue(ctl) - def get_reasoning_mode_nogoods(self, variables: set[atom.ResultAtom], first_call: bool) -> list[Iterable[int]]: + def get_reasoning_mode_nogoods(self, variables: set[result.ResultAtom], first_call: bool) -> list[Iterable[int]]: """ Create nogoods used to drive brave/cautious reasoning. @@ -1626,7 +1626,7 @@ def update_python_model(self): elif final_value is ValueStatus.ASSIGNMENT_IS_FALSE: continue pyVal, errors = evaluator.reducedExpr(final_value) - pyAtom = atom.Evaluated( + pyAtom = result.Evaluated( eval_var.ref, pyVal, ) @@ -1700,7 +1700,7 @@ def handle_on_model_set(self, var: Symbol, final_value: set | frozenset): try: pyVal = expression.Ref(evaluator.get_baseType(final_value), clingo.Function("variable", [var])) - pyAtoms = [atom.Value(var, pyVal)] + pyAtoms = [result.Value(var, pyVal)] for value in final_value: if value is ValueStatus.NOT_SET: @@ -1710,7 +1710,7 @@ def handle_on_model_set(self, var: Symbol, final_value: set | frozenset): set_pyVal = value else: set_pyVal = expression.Val(evaluator.get_baseType(value), value) - set_pyAtom = atom.Set_value(var, set_pyVal) + set_pyAtom = result.Set_value(var, set_pyVal) pyAtoms.append(set_pyAtom) for pyAtom in pyAtoms: self.python_model.add(pyAtom) @@ -1724,7 +1724,7 @@ def handle_on_model_set(self, var: Symbol, final_value: set | frozenset): ) ] ) - self.python_model.add(atom.Value(var, expression.Bad.bad)) + self.python_model.add(result.Value(var, expression.Bad.bad)) def handle_on_model_dict(self, var: Symbol, final_value: dict): """ @@ -1743,7 +1743,7 @@ def handle_on_model_dict(self, var: Symbol, final_value: dict): pyVal = expression.Val(evaluator.get_baseType(final_value), var) except Exception: pyVal = expression.Bad.bad - pyAtom = atom.Value(var, pyVal) + pyAtom = result.Value(var, pyVal) self.python_model.add(pyAtom) if pyVal != expression.Bad.bad: @@ -1757,7 +1757,7 @@ def handle_on_model_dict(self, var: Symbol, final_value: dict): errors.extend(keyErrors) mm_pyVal, valErrors = evaluator.reducedExpr(val) errors.extend(valErrors) - mm_pyAtom = atom.Multimap_value(var, mm_pyKey, mm_pyVal) + mm_pyAtom = result.Multimap_value(var, mm_pyKey, mm_pyVal) self.python_model.add(mm_pyAtom) @@ -1782,7 +1782,7 @@ def handle_on_model_normal_type( self.handle_on_model_warning([warning.Warning(kind, (), msg) for kind, msg in errors]) - pyAtom = atom.Value(var, pyVal) + pyAtom = result.Value(var, pyVal) self.python_model.add(pyAtom) def handle_on_model_warning(self, errors: propagator_warning_t): diff --git a/src/constraint_handler/schemas/atom.py b/src/constraint_handler/schemas/atom.py index 5d0a5838..34a9c1cd 100644 --- a/src/constraint_handler/schemas/atom.py +++ b/src/constraint_handler/schemas/atom.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Any, NamedTuple +from typing import NamedTuple import clingo @@ -8,7 +8,6 @@ import constraint_handler.schemas.domain as domain # fmt: skip import constraint_handler.schemas.expression as expression import constraint_handler.schemas.statement as statement -import constraint_handler.schemas.warning as warning LABEL_ANONYMOUS: expression.constant = clingo.Function("_label_anonymous") @@ -17,9 +16,10 @@ class FailIntegrity(NamedTuple): pass -class EvalResult(NamedTuple): - value: Any - errors: tuple[tuple[warning.Kind, str], ...] +class Variable_assign(NamedTuple): + name: expression.constant + value: expression.Expr + label: expression.constant = LABEL_ANONYMOUS class Variable_choice(NamedTuple): @@ -54,7 +54,7 @@ class Variable_domain(NamedTuple): label: expression.constant = LABEL_ANONYMOUS -type VariableAtom = Variable_declare | Variable_define | Variable_default | Variable_domain +type VariableAtom = Variable_assign | Variable_choice | Variable_declare | Variable_default | Variable_define | Variable_domain class Bool_evaluate(NamedTuple): @@ -62,11 +62,6 @@ class Bool_evaluate(NamedTuple): label: expression.constant = LABEL_ANONYMOUS -class Bool_evaluated(NamedTuple): - expr: expression.Expr - value: expression.ReducedExpr - - class Set_assign(NamedTuple): name: expression.constant member: expression.Expr @@ -79,11 +74,6 @@ class Set_baseDomain(NamedTuple): label: expression.constant = LABEL_ANONYMOUS -class Set_value(NamedTuple): - name: expression.constant - elt: expression.ReducedExpr - - type SetAtom = Set_assign | Set_baseDomain @@ -94,15 +84,6 @@ class Multimap_assign(NamedTuple): label: expression.constant = LABEL_ANONYMOUS -class Multimap_value(NamedTuple): - name: expression.constant - key: expression.ReducedExpr - cst: expression.ReducedExpr - - -type MultimapAtom = Multimap_assign - - class Execution_declare(NamedTuple): name: expression.constant body: statement.Stmt @@ -134,21 +115,6 @@ class Optimize_precision(NamedTuple): type OptimizeAtom = Optimize_maximizeSum | Optimize_precision -class Optimize_modelValue(NamedTuple): - label: expression.constant - priority: expression.constant - total: expression.ReducedExpr - - -class Optimize_value(NamedTuple): - label: expression.constant - priority: expression.constant - total: expression.ReducedExpr - - -type OptimizeResult = Optimize_modelValue | Optimize_value - - class Preference_maximizeScore(NamedTuple): pass @@ -169,33 +135,15 @@ class Preference_variableValue(NamedTuple): type PreferenceAtom = Preference_maximizeScore | Preference_holds | Preference_variableValue -class Preference_score(NamedTuple): - score: int - - class Ensure(NamedTuple): expr: expression.Expr label: expression.constant = LABEL_ANONYMOUS -class Value(NamedTuple): - name: expression.constant - val: expression.ReducedExpr - - def __repr__(self): - return f"Value({str(self.name)},{str(self.val)})" - - class Evaluate(NamedTuple): expr: expression.Expr label: expression.constant = LABEL_ANONYMOUS -class Evaluated(NamedTuple): - expr: expression.Expr - value: expression.ReducedExpr - - -type MainAtom = Ensure | Evaluate -type Atom = ExecutionAtom | MainAtom | MultimapAtom | OptimizeAtom | PreferenceAtom | SetAtom | VariableAtom -type ResultAtom = Value | Evaluated | Set_value | Multimap_value | OptimizeResult | Preference_score | warning.Warning +type MainAtom = Bool_evaluate | Ensure | Evaluate +type Atom = ExecutionAtom | MainAtom | Multimap_assign | OptimizeAtom | PreferenceAtom | SetAtom | VariableAtom diff --git a/src/constraint_handler/schemas/core.py b/src/constraint_handler/schemas/core.py new file mode 100644 index 00000000..eb608bf0 --- /dev/null +++ b/src/constraint_handler/schemas/core.py @@ -0,0 +1,95 @@ +from __future__ import annotations + +from typing import NamedTuple + +import clingo + +import constraint_handler.schemas.domain as domain # fmt: skip +import constraint_handler.schemas.expression as expression + + +class Variable_assign(NamedTuple): + name: expression.constant + value: expression.Expr + + +class Variable_choice(NamedTuple): + name: expression.constant + value: expression.Expr + + +class Variable_declare(NamedTuple): + name: expression.constant + domain: domain.Domain + + +class Variable_define(NamedTuple): + name: expression.constant + value: expression.Expr + + +class Variable_default(NamedTuple): + name: expression.constant + value: expression.Expr + condition: expression.Expr + priority: expression.constant + + +class Variable_domain(NamedTuple): + name: expression.constant + value: expression.Expr + + +class Bool_evaluate(NamedTuple): + expr: expression.Expr + + +class Set_assign(NamedTuple): + name: expression.constant + member: expression.Expr + + +class Set_baseDomain(NamedTuple): + name: expression.constant + value: expression.Expr + + +class Multimap_assign(NamedTuple): + name: expression.constant + key: expression.Expr + val: expression.Expr + + +class Optimize_component(NamedTuple): + value: expression.Expr + precision: expression.Expr + id: expression.constant + priority: expression.constant + + +class Preference_maximizeScore(NamedTuple): + pass + + +class Preference_holds(NamedTuple): + value: expression.Expr + factor: int + + +type PreferenceAtom = Preference_maximizeScore | Preference_holds + + +class Ensure(NamedTuple): + expr: expression.Expr + + +class Evaluate(NamedTuple): + expr: expression.Expr + + +type Atom = Bool_evaluate | Ensure | Evaluate | Multimap_assign | Optimize_component | PreferenceAtom | Set_assign | Set_baseDomain | Variable_assign | Variable_choice | Variable_declare | Variable_default | Variable_define | Variable_domain + + +class Core_ch(NamedTuple): + declaration: Atom + label: expression.constant diff --git a/src/constraint_handler/schemas/propagator_atom.py b/src/constraint_handler/schemas/propagator_atom.py index b09403b0..75b4454b 100644 --- a/src/constraint_handler/schemas/propagator_atom.py +++ b/src/constraint_handler/schemas/propagator_atom.py @@ -5,13 +5,14 @@ import constraint_handler.schemas.atom as atom import constraint_handler.schemas.domain as domain import constraint_handler.schemas.expression as expression +import constraint_handler.schemas.result as result import constraint_handler.schemas.warning as warning -Bool_evaluated = atom.Bool_evaluated -Evaluated = atom.Evaluated -Multimap_value = atom.Multimap_value -Set_value = atom.Set_value -Value = atom.Value +Bool_evaluated = result.Bool_evaluated +Evaluated = result.Evaluated +Multimap_value = result.Multimap_value +Set_value = result.Set_value +Value = result.Value BoolDomain = domain.BoolDomain FromFacts = domain.FromFacts diff --git a/src/constraint_handler/schemas/result.py b/src/constraint_handler/schemas/result.py new file mode 100644 index 00000000..d31dea92 --- /dev/null +++ b/src/constraint_handler/schemas/result.py @@ -0,0 +1,65 @@ +from __future__ import annotations + +from typing import Any, NamedTuple + +import clingo + +import constraint_handler.schemas.domain as domain # fmt: skip +import constraint_handler.schemas.expression as expression +import constraint_handler.schemas.warning as warning + + +class EvalResult(NamedTuple): + value: Any + errors: tuple[tuple[warning.Kind, str], ...] + + +class Bool_evaluated(NamedTuple): + expr: expression.Expr + value: expression.ReducedExpr + + +class Set_value(NamedTuple): + name: expression.constant + elt: expression.ReducedExpr + + +class Multimap_value(NamedTuple): + name: expression.constant + key: expression.ReducedExpr + cst: expression.ReducedExpr + + +class Optimize_modelValue(NamedTuple): + label: expression.constant + priority: expression.constant + total: expression.ReducedExpr + + +class Optimize_value(NamedTuple): + label: expression.constant + priority: expression.constant + total: expression.ReducedExpr + + +class Preference_score(NamedTuple): + score: int + + +type OptimizeResult = Optimize_modelValue | Optimize_value + + +class Value(NamedTuple): + name: expression.constant + val: expression.ReducedExpr + + def __repr__(self): + return f"Value({str(self.name)},{str(self.val)})" + + +class Evaluated(NamedTuple): + expr: expression.Expr + value: expression.ReducedExpr + + +type ResultAtom = Bool_evaluated | Evaluated | Set_value | Multimap_value | OptimizeResult | Preference_score | Value | warning.Warning diff --git a/src/constraint_handler/set.py b/src/constraint_handler/set.py index c50a03ca..863da2db 100644 --- a/src/constraint_handler/set.py +++ b/src/constraint_handler/set.py @@ -1,5 +1,5 @@ -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 import constraint_handler.utils.errors as errors @@ -15,11 +15,11 @@ def fold(f, s, start): return accu -def evaluate_operator(o, args, apply_operator=None) -> atom.EvalResult: +def evaluate_operator(o, args, apply_operator=None) -> result.EvalResult: match o: case operators.SetOperator.cardinality: if len(args) != 1: - return atom.EvalResult( + return result.EvalResult( common.Bad.bad, ( ( @@ -29,13 +29,13 @@ def evaluate_operator(o, args, apply_operator=None) -> atom.EvalResult: ), ) if args[0] == common.Bad.bad: - return atom.EvalResult(common.Bad.bad, NO_ERRORS) - return atom.EvalResult(len(args[0]), NO_ERRORS) + return result.EvalResult(common.Bad.bad, NO_ERRORS) + return result.EvalResult(len(args[0]), NO_ERRORS) case operators.SetOperator.set_make: - return atom.EvalResult(frozenset(args), NO_ERRORS) + return result.EvalResult(frozenset(args), NO_ERRORS) case operators.SetOperator.set_isin: if len(args) != 2: - return atom.EvalResult( + return result.EvalResult( common.Bad.bad, ( ( @@ -45,11 +45,11 @@ def evaluate_operator(o, args, apply_operator=None) -> atom.EvalResult: ), ) if common.Bad.bad in args: - return atom.EvalResult(common.Bad.bad, NO_ERRORS) - return atom.EvalResult(args[0] in args[1], NO_ERRORS) + return result.EvalResult(common.Bad.bad, NO_ERRORS) + return result.EvalResult(args[0] in args[1], NO_ERRORS) case operators.SetOperator.set_notin: if len(args) != 2: - return atom.EvalResult( + return result.EvalResult( common.Bad.bad, ( ( @@ -59,15 +59,15 @@ def evaluate_operator(o, args, apply_operator=None) -> atom.EvalResult: ), ) if args[1] == common.Bad.bad: - return atom.EvalResult(common.Bad.bad, NO_ERRORS) - return atom.EvalResult(args[0] not in args[1], NO_ERRORS) + return result.EvalResult(common.Bad.bad, NO_ERRORS) + return result.EvalResult(args[0] not in args[1], NO_ERRORS) case operators.SetOperator.union: if common.Bad.bad in args: - return atom.EvalResult(common.Bad.bad, NO_ERRORS) - return atom.EvalResult(frozenset().union(*args), NO_ERRORS) + return result.EvalResult(common.Bad.bad, NO_ERRORS) + return result.EvalResult(frozenset().union(*args), NO_ERRORS) case operators.SetOperator.inter: if len(args) < 1: - return atom.EvalResult( + return result.EvalResult( common.Bad.bad, ( ( @@ -77,11 +77,11 @@ def evaluate_operator(o, args, apply_operator=None) -> atom.EvalResult: ), ) if common.Bad.bad in args: - return atom.EvalResult(common.Bad.bad, NO_ERRORS) - return atom.EvalResult(frozenset(args[0].intersection(*args[1:])), NO_ERRORS) + return result.EvalResult(common.Bad.bad, NO_ERRORS) + return result.EvalResult(frozenset(args[0].intersection(*args[1:])), NO_ERRORS) case operators.SetOperator.diff: if len(args) != 2: - return atom.EvalResult( + return result.EvalResult( common.Bad.bad, ( ( @@ -91,11 +91,11 @@ def evaluate_operator(o, args, apply_operator=None) -> atom.EvalResult: ), ) if common.Bad.bad in args: - return atom.EvalResult(common.Bad.bad, NO_ERRORS) - return atom.EvalResult(frozenset(args[0].difference(args[1])), NO_ERRORS) + return result.EvalResult(common.Bad.bad, NO_ERRORS) + return result.EvalResult(frozenset(args[0].difference(args[1])), NO_ERRORS) case operators.SetOperator.subset: if len(args) != 2: - return atom.EvalResult( + return result.EvalResult( common.Bad.bad, ( ( @@ -105,11 +105,11 @@ def evaluate_operator(o, args, apply_operator=None) -> atom.EvalResult: ), ) if common.Bad.bad in args: - return atom.EvalResult(common.Bad.bad, NO_ERRORS) - return atom.EvalResult(args[0].issubset(args[1]), NO_ERRORS) + return result.EvalResult(common.Bad.bad, NO_ERRORS) + return result.EvalResult(args[0].issubset(args[1]), NO_ERRORS) case operators.SetOperator.set_fold: if len(args) != 3: - return atom.EvalResult( + return result.EvalResult( common.Bad.bad, ( ( @@ -119,9 +119,9 @@ def evaluate_operator(o, args, apply_operator=None) -> atom.EvalResult: ), ) if args[1] == common.Bad.bad or args[2] == common.Bad.bad: - return atom.EvalResult(common.Bad.bad, NO_ERRORS) + return result.EvalResult(common.Bad.bad, NO_ERRORS) if apply_operator is None: - return atom.EvalResult( + return result.EvalResult( common.Bad.bad, ((warning.Expression(warning.ExpressionWarning.notImplemented), "set_fold missing callback"),), ) @@ -132,9 +132,9 @@ def step(*aaa): fold_errors.extend(applied.errors) return applied.value - return atom.EvalResult(fold(step, args[1], args[2]), tuple(fold_errors)) + return result.EvalResult(fold(step, args[1], args[2]), tuple(fold_errors)) case _: - return atom.EvalResult( + return result.EvalResult( common.Bad.bad, ((warning.Expression(warning.ExpressionWarning.notImplemented), f"set.operator {o}"),), ) diff --git a/src/constraint_handler/string.py b/src/constraint_handler/string.py index 26bc3b4a..95a1178f 100644 --- a/src/constraint_handler/string.py +++ b/src/constraint_handler/string.py @@ -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.StringOperator.length: if len(args) != 1: - return atom.EvalResult( + return result.EvalResult( expression.Bad.bad, ( ( @@ -19,11 +19,11 @@ def evaluate_operator(o, args) -> atom.EvalResult: ), ), ) - return atom.EvalResult(len(args[0]), NO_ERRORS) + return result.EvalResult(len(args[0]), NO_ERRORS) case operators.StringOperator.concat: - return atom.EvalResult("".join(args), NO_ERRORS) + return result.EvalResult("".join(args), NO_ERRORS) case _: - return atom.EvalResult( + return result.EvalResult( expression.Bad.bad, ((warning.Expression(warning.ExpressionWarning.notImplemented), f"string operator {o}"),), ) diff --git a/tests/test_from_python.py b/tests/test_from_python.py index 8ff5e721..3775eba7 100644 --- a/tests/test_from_python.py +++ b/tests/test_from_python.py @@ -1,11 +1,9 @@ import clingo import constraint_handler -import constraint_handler.schemas.atom as atom from constraint_handler.schemas.atom import ( Ensure, Optimize_maximizeSum, - Value, Variable_declare, Variable_define, Variable_domain, @@ -13,6 +11,11 @@ from constraint_handler.schemas.domain import FromFacts from constraint_handler.schemas.expression import Operation, Val, Variable from constraint_handler.schemas.operators import ArithmeticOperator, ComparisonOperator +from constraint_handler.schemas.result import ( + Optimize_modelValue, + Optimize_value, + Value, +) from constraint_handler.schemas.type_ import BaseType @@ -84,11 +87,11 @@ def test_optimization(): actual_value = {} for x in results: match x: - case atom.Value(): + case Value(): best_assignment[x.name] = x.val.value - case atom.Optimize_value(): + case Optimize_value(): opt_value[x.label] = x.total.value - case atom.Optimize_modelValue(): + case Optimize_modelValue(): actual_value[x.label] = x.total.value assert best_assignment == {"x": 4, "y": 3.25} From 4fdc3ad94384f81f11de8b11f1bb4f689c9a0a6b Mon Sep 17 00:00:00 2001 From: Abdallah Saffidine Date: Thu, 17 Sep 2026 12:52:12 +1000 Subject: [PATCH 03/18] swap order of engine_request arguments and start inserting core interface --- CHANGES.md | 1 + src/constraint_handler/data/5_presolve/core.lp | 10 ---------- .../data/5_presolve/engine.lp | 12 ++++-------- .../data/5_presolve/to_core.lp | 18 ++++++++++++++++++ .../data/7_output/warning.lp | 11 ++--------- src/constraint_handler/main.py | 3 ++- tests/correctness/engine/request.lp | 12 ++++++------ .../correctness/engine/request_interaction.lp | 12 ++++++------ tests/correctness/engine/request_mixed_trig.lp | 6 +++--- tests/correctness/engine/request_mult.lp | 16 ++++++++-------- tests/correctness/engine/request_set_ref.lp | 10 +++++----- 11 files changed, 55 insertions(+), 56 deletions(-) create mode 100644 src/constraint_handler/data/5_presolve/to_core.lp diff --git a/CHANGES.md b/CHANGES.md index 357c2710..0e9717ad 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,7 @@ ## Ongoing +- - 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"`. diff --git a/src/constraint_handler/data/5_presolve/core.lp b/src/constraint_handler/data/5_presolve/core.lp index d18c7b76..bf707823 100644 --- a/src/constraint_handler/data/5_presolve/core.lp +++ b/src/constraint_handler/data/5_presolve/core.lp @@ -13,13 +13,3 @@ _passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=multimap_assign(X,K,B). _passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=share_value(E). _passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=optimize_component(E,O,P,X,PRIORITY). _passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=preference_holds(E,K). - - - -ch_core(engine_request(LBL,ENG)) :- engine_request(LBL,ENG). -%%%ch_core(engine_default(ENG)) :- engine_default(ENG). -%% ch_core(engine_request(LBL,ENG)). -%%%% ch_core(engine_default(ENG)). - -ch_core(warning_forbid(KIND,LBL)) :- warning_forbid(KIND,LBL). -ch_core(warning_ignore(KIND,LBL)) :- warning_ignore(KIND,LBL). diff --git a/src/constraint_handler/data/5_presolve/engine.lp b/src/constraint_handler/data/5_presolve/engine.lp index bfb62379..ad2fc44f 100644 --- a/src/constraint_handler/data/5_presolve/engine.lp +++ b/src/constraint_handler/data/5_presolve/engine.lp @@ -1,19 +1,15 @@ -#defined engine_request/1. -#defined engine_request/2. - %%%%%%%%%%%%%%%%% engines _engine_supportOptimization(compile;compile2;ground;propagator). _engine(compile;compile2;ground;propagator;none). _engine_grounding(compile;compile2;ground). -_engine_default(ENG) :- engine_request(ENG,_label_anonymous), _engine(ENG). -_engine_default(ENG) :- engine_request(ENG), _engine(ENG). -_engine_defaultProvided :- engine_request(ENG), _engine(ENG). +_engine_default(ENG) :- ch_core(engine_request(ENG),_label_anonymous). +_engine_defaultProvided :- ch_core(engine_request(ENG),_label_anonymous). _engine_default(compile) :- not _engine_defaultProvided. _label(LBL) :- _label(LBL,DECL). -_engine_userRequest(LBL) :- engine_request(LBL,ENG), _engine(ENG). -_engine(LBL,ENG) :- engine_request(LBL,ENG), _engine(ENG). +_engine_userRequest(LBL) :- ch_core(engine_request(ENG),LBL). +_engine(LBL,ENG) :- ch_core(engine_request(ENG),LBL). _engine(LBL,ENG) :- _engine_default(ENG), not _engine_userRequest(LBL), _label(LBL). %%%%%%%%%%%%%%%%% collect labels diff --git a/src/constraint_handler/data/5_presolve/to_core.lp b/src/constraint_handler/data/5_presolve/to_core.lp new file mode 100644 index 00000000..5ce16dd2 --- /dev/null +++ b/src/constraint_handler/data/5_presolve/to_core.lp @@ -0,0 +1,18 @@ +%%%%%%%%%%%%%%%%% engines +#defined engine_request/1. +#defined engine_request/2. + +#defined warning_forbid/1. +#defined warning_forbid/2. +#defined warning_ignore/1. +#defined warning_ignore/2. + +ch_core(engine_request(ENG),_label_anonymous) :- engine_request(ENG), _engine(ENG). +ch_core(engine_request(ENG),LBL) :- engine_request(ENG,LBL), _engine(ENG). + +%%%%%%%%%%%%%%%%% warnings +ch_core(warning_forbid(KIND),LBL) :- warning_forbid(KIND,LBL). +ch_core(warning_ignore(KIND),LBL) :- warning_ignore(KIND,LBL). + +ch_core(warning_forbid(KIND),_label_anonymous) :- warning_forbid(KIND). +ch_core(warning_ignore(KIND),_label_anonymous) :- warning_ignore(KIND). diff --git a/src/constraint_handler/data/7_output/warning.lp b/src/constraint_handler/data/7_output/warning.lp index 1291121f..52a65402 100644 --- a/src/constraint_handler/data/7_output/warning.lp +++ b/src/constraint_handler/data/7_output/warning.lp @@ -1,12 +1,5 @@ -#defined warning_forbid/1. -#defined warning_forbid/2. -#defined warning_ignore/1. -#defined warning_ignore/2. - -_warning_forbid(KIND,LBL) :- warning_forbid(KIND,LBL). -_warning_ignore(KIND,LBL) :- warning_ignore(KIND,LBL). -_warning_forbid(KIND,_label_anonymous) :- warning_forbid(KIND). -_warning_ignore(KIND,_label_anonymous) :- warning_ignore(KIND). +_warning_forbid(KIND,LBL) :- ch_core(warning_forbid(KIND),LBL). +_warning_ignore(KIND,LBL) :- ch_core(warning_ignore(KIND),LBL). _warning_raised(KIND,INFO) :- _warning(KIND,INFO,MSG), not _warning_ignore(KIND,INFO), not _warning_ignore(KIND,_label_anonymous). :- _warning_raised(KIND,INFO), _warning_forbid(KIND,_label_anonymous). diff --git a/src/constraint_handler/main.py b/src/constraint_handler/main.py index d3bcf08d..266aa182 100644 --- a/src/constraint_handler/main.py +++ b/src/constraint_handler/main.py @@ -55,7 +55,8 @@ ] + m4_variable_safety_checks m5_presolve = [ - # "5_presolve/core", + "5_presolve/core", + "5_presolve/to_core", "5_presolve/dispatch", "5_presolve/engine", "5_presolve/presolve", diff --git a/tests/correctness/engine/request.lp b/tests/correctness/engine/request.lp index 5e84ff8a..1a29c3d5 100644 --- a/tests/correctness/engine/request.lp +++ b/tests/correctness/engine/request.lp @@ -14,13 +14,13 @@ variable_define(y(E1,E2,E3), (variable(i(E1,E2,E3)),()))), (val(int,1),()))), assign_y(E1,E2,E3)) :- combo(E1,E2,E3). -engine_request(assign_i(E1,E2,E3),E1) :- combo(E1,E2,E3). -engine_request(assign_j(E1,E2,E3),E2) :- combo(E1,E2,E3). -engine_request(assign_y(E1,E2,E3),E3) :- combo(E1,E2,E3). +engine_request(E1,assign_i(E1,E2,E3)) :- combo(E1,E2,E3). +engine_request(E2,assign_j(E1,E2,E3)) :- combo(E1,E2,E3). +engine_request(E3,assign_y(E1,E2,E3)) :- combo(E1,E2,E3). variable_define(i,val(int,3),assign_cons_i). variable_define(j,operation(mult,(variable(i),(variable(i),()))),assign_cons_j). variable_define(k,operation(add,(variable(i),(variable(j),()))),assign_cons_k). -engine_request(assign_cons_i,compile). -engine_request(assign_cons_j,ground). -engine_request(assign_cons_k,propagator). +engine_request(compile,assign_cons_i). +engine_request(ground,assign_cons_j). +engine_request(propagator,assign_cons_k). diff --git a/tests/correctness/engine/request_interaction.lp b/tests/correctness/engine/request_interaction.lp index 33576a0b..4ebfb9b9 100644 --- a/tests/correctness/engine/request_interaction.lp +++ b/tests/correctness/engine/request_interaction.lp @@ -1,18 +1,18 @@ variable_define(base_compile,val(int,1),base_c). variable_define(base_ground,val(int,1),base_g). -engine_request(base_c, compile). -engine_request(base_g, ground). +engine_request(compile,base_c). +engine_request(ground,base_g). variable_define(compile_to_ground,operation(add,(variable(base_compile),(variable(base_compile),()))),c_to_g). variable_define(ground_to_compile,operation(add,(variable(base_ground),(variable(base_ground),()))),g_to_c). -engine_request(c_to_g,ground). -engine_request(g_to_c,compile). +engine_request(ground,c_to_g). +engine_request(compile,g_to_c). variable_define(mixed_to_ground,operation(add,(variable(base_compile),(variable(base_ground),()))),mixed_to_g). variable_define(mixed_to_compile,operation(add,(variable(base_compile),(variable(base_ground),()))),mixed_to_c). -engine_request(mixed_to_g,ground). -engine_request(mixed_to_c,compile). +engine_request(ground,mixed_to_g). +engine_request(compile,mixed_to_c). diff --git a/tests/correctness/engine/request_mixed_trig.lp b/tests/correctness/engine/request_mixed_trig.lp index 569aebaf..c20d832d 100644 --- a/tests/correctness/engine/request_mixed_trig.lp +++ b/tests/correctness/engine/request_mixed_trig.lp @@ -14,6 +14,6 @@ variable_define(z,operation(sub,(variable(y), (variable(f),()))),assign_z). variable_define(u,operation(sin,(variable(z),())),assign_u). -engine_request(assign_y,ground). -engine_request(assign_z,compile). -engine_request(assign_u,ground). +engine_request(ground,assign_y). +engine_request(compile,assign_z). +engine_request(ground,assign_u). diff --git a/tests/correctness/engine/request_mult.lp b/tests/correctness/engine/request_mult.lp index 50a8ac33..6fb219ad 100644 --- a/tests/correctness/engine/request_mult.lp +++ b/tests/correctness/engine/request_mult.lp @@ -4,8 +4,8 @@ variable_declare(as_s,set,assign_as_s). set_assign(as_s,val(int,2),assign_as_s). set_assign(as_s,variable(as_a),assign_as_s). -engine_request(assign_as_a, compile). -engine_request(assign_as_s, ground). +engine_request(compile,assign_as_a). +engine_request(ground,assign_as_s). %%% (set,set) -> set @@ -17,9 +17,9 @@ set_assign(sss_s2,val(int,2),assign_sss_s2). set_assign(sss_s2,val(int,3),assign_sss_s2). variable_define(sss_s3,operation(inter,(variable(sss_s1),(variable(sss_s2),()))),assign_sss_s3). -engine_request(assign_sss_s1,compile). -engine_request(assign_sss_s2,ground). -engine_request(assign_sss_s3,compile). +engine_request(compile,assign_sss_s1). +engine_request(ground,assign_sss_s2). +engine_request(compile,assign_sss_s3). %%% set -> atomic @@ -37,8 +37,8 @@ set_assign(ssa_s2,val(int,2),assign_ssa_s2). set_assign(ssa_s2,val(int,3),assign_ssa_s2). variable_define(ssa_a,operation(subset,(variable(ssa_s1),(variable(ssa_s2),()))),assign_ssa_a). -engine_request(assign_ssa_s1,compile). -engine_request(assign_ssa_s2,ground). -engine_request(assign_ssa_a,propagator). +engine_request(compile,assign_ssa_s1). +engine_request(ground,assign_ssa_s2). +engine_request(propagator,assign_ssa_a). warning_ignore(type(failed_operation)). diff --git a/tests/correctness/engine/request_set_ref.lp b/tests/correctness/engine/request_set_ref.lp index 1cc458af..d554717c 100644 --- a/tests/correctness/engine/request_set_ref.lp +++ b/tests/correctness/engine/request_set_ref.lp @@ -19,8 +19,8 @@ variable_define(cap2,variable(cap1),cap2). variable_define(curd2,operation(length,(variable(cup2),())),curd2). variable_define(card2,operation(length,(variable(cap2),())),card2). -% engine_request(sma0, ground). -engine_request(odd0, compile). -engine_request(cap2, propagator). -engine_request(curd2, propagator). -engine_request(card2, propagator). +% engine_request(ground,sma0). +engine_request(compile,odd0). +engine_request(propagator,cap2). +engine_request(propagator,curd2). +engine_request(propagator,card2). From d8231dfbd21da8f7cba0a040c44ba2b9db5db6ad Mon Sep 17 00:00:00 2001 From: Abdallah Saffidine Date: Mon, 21 Sep 2026 17:53:19 +1000 Subject: [PATCH 04/18] Swap label position in internal predicates _engine, _label, and _optimize_component --- src/constraint_handler/data/5_presolve/dispatch.lp | 14 +++++++------- src/constraint_handler/data/5_presolve/engine.lp | 8 ++++---- src/constraint_handler/data/6_solve/optimize.lp | 2 +- src/constraint_handler/post_processor.py | 6 +++--- src/constraint_handler/schemas/internal.py | 2 +- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/constraint_handler/data/5_presolve/dispatch.lp b/src/constraint_handler/data/5_presolve/dispatch.lp index b8caa7f7..334bf5cb 100644 --- a/src/constraint_handler/data/5_presolve/dispatch.lp +++ b/src/constraint_handler/data/5_presolve/dispatch.lp @@ -1,11 +1,11 @@ -_optimize_component(LBL,E,ORIG,PREC,ID,PRIORITY) :- _passed(solve,LBL,optimize_component(E,ORIG,PREC,ID,PRIORITY)), _engine(LBL,ENG), _engine_supportOptimization(ENG). +_optimize_component(E,ORIG,PREC,ID,PRIORITY,LBL) :- _passed(solve,LBL,optimize_component(E,ORIG,PREC,ID,PRIORITY)), _engine(ENG,LBL), _engine_supportOptimization(ENG). -_preference_expressionScore(E,K) :- _passed(solve,LBL,preference_holds(E,K)), _engine(LBL,ENG), _engine_grounding(ENG). +_preference_expressionScore(E,K) :- _passed(solve,LBL,preference_holds(E,K)), _engine(ENG,LBL), _engine_grounding(ENG). -_evaluate(REF,E) :- _passed(solve,LBL,evaluate(REF,E)), _engine(LBL,ENG), _engine_grounding(ENG). +_evaluate(REF,E) :- _passed(solve,LBL,evaluate(REF,E)), _engine(ENG,LBL), _engine_grounding(ENG). _passed(skip,bla) :- _never. -_passed(compile,LBL,DECL) :- _passed(solve,LBL,DECL), _label(LBL,DECL), _engine(LBL,compile), not _passed(skip,DECL). -_passed(compile2,LBL,DECL) :- _passed(solve,LBL,DECL), _label(LBL,DECL), _engine(LBL,compile2), not _passed(skip,DECL). -_passed(ground,LBL,DECL) :- _passed(solve,LBL,DECL), _label(LBL,DECL), _engine(LBL,ground), not _passed(skip,DECL). -_passed(propagator,LBL,DECL) :- _passed(solve,LBL,DECL), _label(LBL,DECL), _engine(LBL,propagator), not _passed(skip,DECL). +_passed(compile,LBL,DECL) :- _passed(solve,LBL,DECL), _label(DECL,LBL), _engine(compile,LBL), not _passed(skip,DECL). +_passed(compile2,LBL,DECL) :- _passed(solve,LBL,DECL), _label(DECL,LBL), _engine(compile2,LBL), not _passed(skip,DECL). +_passed(ground,LBL,DECL) :- _passed(solve,LBL,DECL), _label(DECL,LBL), _engine(ground,LBL), not _passed(skip,DECL). +_passed(propagator,LBL,DECL) :- _passed(solve,LBL,DECL), _label(DECL,LBL), _engine(propagator,LBL), not _passed(skip,DECL). diff --git a/src/constraint_handler/data/5_presolve/engine.lp b/src/constraint_handler/data/5_presolve/engine.lp index ad2fc44f..dd01e254 100644 --- a/src/constraint_handler/data/5_presolve/engine.lp +++ b/src/constraint_handler/data/5_presolve/engine.lp @@ -7,10 +7,10 @@ _engine_default(ENG) :- ch_core(engine_request(ENG),_label_anonymous). _engine_defaultProvided :- ch_core(engine_request(ENG),_label_anonymous). _engine_default(compile) :- not _engine_defaultProvided. -_label(LBL) :- _label(LBL,DECL). +_label(LBL) :- _label(DECL,LBL). _engine_userRequest(LBL) :- ch_core(engine_request(ENG),LBL). -_engine(LBL,ENG) :- ch_core(engine_request(ENG),LBL). -_engine(LBL,ENG) :- _engine_default(ENG), not _engine_userRequest(LBL), _label(LBL). +_engine(ENG,LBL) :- ch_core(engine_request(ENG),LBL). +_engine(ENG,LBL) :- _engine_default(ENG), not _engine_userRequest(LBL), _label(LBL). %%%%%%%%%%%%%%%%% collect labels -_label(LBL,DECL) :- _passed(solve,LBL,DECL). +_label(DECL,LBL) :- _passed(solve,LBL,DECL). diff --git a/src/constraint_handler/data/6_solve/optimize.lp b/src/constraint_handler/data/6_solve/optimize.lp index 889f1bd9..4a69f518 100644 --- a/src/constraint_handler/data/6_solve/optimize.lp +++ b/src/constraint_handler/data/6_solve/optimize.lp @@ -1 +1 @@ -#maximize { I@P,ID : _optimize_component(LBL,E,ORIG,PREC,ID,P), _shared_value(E,val(int,I)) }. +#maximize { I@P,ID : _optimize_component(E,ORIG,PREC,ID,P,LBL), _shared_value(E,val(int,I)) }. diff --git a/src/constraint_handler/post_processor.py b/src/constraint_handler/post_processor.py index a26dabbc..935c410d 100644 --- a/src/constraint_handler/post_processor.py +++ b/src/constraint_handler/post_processor.py @@ -23,7 +23,7 @@ def init(self, init: clingo.PropagateInit) -> None: self._optimize_symbols = [ symbolic_atom.symbol for symbolic_atom in init.symbolic_atoms.by_signature("_optimize_component", 6) ] - optimize_exprs = {expr for symbol in self._optimize_symbols for expr in symbol.arguments[1:4]} + optimize_exprs = {expr for symbol in self._optimize_symbols for expr in symbol.arguments[:3]} self._value_symbols_by_expr.clear() for symbolic_atom in init.symbolic_atoms.by_signature("_shared_value", 2): @@ -39,7 +39,7 @@ def reset_optimize_value_symbols(self) -> None: def get_results(self, model) -> tuple[dict[clingo.Symbol, int | float], list[clingo.Symbol]]: values = {} for optimize_symbol in self._optimize_symbols: - _, value_expr, original_expr, precision_expr, _, _ = optimize_symbol.arguments + value_expr, original_expr, precision_expr, _, _, _ = optimize_symbol.arguments for expr in (value_expr, original_expr, precision_expr): if expr in values: continue @@ -82,7 +82,7 @@ def _extend_optimize_values( totals: dict[tuple[clingo.Symbol, clingo.Symbol], int | float] = {} totals_real: dict[tuple[clingo.Symbol, clingo.Symbol], int | float] = {} for symbol in [] if optimize_results is None else optimize_results: - label, expr, original_expr, precision_expr, _, priority = symbol.arguments + expr, original_expr, precision_expr, _, priority, label = symbol.arguments key = (label, priority) value = values.get(expr, 0) diff --git a/src/constraint_handler/schemas/internal.py b/src/constraint_handler/schemas/internal.py index 294f2df6..3106a9cb 100644 --- a/src/constraint_handler/schemas/internal.py +++ b/src/constraint_handler/schemas/internal.py @@ -33,12 +33,12 @@ class _shared_value(NamedTuple): class _optimize_component(NamedTuple): - label: expression.constant expr: expression.Expr original: expression.Expr precision: clingo.Symbol id: expression.constant priority: expression.Expr | expression.constant + label: expression.constant class Valid(NamedTuple): From 54f92c87209fdc06ceabcd0e26233b9511e85e96 Mon Sep 17 00:00:00 2001 From: Abdallah Saffidine Date: Mon, 21 Sep 2026 19:12:59 +1000 Subject: [PATCH 05/18] add support for preferences to the propagator --- CHANGES.md | 1 + src/constraint_handler/data/5_presolve/dispatch.lp | 2 -- src/constraint_handler/data/6_solve/preference.lp | 8 ++++++-- tests/test_encoding.py | 1 - 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 0e9717ad..2ee1e8d4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,7 @@ ## Ongoing +- 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 diff --git a/src/constraint_handler/data/5_presolve/dispatch.lp b/src/constraint_handler/data/5_presolve/dispatch.lp index 334bf5cb..71fc91d9 100644 --- a/src/constraint_handler/data/5_presolve/dispatch.lp +++ b/src/constraint_handler/data/5_presolve/dispatch.lp @@ -1,7 +1,5 @@ _optimize_component(E,ORIG,PREC,ID,PRIORITY,LBL) :- _passed(solve,LBL,optimize_component(E,ORIG,PREC,ID,PRIORITY)), _engine(ENG,LBL), _engine_supportOptimization(ENG). -_preference_expressionScore(E,K) :- _passed(solve,LBL,preference_holds(E,K)), _engine(ENG,LBL), _engine_grounding(ENG). - _evaluate(REF,E) :- _passed(solve,LBL,evaluate(REF,E)), _engine(ENG,LBL), _engine_grounding(ENG). _passed(skip,bla) :- _never. diff --git a/src/constraint_handler/data/6_solve/preference.lp b/src/constraint_handler/data/6_solve/preference.lp index 4e835387..92a968e4 100644 --- a/src/constraint_handler/data/6_solve/preference.lp +++ b/src/constraint_handler/data/6_solve/preference.lp @@ -2,6 +2,9 @@ _warning(preference(unsupported),LBL1,("multiple scores for the same expression",E,K1,K2)) :- _passed(sugar,LBL1,preference_holds(E,K1)), _passed(sugar,LBL2,preference_holds(E,K2)), K1 < K2. +_preference_expressionScore(E,K) :- _passed(solve,LBL,preference_holds(E,K)). +_passed(solve,LBL,bool_evaluate(E)) :- _passed(solve,LBL,preference_holds(E,K)). + _preference_expression(E) :- _preference_expressionScore(E,K). @@ -13,7 +16,8 @@ _preference_potentialAux(0,0) :- preference_maximizeScore. _preference_potentialAux(IDX+1,W) :- _preference_potentialAux(IDX,W), _preference_index(E,IDX). _preference_potentialAux(IDX+1,W+K) :- _preference_potentialAux(IDX,W), _preference_index(E,IDX), _preference_expressionScore(E, K), K > 0. _preference_potentialScore(W) :- _preference_potentialAux(IDX,W), not _preference_potentialAux(IDX+1,W). -preference_score(W) :- preference_maximizeScore, W = #sum { K,E : _shared_value(E,val(bool,true)), _preference_expressionScore(E,K), K > 0 }. -#heuristic _shared_value(E,val(bool,true)) : _preference_expressionScore(E,K). [1,true] +preference_score(W) :- preference_maximizeScore, W = #sum { K,E : bool_evaluated(E,val(bool,true)), _preference_expressionScore(E,K), K > 0 }. + +#heuristic bool_evaluated(E,val(bool,true)) : _preference_expressionScore(E,K). [1,true] #heuristic preference_score(W) : _preference_potentialScore(W),W>0. [1+W,true] diff --git a/tests/test_encoding.py b/tests/test_encoding.py index d5ff3862..09def1c7 100644 --- a/tests/test_encoding.py +++ b/tests/test_encoding.py @@ -609,7 +609,6 @@ def run_test(name: str, selected_engine: engine.Engine): "engine/request_mixed_trig", "expression/lambda/recursive", "multimap/main", - "optimization/preferences", "set/fold_bools", "set/iterations", "set/selfref", From 78a57f12190dd81d5472df4276be4f76b2dc3404 Mon Sep 17 00:00:00 2001 From: Abdallah Saffidine Date: Tue, 22 Sep 2026 21:39:49 +1000 Subject: [PATCH 06/18] fix rebase-introduced bugs --- src/constraint_handler/PropagatorConstants.py | 2 +- src/constraint_handler/engine.py | 2 +- tests/test_api.py | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/constraint_handler/PropagatorConstants.py b/src/constraint_handler/PropagatorConstants.py index aeb62243..c44f3969 100644 --- a/src/constraint_handler/PropagatorConstants.py +++ b/src/constraint_handler/PropagatorConstants.py @@ -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. diff --git a/src/constraint_handler/engine.py b/src/constraint_handler/engine.py index d0453634..8cbaed86 100644 --- a/src/constraint_handler/engine.py +++ b/src/constraint_handler/engine.py @@ -12,7 +12,7 @@ def identifier(self) -> str: return "-".join((self.name, *(f"{name}={value}" for name, value in sorted(self.parameters.items())))) def program(self) -> str: - program = f"engine_default({self.name})." + program = f"engine_request({self.name})." if self.parameters.get("check_mode"): program += f"\n{PROPAGATOR_CHECK_MODE_STR}." return program diff --git a/tests/test_api.py b/tests/test_api.py index f505c1c7..d8e62bf7 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -7,6 +7,7 @@ from clingo import Control, Symbol import constraint_handler +import constraint_handler.engine as engine def test_add_ctrl(): From b1e06b1d9af1e39f00d69e539aa29a0d95669c82 Mon Sep 17 00:00:00 2001 From: Abdallah Saffidine Date: Wed, 23 Sep 2026 14:46:35 +1000 Subject: [PATCH 07/18] Insert ch_core stage. --- src/constraint_handler/data/3_sugar/sugar.lp | 6 ---- .../data/5_presolve/core.lp | 34 +++++++++++-------- .../data/5_presolve/dispatch.lp | 4 --- .../data/5_presolve/engine.lp | 1 + .../data/5_presolve/presolve.lp | 6 ++-- .../data/6_solve/defaults.lp | 8 ++--- src/constraint_handler/data/6_solve/ensure.lp | 8 +++++ .../data/6_solve/evaluate.lp | 9 +++++ .../data/6_solve/optimize.lp | 9 ++++- .../data/6_solve/preference.lp | 5 +-- .../data/6_solve/propagator/propagator.lp | 2 -- src/constraint_handler/data/7_output/value.lp | 5 --- src/constraint_handler/data/main.lp | 2 +- src/constraint_handler/main.py | 2 ++ 14 files changed, 58 insertions(+), 43 deletions(-) create mode 100644 src/constraint_handler/data/6_solve/ensure.lp create mode 100644 src/constraint_handler/data/6_solve/evaluate.lp diff --git a/src/constraint_handler/data/3_sugar/sugar.lp b/src/constraint_handler/data/3_sugar/sugar.lp index fc6ef60d..24d03abf 100644 --- a/src/constraint_handler/data/3_sugar/sugar.lp +++ b/src/constraint_handler/data/3_sugar/sugar.lp @@ -1,13 +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))). @@ -58,7 +54,6 @@ _sugar_aux(LBL,optimize_component(EXPR,E,PREC,ID,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. @@ -67,7 +62,6 @@ _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). diff --git a/src/constraint_handler/data/5_presolve/core.lp b/src/constraint_handler/data/5_presolve/core.lp index bf707823..7069bb26 100644 --- a/src/constraint_handler/data/5_presolve/core.lp +++ b/src/constraint_handler/data/5_presolve/core.lp @@ -1,15 +1,19 @@ -_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=bool_evaluate(E). -_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=ensure(E). -_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=evaluate(REF,E). -_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=variable_assign(X,E). -_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=variable_choice(X,E). -_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=variable_declare(X,D). -_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=variable_default(X,D,C,P). -_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=variable_define(X,E). -_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=variable_domain(X,E). -_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=set_assign(X,E). -_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=set_baseDomain(X,E). -_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=multimap_assign(X,K,B). -_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=share_value(E). -_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=optimize_component(E,O,P,X,PRIORITY). -_passed(solve,LBL,DECL) :- ch_core(DECL,LBL), DECL=preference_holds(E,K). +_passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=bool_evaluate(E). +_passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=variable_assign(X,E). +_passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=variable_choice(X,E). +_passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=variable_declare(X,D). +_passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=variable_default(X,D,C,P). +_passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=variable_define(X,E). +_passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=variable_domain(X,E). +_passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=set_assign(X,E). +_passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=set_baseDomain(X,E). +_passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=multimap_assign(X,K,B). +_passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=share_value(E). +_passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=optimize_component(E,O,P,X,PRIORITY). +_passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=variable_interface(X). + +_passed(solve,LBL,share_value(E)) :- _phase_active(solve), ch_core(bool_evaluate(E),LBL). +%_passed(solve,LBL,share_value(E)) :- _phase_active(solve), ch_core(evaluate(REF,E),LBL). +%_passed(solve,LBL,share_value(E)) :- _phase_active(solve), ch_core(ensure(E),LBL). +%_passed(solve,LBL,share_value(E)) :- _phase_active(solve), ch_core(preference_holds(E,K),LBL). +%_passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=evaluate(REF,E). diff --git a/src/constraint_handler/data/5_presolve/dispatch.lp b/src/constraint_handler/data/5_presolve/dispatch.lp index 71fc91d9..40d2fbbe 100644 --- a/src/constraint_handler/data/5_presolve/dispatch.lp +++ b/src/constraint_handler/data/5_presolve/dispatch.lp @@ -1,7 +1,3 @@ -_optimize_component(E,ORIG,PREC,ID,PRIORITY,LBL) :- _passed(solve,LBL,optimize_component(E,ORIG,PREC,ID,PRIORITY)), _engine(ENG,LBL), _engine_supportOptimization(ENG). - -_evaluate(REF,E) :- _passed(solve,LBL,evaluate(REF,E)), _engine(ENG,LBL), _engine_grounding(ENG). - _passed(skip,bla) :- _never. _passed(compile,LBL,DECL) :- _passed(solve,LBL,DECL), _label(DECL,LBL), _engine(compile,LBL), not _passed(skip,DECL). _passed(compile2,LBL,DECL) :- _passed(solve,LBL,DECL), _label(DECL,LBL), _engine(compile2,LBL), not _passed(skip,DECL). diff --git a/src/constraint_handler/data/5_presolve/engine.lp b/src/constraint_handler/data/5_presolve/engine.lp index dd01e254..4b55481f 100644 --- a/src/constraint_handler/data/5_presolve/engine.lp +++ b/src/constraint_handler/data/5_presolve/engine.lp @@ -14,3 +14,4 @@ _engine(ENG,LBL) :- _engine_default(ENG), not _engine_userRequest(LBL), _label(L %%%%%%%%%%%%%%%%% collect labels _label(DECL,LBL) :- _passed(solve,LBL,DECL). +_label(DECL,LBL) :- ch_core(DECL,LBL). diff --git a/src/constraint_handler/data/5_presolve/presolve.lp b/src/constraint_handler/data/5_presolve/presolve.lp index f1a8876f..ffbee560 100644 --- a/src/constraint_handler/data/5_presolve/presolve.lp +++ b/src/constraint_handler/data/5_presolve/presolve.lp @@ -15,8 +15,8 @@ _solve_conflictVariable(X) :- _variable(sugar,X), 1 < #count { LBL0,DECL : _passed(presolve,LBL0,DECL), DECL=(variable_define(X,E);variable_declare(X,(fromFacts;open;set;multimap))) }. -_passed(solve,LBL,DECL) :- _phase_active(solve), _passed(presolve,LBL,DECL), #false : _variable_involve(presolve,LBL,X,DECL), _solve_conflictVariable(X). +ch_core(DECL,LBL) :- _passed(presolve,LBL,DECL), #false : _variable_involve(presolve,LBL,X,DECL), _solve_conflictVariable(X). _solve_firstLabel(X,LBL) :-_solve_conflictVariable(X), _variable_involve(presolve,LBL,X,DECL), 0 = #count { LBL2 : _variable_involve(presolve,LBL2,X,DECL2), LBL2 < LBL }. -_passed(solve,LBL,variable_declare(X,definition)) :- _phase_active(solve), _solve_firstLabel(X,LBL). -_passed(solve,LBL,variable_define(X,bad)) :- _phase_active(solve), _solve_firstLabel(X,LBL). +ch_core(variable_declare(X,definition),LBL) :- _solve_firstLabel(X,LBL). +ch_core(variable_define(X,bad),LBL) :- _solve_firstLabel(X,LBL). diff --git a/src/constraint_handler/data/6_solve/defaults.lp b/src/constraint_handler/data/6_solve/defaults.lp index 859b811d..73eb9784 100644 --- a/src/constraint_handler/data/6_solve/defaults.lp +++ b/src/constraint_handler/data/6_solve/defaults.lp @@ -28,15 +28,15 @@ _default_apply(X,D,C,P) :- _passed(solve,LBL,variable_default(X,D,C,P)), not -_d %%%%%% mode depends % Collect all variables that occur in ensure declarations. -_default_ensureVariable(E,X) :- _passed(solve,LBL,ensure(E)), _default_mode(depends), X=@pythonExpressionVariable(E). +_default_ensureVariable(E,X) :- ch_core(ensure(E),LBL), _default_mode(depends), X=@pythonExpressionVariable(E). _default_dependVariable(E,X) :- _default_ensureVariable(E,X), _passed(solve,LBL,variable_declare(X,open)). _default_connect(X,Y) :- _default_dependVariable(E,X), _default_ensureVariable(E,Y), X != Y. -_default_connect(X,X) :- _passed(solve,LBL,variable_declare(X,open)), _default_mode(depends). +_default_connect(X,X) :- ch_core(variable_declare(X,open),LBL), _default_mode(depends). -_default_apply(X,D,C,P) :- - _passed(solve,LBL,variable_default(X,D,C,P)), - _passed(solve,LBL2,variable_assign(Y,E)), + ch_core(variable_default(X,D,C,P),LBL), + ch_core(variable_assign(Y,E),LBL2), _default_connect(X,Y), _default_mode(depends). diff --git a/src/constraint_handler/data/6_solve/ensure.lp b/src/constraint_handler/data/6_solve/ensure.lp new file mode 100644 index 00000000..933fd00b --- /dev/null +++ b/src/constraint_handler/data/6_solve/ensure.lp @@ -0,0 +1,8 @@ +:- _passed(ENG,LBL,ensure(E)), not _shared_value(E,val(bool,true)), not _shared_value(E,bad), _engine_grounding(ENG). +_passed(solve,LBL,ensure(E)) :- _phase_active(solve), ch_core(ensure(E),LBL). +_passed(solve,LBL,share_value(E)) :- _phase_active(solve), ch_core(ensure(E),LBL). +propagator_ensure(EXPR,LBL) :- ch_core(ensure(EXPR),LBL), _engine(propagator,LBL). + +%_passed(solve,LBL,share_value(E)) :- _phase_active(solve), ch_core(ensure(E),LBL). +%_passed(solve,LBL,bool_evaluate(E)) :- _phase_active(solve), ch_core(ensure(E),LBL). +%:- _phase_active(solve), ch_core(ensure(E),LBL), not bool_evaluated(E,val(bool,true)), not bool_evaluated(E,bad). diff --git a/src/constraint_handler/data/6_solve/evaluate.lp b/src/constraint_handler/data/6_solve/evaluate.lp new file mode 100644 index 00000000..aa9f3d31 --- /dev/null +++ b/src/constraint_handler/data/6_solve/evaluate.lp @@ -0,0 +1,9 @@ +_passed(solve,LBL,share_value(E)) :- _phase_active(solve), ch_core(evaluate(REF,E),LBL). +_evaluate(REF,E) :- ch_core(evaluate(REF,E),LBL), _engine(ENG,LBL), _engine_grounding(ENG). + +evaluated(REF,V) :- _evaluate(REF,E), _shared_value(E,V). +evaluated(REF,bad) :- _evaluate(REF,E), #false: _shared_value(E,V). + +_evaluate(REF,E) :- ch_core(evaluate(REF,E),LBL), _engine(ENG,LBL), _engine_grounding(ENG). + +_passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=evaluate(REF,E). diff --git a/src/constraint_handler/data/6_solve/optimize.lp b/src/constraint_handler/data/6_solve/optimize.lp index 4a69f518..62a0e0c8 100644 --- a/src/constraint_handler/data/6_solve/optimize.lp +++ b/src/constraint_handler/data/6_solve/optimize.lp @@ -1 +1,8 @@ -#maximize { I@P,ID : _optimize_component(E,ORIG,PREC,ID,P,LBL), _shared_value(E,val(int,I)) }. +_passed(solve,LBL,share_value(E;O;P)) :- _phase_active(solve), ch_core(optimize_component(E,O,P,ID,PRIORITY),LBL). + +propagator_optimize_maximizeSum(E,ID,PRIO,LBL) :- _phase_active(solve), ch_core(optimize_component(E,ORIG,PREC,ID,PRIO),LBL), _engine(propagator,LBL). +%propagator_optimize_maximizeSum(E,ID,PRIO,LBL) :- _passed(solve,LBL,optimize_component(E,ORIG,PREC,ID,PRIO)), _engine(propagator,LBL). + +_optimize_component(E,ORIG,PREC,ID,PRIORITY,LBL) :- _phase_active(solve), ch_core(optimize_component(E,ORIG,PREC,ID,PRIORITY),LBL), _engine(ENG,LBL), _engine_supportOptimization(ENG). + +#maximize { I@PRIORITY,ID : ch_core(optimize_component(E,ORIG,PREC,ID,PRIORITY),LBL), _shared_value(E,val(int,I)) }. diff --git a/src/constraint_handler/data/6_solve/preference.lp b/src/constraint_handler/data/6_solve/preference.lp index 92a968e4..4e66a86f 100644 --- a/src/constraint_handler/data/6_solve/preference.lp +++ b/src/constraint_handler/data/6_solve/preference.lp @@ -2,8 +2,9 @@ _warning(preference(unsupported),LBL1,("multiple scores for the same expression",E,K1,K2)) :- _passed(sugar,LBL1,preference_holds(E,K1)), _passed(sugar,LBL2,preference_holds(E,K2)), K1 < K2. -_preference_expressionScore(E,K) :- _passed(solve,LBL,preference_holds(E,K)). -_passed(solve,LBL,bool_evaluate(E)) :- _passed(solve,LBL,preference_holds(E,K)). +_passed(solve,LBL,share_value(E)) :- _phase_active(solve), ch_core(preference_holds(E,K),LBL). +_preference_expressionScore(E,K) :- _phase_active(solve), ch_core(preference_holds(E,K),LBL). +_passed(solve,LBL,bool_evaluate(E)) :- _phase_active(solve), ch_core(preference_holds(E,K),LBL). _preference_expression(E) :- _preference_expressionScore(E,K). diff --git a/src/constraint_handler/data/6_solve/propagator/propagator.lp b/src/constraint_handler/data/6_solve/propagator/propagator.lp index 9c8f16dd..e82ec30e 100644 --- a/src/constraint_handler/data/6_solve/propagator/propagator.lp +++ b/src/constraint_handler/data/6_solve/propagator/propagator.lp @@ -1,5 +1,4 @@ propagator_bool_evaluate(E,LBL) :- _passed(propagator,LBL,bool_evaluate(E)). -propagator_ensure(E,LBL) :- _passed(propagator,LBL,ensure(E)). propagator_evaluate(REF,EXPR,LBL) :- _passed(propagator,LBL,evaluate(REF,EXPR)). @@ -47,7 +46,6 @@ propagator_ensure(operation(set_notin,(E,(variable(X),()))),CNAME) :- _passed(pr propagator_multimap_assign(X,K,V,LBL) :- _passed(propagator,LBL,multimap_assign(X,K,V)). propagator_multimap_declare(X,LBL) :- _passed(propagator,LBL,variable_declare(X,multimap)). -propagator_optimize_maximizeSum(E,ID,PRIO,LBL) :- _passed(propagator,LBL,optimize_component(E,ORIG,PREC,ID,PRIO)). propagator_share_value(E,LBL) :- _passed(propagator,LBL,share_value(E)). propagator_warning_forbid(KIND,LBL) :- _warning_forbid(KIND,LBL). diff --git a/src/constraint_handler/data/7_output/value.lp b/src/constraint_handler/data/7_output/value.lp index 20a6a924..a6a11293 100644 --- a/src/constraint_handler/data/7_output/value.lp +++ b/src/constraint_handler/data/7_output/value.lp @@ -5,11 +5,6 @@ value(X,V) :- _se_value(variable(X),V), V != set, _passed(solve,LBL,variable_int _shared_value(E,V) :- _passed(ENG,LBL,share_value(E)), _se_value(E,V), _engine_grounding(ENG). %_shared_value(E,V) :- _passed(share,LBL,share_value(E)), _se_value(E,V). -evaluated(REF,V) :- _evaluate(REF,E), _shared_value(E,V). -evaluated(REF,bad) :- _evaluate(REF,E), #false: _shared_value(E,V). - -:- _passed(ENG,LBL,ensure(E)), not _shared_value(E,val(bool,true)), not _shared_value(E,bad), _engine_grounding(ENG). - _se_value1(variable(X)) :- _se_value(variable(X),V), _passed(compile,LBL,variable_interface(X)). value(X,bad) :- _expression(compile,variable(X)), not _se_value1(variable(X)). diff --git a/src/constraint_handler/data/main.lp b/src/constraint_handler/data/main.lp index e043086e..8bd4724f 100644 --- a/src/constraint_handler/data/main.lp +++ b/src/constraint_handler/data/main.lp @@ -21,4 +21,4 @@ _parameter_value(PARAM,VAL) :- _parameter_default(PARAM,VAL), not _parameter_use _parameter_value(PARAM,VAL) :- parameter_request(PARAM,VAL). %%%%%%%%%%%%%%%%% version -version("0.0.6"). +version("0.0.8"). diff --git a/src/constraint_handler/main.py b/src/constraint_handler/main.py index 266aa182..1435f30c 100644 --- a/src/constraint_handler/main.py +++ b/src/constraint_handler/main.py @@ -106,6 +106,8 @@ m6_solve = ( [ "6_solve/defaults", + "6_solve/ensure", + "6_solve/evaluate", "6_solve/finiteDomain", "6_solve/optimize", "6_solve/preference", From a94d7409c1c407a54ef261755e8083eb818e4a9e Mon Sep 17 00:00:00 2001 From: Abdallah Saffidine Date: Wed, 23 Sep 2026 16:55:24 +1000 Subject: [PATCH 08/18] remove ensure from engine language. --- src/constraint_handler/data/6_solve/README.md | 2 -- src/constraint_handler/data/6_solve/compile/direct.lp | 2 +- src/constraint_handler/data/6_solve/compile/int.lp | 2 +- src/constraint_handler/data/6_solve/ensure.lp | 9 ++------- src/constraint_handler/data/6_solve/ground/README.md | 1 - src/constraint_handler/data/6_solve/propagator/README.md | 1 - .../data/6_solve/propagator/propagator.lp | 2 +- tests/test_encoding.py | 2 +- 8 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/constraint_handler/data/6_solve/README.md b/src/constraint_handler/data/6_solve/README.md index 72f109bf..c7a59cde 100644 --- a/src/constraint_handler/data/6_solve/README.md +++ b/src/constraint_handler/data/6_solve/README.md @@ -36,10 +36,8 @@ _variable_indexedDomain/3. ### Output predicates _ge_assign/2. -_passed(compile,LBL,ensure/1). _passed(compile,LBL,variable_declare/2). _passed(compile,LBL,variable_define/2). -_passed(ground,LBL,ensure/1). _passed(ground,LBL,variable_declare/2). _passed(ground,LBL,variable_define/2). _se_value/2. diff --git a/src/constraint_handler/data/6_solve/compile/direct.lp b/src/constraint_handler/data/6_solve/compile/direct.lp index f5ea4d72..cd6ec7a8 100644 --- a/src/constraint_handler/data/6_solve/compile/direct.lp +++ b/src/constraint_handler/data/6_solve/compile/direct.lp @@ -1,4 +1,4 @@ -%%%%%%%%%%%%%%%%% interface ensure/2 variable_define/3 +%%%%%%%%%%%%%%%%% interface variable_define/3 direct_query(E) :- _expression(compile,LBL,DECL,E). direct_query(SE) :- direct_query(operation(OP,ES)), not _direct_lazy(OP), _expression_operationIndex(compile,operation(OP,ES),IDX,SE). direct_query(SE) :- direct_query(E), _expression_tupleIndex(compile,E,IDX,SE). diff --git a/src/constraint_handler/data/6_solve/compile/int.lp b/src/constraint_handler/data/6_solve/compile/int.lp index fb28da5b..5c8f9458 100644 --- a/src/constraint_handler/data/6_solve/compile/int.lp +++ b/src/constraint_handler/data/6_solve/compile/int.lp @@ -9,7 +9,7 @@ _computedIdx(operation(add,ARGS),val(int,N)) :- _computeIdx(operation(add,ARGS),add), _expression_operationLength(compile,operation(add,ARGS),LEN), LEN > 2, %%% LEN = #count { IDX : _computeIdx(operation(add,ARGS),IDX,val((bool;int;none),V)) }, - LEN = #count { IDX : _computeIdx(operation(add,ARGS),IDX,val((bool;int),V)) }, %%% ensures there are no floats + LEN = #count { IDX : _computeIdx(operation(add,ARGS),IDX,val((bool;int),V)) }, %%% makes sure there are no floats N = #sum { V,IDX : _computeIdx(operation(add,ARGS),IDX,val(int,V)); 1,IDX : _computeIdx(operation(add,ARGS),IDX,val(bool,true)) }. diff --git a/src/constraint_handler/data/6_solve/ensure.lp b/src/constraint_handler/data/6_solve/ensure.lp index 933fd00b..bf424b94 100644 --- a/src/constraint_handler/data/6_solve/ensure.lp +++ b/src/constraint_handler/data/6_solve/ensure.lp @@ -1,8 +1,3 @@ -:- _passed(ENG,LBL,ensure(E)), not _shared_value(E,val(bool,true)), not _shared_value(E,bad), _engine_grounding(ENG). -_passed(solve,LBL,ensure(E)) :- _phase_active(solve), ch_core(ensure(E),LBL). _passed(solve,LBL,share_value(E)) :- _phase_active(solve), ch_core(ensure(E),LBL). -propagator_ensure(EXPR,LBL) :- ch_core(ensure(EXPR),LBL), _engine(propagator,LBL). - -%_passed(solve,LBL,share_value(E)) :- _phase_active(solve), ch_core(ensure(E),LBL). -%_passed(solve,LBL,bool_evaluate(E)) :- _phase_active(solve), ch_core(ensure(E),LBL). -%:- _phase_active(solve), ch_core(ensure(E),LBL), not bool_evaluated(E,val(bool,true)), not bool_evaluated(E,bad). +_passed(solve,LBL,bool_evaluate(E)) :- _phase_active(solve), ch_core(ensure(E),LBL). +:- _phase_active(solve), ch_core(ensure(E),LBL), not bool_evaluated(E,val(bool,true)), not bool_evaluated(E,bad). diff --git a/src/constraint_handler/data/6_solve/ground/README.md b/src/constraint_handler/data/6_solve/ground/README.md index 388e7a05..3b0f2c03 100644 --- a/src/constraint_handler/data/6_solve/ground/README.md +++ b/src/constraint_handler/data/6_solve/ground/README.md @@ -1,6 +1,5 @@ ### Input predicates -_passed(ground,LBL,ensure/1). _passed(ground,LBL,variable_assign/4). _passed(ground,LBL,variable_choice/4). _passed(ground,LBL,variable_declare/2). diff --git a/src/constraint_handler/data/6_solve/propagator/README.md b/src/constraint_handler/data/6_solve/propagator/README.md index e60b6a05..27a2494a 100644 --- a/src/constraint_handler/data/6_solve/propagator/README.md +++ b/src/constraint_handler/data/6_solve/propagator/README.md @@ -1,7 +1,6 @@ ### Input predicates _passed(propagator,LBL,bool_evaluate/1). -_passed(propagator,LBL,ensure/1). _passed(propagator,LBL,evaluate/2). _passed(propagator,LBL,variable_assign/2). _passed(propagator,LBL,variable_choice/2). diff --git a/src/constraint_handler/data/6_solve/propagator/propagator.lp b/src/constraint_handler/data/6_solve/propagator/propagator.lp index e82ec30e..06dd1249 100644 --- a/src/constraint_handler/data/6_solve/propagator/propagator.lp +++ b/src/constraint_handler/data/6_solve/propagator/propagator.lp @@ -40,7 +40,7 @@ propagator_set_assign(X,E,CNAME) :- _passed(propagator,CNAME,set_assign(X,E)). {propagator_set_baseDomain(X,E,CNAME1) : _passed(propagator,CNAME1,set_baseDomain(X,E))} :- propagator_set_declare(X,CNAME2). -% ensure that value of expr is not in set if not chosen +% make sure that value of expr is not in set if not chosen propagator_ensure(operation(set_notin,(E,(variable(X),()))),CNAME) :- _passed(propagator,CNAME,set_baseDomain(X,E)), not propagator_set_baseDomain(X,E,CNAME). propagator_multimap_assign(X,K,V,LBL) :- _passed(propagator,LBL,multimap_assign(X,K,V)). diff --git a/tests/test_encoding.py b/tests/test_encoding.py index 09def1c7..5e64aea2 100644 --- a/tests/test_encoding.py +++ b/tests/test_encoding.py @@ -617,7 +617,7 @@ def run_test(name: str, selected_engine: engine.Engine): "warning/bad_interface", } -propagator_true_skip: set[str] = propagator_skip | set() +propagator_true_skip: set[str] = propagator_skip | {"execution/python_integrity_should_be_ignored"} propagator_true_xfail: set[str] = propagator_xfail | set() engine_test_configs: list[tuple[engine.Engine, set[str], set[str]]] = [ From 457261eae5da7d5c67a1a786852b6be9ce3d49dc Mon Sep 17 00:00:00 2001 From: Abdallah Saffidine Date: Wed, 23 Sep 2026 20:14:17 +1000 Subject: [PATCH 09/18] distinguish interface bool_evaluate from internal _bool_evaluate --- src/constraint_handler/data/6_solve/ensure.lp | 4 ++-- src/constraint_handler/data/6_solve/preference.lp | 6 +++--- .../data/6_solve/propagator/propagator.lp | 1 - .../data/7_output/bool_evaluate.lp | 12 ++++++++---- src/constraint_handler/propagator.py | 2 +- src/constraint_handler/schemas/internal.py | 10 ++++++++++ src/constraint_handler/schemas/propagator_atom.py | 1 - .../core/bool_evaluate/internal.expected.all | 1 + tests/correctness/core/bool_evaluate/internal.lp | 5 +++++ tests/test_encoding.py | 1 + 10 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 tests/correctness/core/bool_evaluate/internal.expected.all create mode 100644 tests/correctness/core/bool_evaluate/internal.lp diff --git a/src/constraint_handler/data/6_solve/ensure.lp b/src/constraint_handler/data/6_solve/ensure.lp index bf424b94..44016ad4 100644 --- a/src/constraint_handler/data/6_solve/ensure.lp +++ b/src/constraint_handler/data/6_solve/ensure.lp @@ -1,3 +1,3 @@ _passed(solve,LBL,share_value(E)) :- _phase_active(solve), ch_core(ensure(E),LBL). -_passed(solve,LBL,bool_evaluate(E)) :- _phase_active(solve), ch_core(ensure(E),LBL). -:- _phase_active(solve), ch_core(ensure(E),LBL), not bool_evaluated(E,val(bool,true)), not bool_evaluated(E,bad). +_bool_evaluate(E,LBL) :- _phase_active(solve), ch_core(ensure(E),LBL). +:- _phase_active(solve), ch_core(ensure(E),LBL), not _bool_evaluated(E,val(bool,true)), not _bool_evaluated(E,bad). diff --git a/src/constraint_handler/data/6_solve/preference.lp b/src/constraint_handler/data/6_solve/preference.lp index 4e66a86f..0bfe7b17 100644 --- a/src/constraint_handler/data/6_solve/preference.lp +++ b/src/constraint_handler/data/6_solve/preference.lp @@ -4,7 +4,7 @@ _warning(preference(unsupported),LBL1,("multiple scores for the same expression" _passed(solve,LBL,share_value(E)) :- _phase_active(solve), ch_core(preference_holds(E,K),LBL). _preference_expressionScore(E,K) :- _phase_active(solve), ch_core(preference_holds(E,K),LBL). -_passed(solve,LBL,bool_evaluate(E)) :- _phase_active(solve), ch_core(preference_holds(E,K),LBL). +_bool_evaluate(E,LBL) :- _phase_active(solve), ch_core(preference_holds(E,K),LBL). _preference_expression(E) :- _preference_expressionScore(E,K). @@ -18,7 +18,7 @@ _preference_potentialAux(IDX+1,W) :- _preference_potentialAux(IDX,W), _prefere _preference_potentialAux(IDX+1,W+K) :- _preference_potentialAux(IDX,W), _preference_index(E,IDX), _preference_expressionScore(E, K), K > 0. _preference_potentialScore(W) :- _preference_potentialAux(IDX,W), not _preference_potentialAux(IDX+1,W). -preference_score(W) :- preference_maximizeScore, W = #sum { K,E : bool_evaluated(E,val(bool,true)), _preference_expressionScore(E,K), K > 0 }. +preference_score(W) :- preference_maximizeScore, W = #sum { K,E : _bool_evaluated(E,val(bool,true)), _preference_expressionScore(E,K), K > 0 }. -#heuristic bool_evaluated(E,val(bool,true)) : _preference_expressionScore(E,K). [1,true] +#heuristic _bool_evaluated(E,val(bool,true)) : _preference_expressionScore(E,K). [1,true] #heuristic preference_score(W) : _preference_potentialScore(W),W>0. [1+W,true] diff --git a/src/constraint_handler/data/6_solve/propagator/propagator.lp b/src/constraint_handler/data/6_solve/propagator/propagator.lp index 06dd1249..5de196d1 100644 --- a/src/constraint_handler/data/6_solve/propagator/propagator.lp +++ b/src/constraint_handler/data/6_solve/propagator/propagator.lp @@ -1,4 +1,3 @@ -propagator_bool_evaluate(E,LBL) :- _passed(propagator,LBL,bool_evaluate(E)). propagator_evaluate(REF,EXPR,LBL) :- _passed(propagator,LBL,evaluate(REF,EXPR)). diff --git a/src/constraint_handler/data/7_output/bool_evaluate.lp b/src/constraint_handler/data/7_output/bool_evaluate.lp index 8e840a6a..cebf5674 100644 --- a/src/constraint_handler/data/7_output/bool_evaluate.lp +++ b/src/constraint_handler/data/7_output/bool_evaluate.lp @@ -1,7 +1,11 @@ %%%%%%%%%%%%%%%%% bool_evaluate -1 { bool_evaluated(E,(bad;val(bool,(true;false)))) } :- _passed(propagator,LBL,bool_evaluate(E)). -bool_evaluated(E,V) :- _passed((compile;compile2;ground),LBL,bool_evaluate(E)), _se_value(E,V), V=(bad;val(bool,(true;false))). +propagator_bool_evaluate(E,LBL) :- _bool_evaluate(E,LBL), _engine(propagator,LBL). +1 { _bool_evaluated(E,(bad;val(bool,(true;false)))) } 1 :- _bool_evaluate(E,LBL), _engine(propagator,LBL). +_bool_evaluated(E,V) :- _bool_evaluate(E,LBL), _se_value(E,V), V=(bad;val(bool,(true;false))). -:- _engine(ENG), _passed(ENG,LBL,bool_evaluate(E)), bool_evaluated(E,V0), bool_evaluated(E,V1), V0 < V1, V0=(bad;val(bool,(true;false))), V1=(bad;val(bool,(true;false))). +:- bool_evaluated(E,V0), bool_evaluated(E,V1), V0 < V1, V0=(bad;val(bool,(true;false))), V1=(bad;val(bool,(true;false))). -:- _engine(ENG), _passed(ENG,LBL,bool_evaluate(E)), bool_evaluated(E,V), V!=bad, V!=val(bool,true), V!=val(bool,false). +:- bool_evaluated(E,V), V!=bad, V!=val(bool,true), V!=val(bool,false). + +_bool_evaluate(E,LBL) :- _phase_active(solve), ch_core(bool_evaluate(E),LBL). +bool_evaluated(E,V) :- ch_core(bool_evaluate(E),LBL), _bool_evaluated(E,V). diff --git a/src/constraint_handler/propagator.py b/src/constraint_handler/propagator.py index 3ded67a7..b450c07b 100644 --- a/src/constraint_handler/propagator.py +++ b/src/constraint_handler/propagator.py @@ -1379,7 +1379,7 @@ def get_evaluate(self, ctl: clingo.PropagateInit): evaluate_atoms = myClorm.findInPropagateInit(ctl, prop_atom.Propagator_evaluate) bool_evaluate_atoms = myClorm.findInPropagateInit(ctl, prop_atom.Propagator_bool_evaluate) - bool_evaluated_atoms = myClorm.findInPropagateInit(ctl, prop_atom.Bool_evaluated) + bool_evaluated_atoms = myClorm.findInPropagateInit(ctl, internal._bool_evaluated) for (ref, expr, _), literal in evaluate_atoms.items(): var = EvaluateVariable(ref, expr, literal) self.evaluatevars.append(var) diff --git a/src/constraint_handler/schemas/internal.py b/src/constraint_handler/schemas/internal.py index 3106a9cb..e7c86de0 100644 --- a/src/constraint_handler/schemas/internal.py +++ b/src/constraint_handler/schemas/internal.py @@ -27,6 +27,16 @@ class _se_value(NamedTuple): val: expression.Val | Ref +class _bool_evaluate(NamedTuple): + expr: expression.Expr + label: expression.constant + + +class _bool_evaluated(NamedTuple): + expr: expression.Expr + value: expression.ReducedExpr + + class _shared_value(NamedTuple): expr: expression.Expr val: expression.ReducedExpr diff --git a/src/constraint_handler/schemas/propagator_atom.py b/src/constraint_handler/schemas/propagator_atom.py index 75b4454b..209ff2f9 100644 --- a/src/constraint_handler/schemas/propagator_atom.py +++ b/src/constraint_handler/schemas/propagator_atom.py @@ -8,7 +8,6 @@ import constraint_handler.schemas.result as result import constraint_handler.schemas.warning as warning -Bool_evaluated = result.Bool_evaluated Evaluated = result.Evaluated Multimap_value = result.Multimap_value Set_value = result.Set_value diff --git a/tests/correctness/core/bool_evaluate/internal.expected.all b/tests/correctness/core/bool_evaluate/internal.expected.all new file mode 100644 index 00000000..ea8d2865 --- /dev/null +++ b/tests/correctness/core/bool_evaluate/internal.expected.all @@ -0,0 +1 @@ +works \ No newline at end of file diff --git a/tests/correctness/core/bool_evaluate/internal.lp b/tests/correctness/core/bool_evaluate/internal.lp new file mode 100644 index 00000000..aa5dec9d --- /dev/null +++ b/tests/correctness/core/bool_evaluate/internal.lp @@ -0,0 +1,5 @@ +ensure(val(bool,true)). + +:- bool_evaluated(_,_). + +works. \ No newline at end of file diff --git a/tests/test_encoding.py b/tests/test_encoding.py index 5e64aea2..8d0573fc 100644 --- a/tests/test_encoding.py +++ b/tests/test_encoding.py @@ -36,6 +36,7 @@ def run_test(name: str, selected_engine: engine.Engine): "core/bool_evaluate/forbidden", "core/bool_evaluate/immediate", "core/bool_evaluate/inconsistent", + "core/bool_evaluate/internal", "core/basic_assignments", "core/boolean_shortcut_optional_presence", "core/conditional_assign", From 11af992841976f40423cf5840502537e45648a82 Mon Sep 17 00:00:00 2001 From: Abdallah Saffidine Date: Thu, 24 Sep 2026 12:54:59 +1000 Subject: [PATCH 10/18] clean-up internal variable marking --- src/constraint_handler/data/3_sugar/sugar.lp | 23 ++----------------- .../data/4_analysis/type_checking/type.lp | 2 +- .../data/5_presolve/core.lp | 3 ++- .../data/6_solve/propagator/propagator.lp | 2 +- .../data/7_output/bad_value.lp | 2 +- src/constraint_handler/data/7_output/value.lp | 20 ++++++++-------- .../core/bool_evaluate/internal.expected.all | 2 +- .../core/bool_evaluate/internal.lp | 2 +- 8 files changed, 20 insertions(+), 36 deletions(-) diff --git a/src/constraint_handler/data/3_sugar/sugar.lp b/src/constraint_handler/data/3_sugar/sugar.lp index 24d03abf..8171064b 100644 --- a/src/constraint_handler/data/3_sugar/sugar.lp +++ b/src/constraint_handler/data/3_sugar/sugar.lp @@ -5,9 +5,6 @@ _passed(sugar,LBL,ensure(E)) :- _passed(defaultArgs,LBL,ensure(E)). _passed(sugar,LBL,evaluate(E,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). _passed(sugar,LBL,variable_declare(X,fromFacts)) :- _passed(defaultArgs,LBL,variable_declare(X,boolDomain)). @@ -16,37 +13,28 @@ _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_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)), @@ -67,14 +55,7 @@ _passed(sugar,LBL,preference_holds(E,K)) :- _sugar_aux(LBL,preference_holds(E,K) _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). - - -%%%%%% 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)). diff --git a/src/constraint_handler/data/4_analysis/type_checking/type.lp b/src/constraint_handler/data/4_analysis/type_checking/type.lp index 9a6a0ef6..7c590cb6 100644 --- a/src/constraint_handler/data/4_analysis/type_checking/type.lp +++ b/src/constraint_handler/data/4_analysis/type_checking/type.lp @@ -78,7 +78,7 @@ _type_nonMinimal(E,W) :- _expression_operationIndex(type_check,E,IDX,ARG), _type _type_nonMinimal(E,W) :- _expression_tupleIndex(type_check,E,IDX,ARG), _type_warning(ARG,W). _warning(type(W),(),E) :- _type_warning(E,W), not _type_nonMinimal(E,W). -_warning(type(W),LBL,variable(X)) :- _type_warning(variable(X),W), _passed(sugar,LBL,variable_interface(X)). +_warning(type(W),LBL,variable(X)) :- _type_warning(variable(X),W), _variable_interface(X,LBL). type_expression(E,T) :- _type_expression(E,T), T != bot, not _type_expression(E,top). type_expression(E,top) :- _type_expression(E,top). diff --git a/src/constraint_handler/data/5_presolve/core.lp b/src/constraint_handler/data/5_presolve/core.lp index 7069bb26..aeb174b1 100644 --- a/src/constraint_handler/data/5_presolve/core.lp +++ b/src/constraint_handler/data/5_presolve/core.lp @@ -10,7 +10,8 @@ _passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=set_bas _passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=multimap_assign(X,K,B). _passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=share_value(E). _passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=optimize_component(E,O,P,X,PRIORITY). -_passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=variable_interface(X). + +_variable_interface(X,LBL) :- ch_core(variable_declare(X,D),LBL), #false: X=loc(V). _passed(solve,LBL,share_value(E)) :- _phase_active(solve), ch_core(bool_evaluate(E),LBL). %_passed(solve,LBL,share_value(E)) :- _phase_active(solve), ch_core(evaluate(REF,E),LBL). diff --git a/src/constraint_handler/data/6_solve/propagator/propagator.lp b/src/constraint_handler/data/6_solve/propagator/propagator.lp index 5de196d1..9a9930d8 100644 --- a/src/constraint_handler/data/6_solve/propagator/propagator.lp +++ b/src/constraint_handler/data/6_solve/propagator/propagator.lp @@ -50,4 +50,4 @@ propagator_share_value(E,LBL) :- _passed(propagator,LBL,share_value(E)). propagator_warning_forbid(KIND,LBL) :- _warning_forbid(KIND,LBL). propagator_warning_ignore(KIND,LBL) :- _warning_ignore(KIND,LBL). -propagator_variable_interface(X,LBL) :- _passed(propagator,LBL,variable_interface(X)). +propagator_variable_interface(X,LBL) :- _variable_interface(X,LBL). diff --git a/src/constraint_handler/data/7_output/bad_value.lp b/src/constraint_handler/data/7_output/bad_value.lp index 0d4f5a31..0ccc3f0d 100644 --- a/src/constraint_handler/data/7_output/bad_value.lp +++ b/src/constraint_handler/data/7_output/bad_value.lp @@ -1 +1 @@ -_warning(variable(badValue),LBL,X) :- _se_value(variable(X),bad), _passed(sugar,LBL,variable_interface(X)). +_warning(variable(badValue),LBL,X) :- _se_value(variable(X),bad), _variable_interface(X,LBL). diff --git a/src/constraint_handler/data/7_output/value.lp b/src/constraint_handler/data/7_output/value.lp index a6a11293..7b34ead9 100644 --- a/src/constraint_handler/data/7_output/value.lp +++ b/src/constraint_handler/data/7_output/value.lp @@ -1,14 +1,16 @@ -set_value(X,V) :- _se_value(variable(X),set), _set_contains(variable(X),V), _passed(solve,LBL,variable_interface(X)). %%% for compile2 -set_value(X,V) :- _se_value(variable(X),ref(set,E)), _set_contains(E,V), _passed(solve,LBL,variable_interface(X)). -value(X,V) :- _se_value(variable(X),V), V != set, _passed(solve,LBL,variable_interface(X)). +set_value(X,V) :- _se_value(variable(X),set), _set_contains(variable(X),V), _variable_interface(X,LBL). %%% for compile2 +set_value(X,V) :- _se_value(variable(X),ref(set,E)), _set_contains(E,V), _variable_interface(X,LBL). +value(X,V) :- _se_value(variable(X),V), V != set, _variable_interface(X,LBL). _shared_value(E,V) :- _passed(ENG,LBL,share_value(E)), _se_value(E,V), _engine_grounding(ENG). %_shared_value(E,V) :- _passed(share,LBL,share_value(E)), _se_value(E,V). -_se_value1(variable(X)) :- _se_value(variable(X),V), _passed(compile,LBL,variable_interface(X)). -value(X,bad) :- _expression(compile,variable(X)), not _se_value1(variable(X)). +_se_value1(variable(X)) :- _se_value(variable(X),V), _variable_interface(X,LBL). +value(X,bad) :- _variable_interface(X,LBL), _expression(compile,variable(X)), not _se_value1(variable(X)). -type_variableD(X,T) :- _se_value(variable(X),val(T,V)), _passed(solve,LBL,variable_interface(X)). -type_variableD(X,set) :- _se_value(variable(X),set), _passed(solve,LBL,variable_interface(X)). -type_variableD(X,set) :- _se_value(variable(X),ref(set,R)), _passed(solve,LBL,variable_interface(X)). -type_variableD(X,bot) :- value(X,bad), _passed(solve,LBL,variable_interface(X)). +_type_variableD(X,T) :- _se_value(variable(X),val(T,V)). +_type_variableD(X,set) :- _se_value(variable(X),set). +_type_variableD(X,set) :- _se_value(variable(X),ref(set,R)). +_type_variableD(X,bot) :- value(X,bad). + +type_variableD(X,T) :- _type_variableD(X,T), _variable_interface(X,LBL). diff --git a/tests/correctness/core/bool_evaluate/internal.expected.all b/tests/correctness/core/bool_evaluate/internal.expected.all index ea8d2865..153d1940 100644 --- a/tests/correctness/core/bool_evaluate/internal.expected.all +++ b/tests/correctness/core/bool_evaluate/internal.expected.all @@ -1 +1 @@ -works \ No newline at end of file +works diff --git a/tests/correctness/core/bool_evaluate/internal.lp b/tests/correctness/core/bool_evaluate/internal.lp index aa5dec9d..047af1bb 100644 --- a/tests/correctness/core/bool_evaluate/internal.lp +++ b/tests/correctness/core/bool_evaluate/internal.lp @@ -2,4 +2,4 @@ ensure(val(bool,true)). :- bool_evaluated(_,_). -works. \ No newline at end of file +works. From af60133ee064ce89eb0c6461c292699b78d86346 Mon Sep 17 00:00:00 2001 From: Abdallah Saffidine Date: Thu, 24 Sep 2026 15:06:45 +1000 Subject: [PATCH 11/18] implement set_baseDomain as a feature --- src/constraint_handler/data/5_presolve/core.lp | 3 +-- src/constraint_handler/data/5_presolve/engine.lp | 2 +- .../data/6_solve/compile/set.lp | 5 ----- .../data/6_solve/ground/gringoEval.lp | 2 -- .../data/6_solve/propagator/README.md | 1 - .../data/6_solve/propagator/propagator.lp | 5 ----- src/constraint_handler/data/6_solve/set.lp | 16 ++++++++++++++++ .../data/7_output/bool_evaluate.lp | 1 + src/constraint_handler/main.py | 1 + 9 files changed, 20 insertions(+), 16 deletions(-) create mode 100644 src/constraint_handler/data/6_solve/set.lp diff --git a/src/constraint_handler/data/5_presolve/core.lp b/src/constraint_handler/data/5_presolve/core.lp index aeb174b1..5ac8b62b 100644 --- a/src/constraint_handler/data/5_presolve/core.lp +++ b/src/constraint_handler/data/5_presolve/core.lp @@ -6,14 +6,13 @@ _passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=variabl _passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=variable_define(X,E). _passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=variable_domain(X,E). _passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=set_assign(X,E). -_passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=set_baseDomain(X,E). _passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=multimap_assign(X,K,B). _passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=share_value(E). _passed(solve,LBL,DECL) :- _phase_active(solve), ch_core(DECL,LBL), DECL=optimize_component(E,O,P,X,PRIORITY). _variable_interface(X,LBL) :- ch_core(variable_declare(X,D),LBL), #false: X=loc(V). -_passed(solve,LBL,share_value(E)) :- _phase_active(solve), ch_core(bool_evaluate(E),LBL). +%_passed(solve,LBL,share_value(E)) :- _phase_active(solve), ch_core(bool_evaluate(E),LBL). %_passed(solve,LBL,share_value(E)) :- _phase_active(solve), ch_core(evaluate(REF,E),LBL). %_passed(solve,LBL,share_value(E)) :- _phase_active(solve), ch_core(ensure(E),LBL). %_passed(solve,LBL,share_value(E)) :- _phase_active(solve), ch_core(preference_holds(E,K),LBL). diff --git a/src/constraint_handler/data/5_presolve/engine.lp b/src/constraint_handler/data/5_presolve/engine.lp index 4b55481f..0cc5183f 100644 --- a/src/constraint_handler/data/5_presolve/engine.lp +++ b/src/constraint_handler/data/5_presolve/engine.lp @@ -7,7 +7,7 @@ _engine_default(ENG) :- ch_core(engine_request(ENG),_label_anonymous). _engine_defaultProvided :- ch_core(engine_request(ENG),_label_anonymous). _engine_default(compile) :- not _engine_defaultProvided. -_label(LBL) :- _label(DECL,LBL). +_label(LBL) :- ch_core(DECL,LBL). _engine_userRequest(LBL) :- ch_core(engine_request(ENG),LBL). _engine(ENG,LBL) :- ch_core(engine_request(ENG),LBL). _engine(ENG,LBL) :- _engine_default(ENG), not _engine_userRequest(LBL), _label(LBL). diff --git a/src/constraint_handler/data/6_solve/compile/set.lp b/src/constraint_handler/data/6_solve/compile/set.lp index d36bf587..df4eed26 100644 --- a/src/constraint_handler/data/6_solve/compile/set.lp +++ b/src/constraint_handler/data/6_solve/compile/set.lp @@ -18,11 +18,6 @@ _set_contains(EX,V1) :- _set_assign(EX,S) :- _set_assign(EX,ref(set,S)). -%%%%%%%%%%%%%%%%% set_baseDomain -_passed(correction(setSymmetry,add),LBL,share_value(operation(set_isin,(E,(variable(X),()))))) :- _passed(sugar,LBL,set_baseDomain(X,E)). -{ _set_assign(variable(X),E) } :- _passed(compile,LBL,set_baseDomain(X,E)). -:- _passed(compile,LBL,set_baseDomain(X,E)), _shared_value(operation(set_isin,(E,(variable(X),()))),val(bool,true)), not _set_assign(variable(X),E). - %%%%%%%%%%%%%%%%% set_isin set_notin direct_query(operation(eq,(V1,(V2,())))) :- _computeIdx(E,(set_isin;set_notin)), _computeIdx(E,0,V1), _computeIdx(E,1,ref(set,S)), _set_contains(S,V2). diff --git a/src/constraint_handler/data/6_solve/ground/gringoEval.lp b/src/constraint_handler/data/6_solve/ground/gringoEval.lp index 69a843c8..1dadf282 100644 --- a/src/constraint_handler/data/6_solve/ground/gringoEval.lp +++ b/src/constraint_handler/data/6_solve/ground/gringoEval.lp @@ -9,8 +9,6 @@ _expression(ground,E) :- _passed(ground,LBL,share_value(E)). _ge_assign(X,E) :- _passed(ground,LBL,variable_define(X,E)). _ge_set_assign(X,E) :- _passed(ground,LBL,set_assign(X,E)). -{ _ge_set_assign(X,E) } :- _passed(ground,LBL,set_baseDomain(X,E)). -:- _passed(ground,LBL,set_baseDomain(X,E)), _shared_value(operation(set_isin,(E,(variable(X),()))),val(bool,true)), not _ge_set_assign(X,E). _ge_set_declare(X) :- _passed(ground,LBL,variable_declare(X,set)). %%% TODO: make sure set assign doesn't get broken down across different engines diff --git a/src/constraint_handler/data/6_solve/propagator/README.md b/src/constraint_handler/data/6_solve/propagator/README.md index 27a2494a..bc675138 100644 --- a/src/constraint_handler/data/6_solve/propagator/README.md +++ b/src/constraint_handler/data/6_solve/propagator/README.md @@ -33,7 +33,6 @@ propagator_variable_define/3. propagator_variable_interface/2. propagator_set_declare/2. propagator_set_assign/3. -propagator_set_baseDomain/3. propagator_multimap_assign/4. propagator_multimap_declare/2. propagator_optimize_maximizeSum/4. diff --git a/src/constraint_handler/data/6_solve/propagator/propagator.lp b/src/constraint_handler/data/6_solve/propagator/propagator.lp index 9a9930d8..6598788b 100644 --- a/src/constraint_handler/data/6_solve/propagator/propagator.lp +++ b/src/constraint_handler/data/6_solve/propagator/propagator.lp @@ -37,11 +37,6 @@ propagator_variable_define(X,E,CNAME) :- _passed(propagator,CNAME,variable_defin propagator_set_declare(X,CNAME) :- _passed(propagator,CNAME,variable_declare(X,set)). propagator_set_assign(X,E,CNAME) :- _passed(propagator,CNAME,set_assign(X,E)). -{propagator_set_baseDomain(X,E,CNAME1) : _passed(propagator,CNAME1,set_baseDomain(X,E))} :- propagator_set_declare(X,CNAME2). - -% make sure that value of expr is not in set if not chosen -propagator_ensure(operation(set_notin,(E,(variable(X),()))),CNAME) :- _passed(propagator,CNAME,set_baseDomain(X,E)), not propagator_set_baseDomain(X,E,CNAME). - propagator_multimap_assign(X,K,V,LBL) :- _passed(propagator,LBL,multimap_assign(X,K,V)). propagator_multimap_declare(X,LBL) :- _passed(propagator,LBL,variable_declare(X,multimap)). diff --git a/src/constraint_handler/data/6_solve/set.lp b/src/constraint_handler/data/6_solve/set.lp new file mode 100644 index 00000000..a911ac3b --- /dev/null +++ b/src/constraint_handler/data/6_solve/set.lp @@ -0,0 +1,16 @@ +%%%%%%%%%%%%%%%%% set_baseDomain +_set_baseDomain(X,E,LBL) :- _phase_active(solve), ch_core(set_baseDomain(X,E),LBL). + +_passed(compile2,LBL,set_baseDomain(X,E)) :- _set_baseDomain(X,E,LBL), _engine(compile2,LBL). + +_bool_evaluate(operation(set_isin,(E,(variable(X),()))),LBL) :- _set_baseDomain(X,E,LBL), _engine((compile;ground;propagator),LBL). +_passed(solve,LBL,variable_declare(loc(set_baseDomain(LBL,X,E)),fromFacts)) :- _set_baseDomain(X,E,LBL), _engine((compile;ground;propagator),LBL). +_passed(solve,LBL,variable_domain(loc(set_baseDomain(LBL,X,E)),val(bool,(false;true)))) :- _set_baseDomain(X,E,LBL), _engine((compile;ground;propagator),LBL). +_bool_evaluate(variable(loc(set_baseDomain(LBL,X,E))),LBL) :- _set_baseDomain(X,E,LBL), _engine((compile;ground;propagator),LBL). +:- _set_baseDomain(X,E,LBL), _engine((compile;ground;propagator),LBL), + _bool_evaluated(operation(set_isin,(E,(variable(X),()))),val(bool,true)), + not _bool_evaluated(variable(loc(set_baseDomain(LBL,X,E))),val(bool,true)). + +_set_assign(variable(X),E) :- _bool_evaluated(variable(loc(set_baseDomain(LBL,X,E))),val(bool,true)), _engine(compile,LBL). +_ge_set_assign(X,E) :- _bool_evaluated(variable(loc(set_baseDomain(LBL,X,E))),val(bool,true)), _engine(ground,LBL). +propagator_set_assign(X,E,LBL) :- _bool_evaluated(variable(loc(set_baseDomain(LBL,X,E))),val(bool,true)), _engine(propagator,LBL). diff --git a/src/constraint_handler/data/7_output/bool_evaluate.lp b/src/constraint_handler/data/7_output/bool_evaluate.lp index cebf5674..d531b132 100644 --- a/src/constraint_handler/data/7_output/bool_evaluate.lp +++ b/src/constraint_handler/data/7_output/bool_evaluate.lp @@ -1,4 +1,5 @@ %%%%%%%%%%%%%%%%% bool_evaluate +_passed(solve,LBL,share_value(E)) :- _bool_evaluate(E,LBL). propagator_bool_evaluate(E,LBL) :- _bool_evaluate(E,LBL), _engine(propagator,LBL). 1 { _bool_evaluated(E,(bad;val(bool,(true;false)))) } 1 :- _bool_evaluate(E,LBL), _engine(propagator,LBL). _bool_evaluated(E,V) :- _bool_evaluate(E,LBL), _se_value(E,V), V=(bad;val(bool,(true;false))). diff --git a/src/constraint_handler/main.py b/src/constraint_handler/main.py index 1435f30c..39ccd474 100644 --- a/src/constraint_handler/main.py +++ b/src/constraint_handler/main.py @@ -111,6 +111,7 @@ "6_solve/finiteDomain", "6_solve/optimize", "6_solve/preference", + "6_solve/set", ] + m6_datatype + m6_compile From 1e03ed3f227b2a9483b169ad53ee93f8357687ff Mon Sep 17 00:00:00 2001 From: Abdallah Saffidine Date: Mon, 28 Sep 2026 14:29:45 +1000 Subject: [PATCH 12/18] Introduce condition argument to set_assign --- CHANGES.md | 2 ++ docs/developer/fact-format.md | 3 +- docs/reference/collections.md | 5 ++- .../1_default_arguments/default_arguments.lp | 6 ++-- src/constraint_handler/data/3_sugar/sugar.lp | 2 +- .../data/4_analysis/bad/safe.lp | 2 +- .../data/4_analysis/domain.lp | 5 ++- .../multiple_declarations.lp | 2 +- .../variable_safety_checks/undeclared.lp | 2 +- .../data/5_presolve/core.lp | 2 +- .../data/5_presolve/presolve.lp | 2 +- .../data/6_solve/compile/set.lp | 2 +- .../data/6_solve/compile2/domain.lp | 4 +-- .../data/6_solve/compile2/variables.lp | 11 ++++-- .../data/6_solve/ground/gringoEval.lp | 3 +- .../data/6_solve/propagator/propagator.lp | 3 +- src/constraint_handler/data/6_solve/set.lp | 5 +-- .../data/template/correction.lp | 6 ++-- .../data/template/expression.lp | 4 +-- .../data/template/variable_involve.lp | 4 +-- src/constraint_handler/schemas/atom.py | 1 + src/constraint_handler/schemas/core.py | 1 + .../schemas/propagator_atom.py | 6 ++-- .../utils/python_domain_computation.py | 34 +++++++++++-------- tests/correctness/core/set_to_variable.lp | 2 +- tests/correctness/engine/request_mult.lp | 20 +++++------ tests/correctness/engine/request_set_ref.lp | 8 ++--- .../set/conditional_assign.expected.all | 4 +++ .../set/conditional_assign.expected.any | 1 + .../set/conditional_assign.expected.none | 1 + .../set/conditional_assign.expected.stats | 1 + tests/correctness/set/conditional_assign.lp | 13 +++++++ tests/flat_ch/test_correctness.py | 1 + tests/test_encoding.py | 21 +++++++++++- 34 files changed, 126 insertions(+), 63 deletions(-) create mode 100644 tests/correctness/set/conditional_assign.expected.all create mode 100644 tests/correctness/set/conditional_assign.expected.any create mode 100644 tests/correctness/set/conditional_assign.expected.none create mode 100644 tests/correctness/set/conditional_assign.expected.stats create mode 100644 tests/correctness/set/conditional_assign.lp diff --git a/CHANGES.md b/CHANGES.md index 2ee1e8d4..4385c696 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,8 @@ ## Ongoing +- - 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)` diff --git a/docs/developer/fact-format.md b/docs/developer/fact-format.md index 201fcbb9..f8eb83f4 100644 --- a/docs/developer/fact-format.md +++ b/docs/developer/fact-format.md @@ -136,7 +136,8 @@ This page describes the EBNF grammar for the fact format used by the constraint ::= | "set_assign" "(" "," ")" - | "set_assign" "(" "," ","