Prolog "railgun"
/**
* Warranty & Liability
* To the extent permitted by applicable law and unless explicitly
* otherwise agreed upon, XLOG Technologies AG makes no warranties
* regarding the provided information. XLOG Technologies AG assumes
* no liability that any problems might be solved with the information
* provided by XLOG Technologies AG.
*
* Rights & License
* All industrial property rights regarding the information - copyright
* and patent rights in particular - are the sole property of XLOG
* Technologies AG. If the company was not the originator of some
* excerpts, XLOG Technologies AG has at least obtained the right to
* reproduce, change and translate the information.
*
* Reproduction is restricted to the whole unaltered document. Reproduction
* of the information is only allowed for non-commercial uses. Selling,
* giving away or letting of the execution of the library is prohibited.
* The library can be distributed as part of your applications and libraries
* for execution provided this comment remains unchanged.
*
* Restrictions
* Only to be distributed with programs that add significant and primary
* functionality to the library. Not to be distributed with additional
* software intended to replace any components of the library.
*
* Trademarks
* Jekejeke is a registered trademark of XLOG Technologies AG.
*/
:- op(700, xfx, in).
:- op(700, xfx, ins).
:- op(700, xfx, #\=).
:- op(700, xfx, #=).
:- op(700, xfx, #<).
:- op(700, xfx, #=<).
:- op(700, xfx, #>).
:- op(700, xfx, #>=).
:- op(700, xfx, ::).
:- op(600, xfx, ..).
:- ensure_loaded(library(sets)).
:- ensure_loaded(library(lists)).
:- ensure_loaded(library(edge/attrvars)).
/**************************************************************/
/* in/2 and ins/2 */
/**************************************************************/
/**
* T in D:
* The predicate delays the goal in D on the term T.
*/
% in(+Term, +Range)
in(T, L..H) :- deref(T, V), freeze(T, sys_mach_bound(L, H, V)).
/**
* sys_mach_bound(L, H, X):
* The predicate succeeds whenever between(L', H', X) succeeds,
* where L' and H' are the Prolog evaluation of L and H.
*/
% sys_mach_bound(+Eval, +Eval, -Integer)
sys_mach_bound(P, Q, X) :-
L is P, H is Q,
between(L, H, X).
/**
* L ins D:
* The predicate delays the goal in D on the elements L.
*/
% ins(+List, +Range)
ins([], _).
ins([X|L], D) :-
in(X, D),
ins(L, D).
/**************************************************************/
/* (#=)/2, (#\=)/2, (#<)/2, (#=<)/2, (#>)/2 and (#>=)/2 */
/**************************************************************/
/**
* S #= T:
* The predicate delays the goal S =:= T on the terms S and T.
*/
% +Term #= +Term
A #= B :-
sys_attr_expr(A, C, [], H),
sys_attr_expr(B, D, H, M),
sys_attr_delay(M, C =:= D).
/**
* S #\= T:
* The predicate delays the goal S =\= T on the terms S and T.
*/
% +Term #\= +Term
A #\= B :-
sys_attr_expr(A, C, [], H),
sys_attr_expr(B, D, H, M),
sys_attr_delay(M, C =\= D).
/**
* S #< T:
* The predicate delays the goal S < T on the terms S and T.
*/
% +Term #< +Term
A #< B :-
sys_attr_expr(A, C, [], H),
sys_attr_expr(B, D, H, M),
sys_attr_delay(M, C < D).
/**
* S #=< T:
* The predicate delays the goal S =< T on the terms S and T.
*/
% +Term #=< +Term
A #=< B :-
sys_attr_expr(A, C, [], H),
sys_attr_expr(B, D, H, M),
sys_attr_delay(M, C =< D).
/**
* S #> T:
* The predicate delays the goal S > T on the terms S and T.
*/
% +Term #> +Term
A #> B :-
sys_attr_expr(A, C, [], H),
sys_attr_expr(B, D, H, M),
sys_attr_delay(M, C > D).
/**
* S #>= T:
* The predicate delays the goal S >= T on the terms S and T.
*/
% +Term #>= +Term
A #>= B :-
sys_attr_expr(A, C, [], H),
sys_attr_expr(B, D, H, M),
sys_attr_delay(M, C >= D).
% sys_attr_delay(+Map, +Goal)
sys_attr_delay([], G) :- !, sys_site_cond(G, F), F.
sys_attr_delay(M, G) :- sys_attr_post(M, G).
% sys_attr_post(+Map, +Goal)
sys_attr_post([], _).
sys_attr_post(['$ATTR'(_,L)|M], G) :- sys_attr_freeze(L, G), sys_attr_post(M, G).
% sys_attr_expr(+Term, -Term, +Map, -Map)
sys_attr_expr(T, (V :: D), M, N) :- T = '$ATTR'(V,R), var(V), !,
sys_attr_range(R, D),
sys_attr_extend(T, M, N).
sys_attr_expr(-A, -B, M, N) :- !,
sys_attr_expr(A, B, M, N).
sys_attr_expr(A+B, C+D, M, N) :- !,
sys_attr_expr(A, C, M, H),
sys_attr_expr(B, D, H, N).
sys_attr_expr(A-B, C-D, M, N) :- !,
sys_attr_expr(A, C, M, H),
sys_attr_expr(B, D, H, N).
sys_attr_expr(A*B, C*D, M, N) :- !,
sys_attr_expr(A, C, M, H),
sys_attr_expr(B, D, H, N).
sys_attr_expr(T, V, M, M) :-
deref(T, V).
% sys_attr_extend(+Term, +Map, -Map)
sys_attr_extend('$ATTR'(V,_), M, M) :- member('$ATTR'(W,_), M), V == W, !.
sys_attr_extend(T, M, [T|M]).
% sys_attr_range(+List, -Range)
sys_attr_range(R, _) :- var(R),
throw(error(resource_error(range_missing), _)).
sys_attr_range([sys_mach_bound(L, H, _)|_], L..H) :- !.
sys_attr_range(_, _) :-
throw(error(resource_error(range_missing), _)).
/**************************************************************/
/* all_different/1, label/1 and labeling/2 */
/**************************************************************/
/**
* all_different(L):
* The predicate delays the goal that all elements of L are different.
*/
% all_different(+List)
all_different([]).
all_different([X|L]) :-
maplist(#\=(X), L),
all_different(L).
/**
* label(L):
* The predicate resolves the elements of L, left to right.
*/
% label(+List)
label(L) :-
catch((sys_collect_plan(L, P), throw(sys_ball(P))),
sys_ball(V),
sys_collect_doit(L, [], V, R, [])),
% writeq(R), nl,
'$SEQ'(nothing, R).
/**
* labeling(O, L):
* The predicate resolves the elements of L, statically reordered
* accordingly to the option list O. For the available options
* see the documentation.
*/
% labeling(+List, +List)
labeling(O, L) :-
sys_attr_opts(O, 2, F),
catch((sys_reorder_plan(L, Q, F), throw(sys_ball(Q))),
sys_ball(U),
sys_reorder_doit(L, U, R)),
label(R).
% sys_attr_opts(+List, +Integer, -Integer)
sys_attr_opts(V, _, _) :- var(V),
throw(error(instantiation_error,_)).
sys_attr_opts([X|L], I, O) :- !,
sys_attr_opt(X, I, H),
sys_attr_opts(L, H, O).
sys_attr_opts([], I, I) :- !.
sys_attr_opts(L, _, _) :-
throw(error(type_error(list,L),_)).
% sys_attr_opt(+Term, +Integer, -Integer)
sys_attr_opt(V, _, _) :- var(V),
throw(error(instantiation_error,_)).
sys_attr_opt(zero, _, 0) :- !.
sys_attr_opt(constr, _, 1) :- !.
sys_attr_opt(plausi, _, 2) :- !.
sys_attr_opt(O, _, _) :-
throw(error(domain_error(score_opt,O),_)).
/***********************************************************/
/* Condition Filtering */
/***********************************************************/
% sys_filter_plan(+List, +Integer, -List)
sys_filter_plan(V, _, []) :- var(V), !.
sys_filter_plan([G|L], K, [I|Q]) :- term_variables(G, R), R \== [], !,
(R = [_] -> I = K; I is (-K)-1),
J is K+1,
sys_filter_plan(L, J, Q).
sys_filter_plan([_|L], K, Q) :-
J is K+1,
sys_filter_plan(L, J, Q).
% sys_filter_doit(+List, +List, +List, -List, +List)
sys_filter_doit([], _, _) --> [].
sys_filter_doit([I|Q], H, L) --> {I >= 0}, !,
{nth0(I, L, G), sys_site_cond(G, A)},
({A \== true} -> [A]; []),
sys_filter_doit(Q, H, L).
sys_filter_doit([I|Q], H, L) -->
{J is (-I)-1, nth0(J, L, G), sys_attr_test(G, H, F, [])},
sys_site_emit(F),
sys_filter_doit(Q, H, L).
% sys_collect_plan(+List, -List)
sys_collect_plan([], []).
sys_collect_plan([X|R], [Q|P]) :- X = '$ATTR'(V,L), var(V), !,
sys_filter_plan(L, 0, Q),
X = '$ATTR'(*,_),
sys_collect_plan(R, P).
sys_collect_plan([_|L], P) :-
sys_collect_plan(L, P).
% sys_collect_doit(+List, +List, +List, -List, +List)
sys_collect_doit([], _, []) --> [].
sys_collect_doit([X|R], H, [Q|S]) --> {X = '$ATTR'(V,L), var(V)}, !,
sys_filter_bound(Q, P, V, H, L, M),
sys_filter_doit(P, [V|H], M),
sys_collect_doit(R, [V|H], S).
sys_collect_doit([_|L], H, P) -->
sys_collect_doit(L, H, P).
% sys_filter_bound(List, -List, +Var, +List, +List, -List, -List, +List)
sys_filter_bound([], [], _, _, L, L) --> [].
sys_filter_bound([I|Q], P, V, H, [A|L], S) --> {I >= 0,
nth0(I, [A|L], G), sys_attr_crisp(G, V, F, E)}, !,
{sys_site_cond(E, C)},
({C \== true} -> [C]; []),
{sys_attr_fuse(F, A, B)},
sys_filter_bound(Q, P, V, H, [B|L], S).
sys_filter_bound([I|Q], P, V, H, [A|L], S) --> {I < 0,
J is (-I)-1, nth0(J, [A|L], G), sys_attr_coarse(G, V, H, F, E, [])}, !,
sys_site_emit(E),
{sys_attr_fuse(F, A, B)},
sys_filter_bound(Q, P, V, H, [B|L], S).
sys_filter_bound([I|Q], [I|P], V, H, L, S) -->
sys_filter_bound(Q, P, V, H, L, S).
/**
* sys_site_emit(L, I, O):
* The predicate succeeds with the compilation of L.
*/
% sys_site_emit(+List, -List, +List)
sys_site_emit([]) --> [].
sys_site_emit([G|L]) -->
{sys_site_cond(G, A)},
({A \== true} -> [A]; []),
sys_site_emit(L).
% sys_attr_fuse(+Goal, +Goal, -Goal)
sys_attr_fuse(true, G, G) :- !.
sys_attr_fuse(sys_mach_bound(C, D, X),
sys_mach_bound(A, B, X),
sys_mach_bound(max(A,C), min(B,D), X)).
/***********************************************************/
/* Variable Ordering */
/***********************************************************/
% sys_reorder_plan(+List, -List, +Integer)
sys_reorder_plan([], [], _).
sys_reorder_plan([X|L], [I|R], F) :- X = '$ATTR'(V,U), var(V), !,
sys_attr_score(U, S, F),
sys_attr_best(L, S, 1, 0, I, F),
nth0(I, [X|L], Y, H),
Y = '$ATTR'(*,_),
sys_reorder_plan(H, R, F).
sys_reorder_plan([_|L], R, F) :-
sys_reorder_plan(L, R, F).
% sys_reorder_doit(+List, +List, -List)
sys_reorder_doit([], [], []).
sys_reorder_doit([X|L], [I|Q], [Y|R]) :- X = '$ATTR'(V,_), var(V), !,
nth0(I, [X|L], Y, H),
sys_reorder_doit(H, Q, R).
sys_reorder_doit([_|L], Q, R) :-
sys_reorder_doit(L, Q, R).
/**
* sys_attr_score(L, S, F):
* The predicate succeeds in S with a pair of the number of free variables
* in the constraints, and the negation of the number of constraints
* for the attributed variable X.
*/
% sys_attr_score(+List, -Integer, +Integer)
sys_attr_score(L, S-U, F) :-
term_variables(L, H),
length(H, S),
sys_attr_skim(L, F, 0, U).
% sys_attr_best(+List, +Integer, +Integer, +Integer, -Integer, +Integer)
sys_attr_best([], _, _, I, I, _).
sys_attr_best(['$ATTR'(V,U)|L], S, K, _, O, F) :- var(V),
sys_attr_score(U, T, F), T @=< S, !,
H is K+1,
sys_attr_best(L, T, H, K, O, F).
sys_attr_best([_|L], S, K, I, O, F) :-
H is K+1,
sys_attr_best(L, S, H, I, O, F).
% sys_attr_skim(+List, +Integer, +Integer, -Integer, +Integer)
sys_attr_skim(V, _, U, U) :- var(V), !.
sys_attr_skim([G|L], 2, U, V) :- term_variables(G, R), R \= [], !,
length(R, J),
H is U-1/J,
sys_attr_skim(L, 2, H, V).
sys_attr_skim([G|L], 1, U, V) :- term_variables(G, [_]), !,
H is U-1,
sys_attr_skim(L, 1, H, V).
sys_attr_skim([_|L], F, U, V) :-
sys_attr_skim(L, F, U, V).
/***********************************************************/
/* Partial Consistency */
/***********************************************************/
% sys_attr_test(+Goal, +List, -List, +List)
sys_attr_test(A =:= B, H) --> !,
sys_attr_inter(A, H, C),
sys_attr_inter(B, H, D),
sys_inter_eq(C, D).
sys_attr_test(A =< B, H) --> !,
sys_attr_inter(A, H, C),
sys_attr_inter(B, H, D),
sys_inter_lq(C, D).
sys_attr_test(A < B, H) --> !,
sys_attr_inter(A, H, C),
sys_attr_inter(B, H, D),
sys_inter_ls(C, D).
sys_attr_test(A >= B, H) --> !,
sys_attr_inter(A, H, C),
sys_attr_inter(B, H, D),
sys_inter_gq(C, D).
sys_attr_test(A > B, H) --> !,
sys_attr_inter(A, H, C),
sys_attr_inter(B, H, D),
sys_inter_gr(C, D).
sys_attr_test(_, _) --> [].
% sys_inter_eq(+Pair, +Pair, -List, +List)
sys_inter_eq(L1..H1, L2..H2) --> !, [L1 =< H2, L2 =< H1].
sys_inter_eq(L1..H1, P2) --> !, sys_inter_is(V, P2), [L1 =< V, V =< H1].
sys_inter_eq(P1, L2..H2) --> !, sys_inter_is(U, P1), [U =< H2, L2 =< U].
sys_inter_eq(P1, P2) --> [P1 =:= P2].
% sys_inter_lq(+Pair, +Pair, -List, +List)
sys_inter_lq(L1.._, _..H2) --> !, [L1 =< H2].
sys_inter_lq(L1.._, P2) --> !, [L1 =< P2].
sys_inter_lq(P1, _..H2) --> !, [P1 =< H2].
sys_inter_lq(P1, P2) --> [P1 =< P2].
% sys_inter_ls(+Pair, +Pair, -List, +List)
sys_inter_ls(L1.._, _..H2) --> !, [L1 < H2].
sys_inter_ls(L1.._, P2) --> !, [L1 < P2].
sys_inter_ls(P1, _..H2) --> !, [P1 < H2].
sys_inter_ls(P1, P2) --> [P1 < P2].
% sys_inter_gq(+Pair, +Pair, -List, +List)
sys_inter_gq(_..H1, L2.._) --> !, [H1 >= L2].
sys_inter_gq(_..H1, P2) --> !, [H1 >= P2].
sys_inter_gq(P1, L2.._) --> !, [P1 >= L2].
sys_inter_gq(P1, P2) --> [P1 >= P2].
% sys_inter_gr(+Pair, +Pair, -List, +List)
sys_inter_gr(_..H1, L2.._) --> !, [H1 > L2].
sys_inter_gr(_..H1, P2) --> !, [H1 > P2].
sys_inter_gr(P1, L2.._) --> !, [P1 > L2].
sys_inter_gr(P1, P2) --> [P1 > P2].
/***********************************************************/
/* Interval Arithmetic */
/***********************************************************/
% sys_attr_inter(+Expr, +List, -Pair, -List, +List)
sys_attr_inter(T, H, T) --> {T = (V :: _), occurs_check(V, H)}, !.
sys_attr_inter((_ :: D), _, D) --> !.
sys_attr_inter(-A, H, R) --> !,
sys_attr_inter(A, H, B),
sys_inter_neg(B, R).
sys_attr_inter(A+B, H, R) --> !,
sys_attr_inter(A, H, C),
sys_attr_inter(B, H, D),
sys_inter_add(C, D, R).
sys_attr_inter(A-B, H, R) --> !,
sys_attr_inter(A, H, C),
sys_attr_inter(B, H, D),
sys_inter_sub(C, D, R).
sys_attr_inter(A*B, H, R) --> !,
sys_attr_inter(A, H, C),
sys_attr_inter(B, H, D),
sys_inter_mul(C, D, R).
sys_attr_inter(T, _, T) --> [].
% sys_inter_neg(+Pair, -Pair, -List, +List)
sys_inter_neg(L..H, -H.. -L) --> !.
sys_inter_neg(P, -P) --> [].
% sys_inter_add(+Pair, +Pair, -Pair, -List, +List)
sys_inter_add(L1..H1, L2..H2, L1+L2..H1+H2) --> !.
sys_inter_add(L1..H1, P2, L1+V..H1+V) --> !, sys_inter_is(V, P2).
sys_inter_add(P1, L2..H2, U+L2..U+H2) --> !, sys_inter_is(U, P1).
sys_inter_add(P1, P2, P1+P2) --> [].
% sys_inter_sub(+Pair, +Pair, -Pair, -List, +List)
sys_inter_sub(L1..H1, L2..H2, L1-H2..H1-L2) --> !.
sys_inter_sub(L1..H1, P2, L1-V..H1-V) --> !, sys_inter_is(V, P2).
sys_inter_sub(P1, L2..H2, U-H2..U-L2) --> !, sys_inter_is(U, P1).
sys_inter_sub(P1, P2, P1-P2) --> [].
% sys_inter_mul(+Pair, +Pair, -Pair, -List, +List)
sys_inter_mul(L1..H1, L2..H2, min(min(W11,W12),min(W21,W22))..
max(max(W11,W12),max(W21,W22))) --> !,
sys_inter_is(U1, L1), sys_inter_is(U2, H1),
sys_inter_is(V1, L2), sys_inter_is(V2, H2),
sys_inter_is(W11, U1*V1), sys_inter_is(W12, U1*V2),
sys_inter_is(W21, U2*V1), sys_inter_is(W22, U2*V2).
sys_inter_mul(L1..H1, P2, min(W1,W2)..max(W1,W2)) --> !,
sys_inter_is(U1, L1), sys_inter_is(U2, H1),
sys_inter_is(V, P2),
sys_inter_is(W1, U1*V), sys_inter_is(W2, U2*V).
sys_inter_mul(P1, L2..H2, min(W1,W2)..max(W1,W2)) --> !,
sys_inter_is(U, P1),
sys_inter_is(V1, L2), sys_inter_is(V2, H2),
sys_inter_is(W1, U*V1), sys_inter_is(W2, U*V2).
sys_inter_mul(P1, P2, P1*P2) --> [].
% sys_inter_is(-Expr, +Expr)
sys_inter_is(T, T) --> {T = (_::_)}, !.
sys_inter_is(X:: -0rInf..0rInf, E) --> [X is E].
/***********************************************************/
/* Bound Indexicals */
/***********************************************************/
% sys_attr_crisp(+Goal, +Var, -Goal, -Goal))
sys_attr_crisp(A =:= B, W, G2, G1) :-
sys_attr_linear(A, W, (P,Q)),
sys_attr_linear(B, W, (R,S)),
sys_simp_sub(P, R, U),
sys_simp_sub(S, Q, V),
(U = 1 ->
G1 = (W is V),
G2 = true;
U = -1 ->
sys_simp_neg(V, K),
G1 = (W is K),
G2 = true;
fail).
sys_attr_crisp(A =< B, W, G2, G1) :-
sys_attr_linear(A, W, (P,Q)),
sys_attr_linear(B, W, (R,S)),
sys_simp_sub(P, R, U),
sys_simp_sub(S, Q, V),
(U = 1 ->
G1 = true,
G2 = sys_mach_bound(-0rInf, V, W);
U = -1 ->
sys_simp_neg(V, K),
G1 = true,
G2 = sys_mach_bound(K, 0rInf, W);
fail).
sys_attr_crisp(A < B, W, G2, G1) :-
sys_attr_linear(A+1, W, (P,Q)),
sys_attr_linear(B, W, (R,S)),
sys_simp_sub(P, R, U),
sys_simp_sub(S, Q, V),
(U = 1 ->
G1 = true,
G2 = sys_mach_bound(-0rInf, V, W);
U = -1 ->
sys_simp_neg(V, K),
G1 = true,
G2 = sys_mach_bound(K, 0rInf, W);
fail).
sys_attr_crisp(B >= A, W, G2, G1) :-
sys_attr_linear(A, W, (P,Q)),
sys_attr_linear(B, W, (R,S)),
sys_simp_sub(P, R, U),
sys_simp_sub(S, Q, V),
(U = 1 ->
G1 = true,
G2 = sys_mach_bound(-0rInf, V, W);
U = -1 ->
sys_simp_neg(V, K),
G1 = true,
G2 = sys_mach_bound(K, 0rInf, W);
fail).
sys_attr_crisp(B > A, W, G2, G1) :-
sys_attr_linear(A+1, W, (P,Q)),
sys_attr_linear(B, W, (R,S)),
sys_simp_sub(P, R, U),
sys_simp_sub(S, Q, V),
(U = 1 ->
G1 = true,
G2 = sys_mach_bound(-0rInf, V, W);
U = -1 ->
sys_simp_neg(V, K),
G1 = true,
G2 = sys_mach_bound(K, 0rInf, W);
fail).
% sys_attr_coarse(+Goal, +Var, +List, -Goal, -List, +List)
sys_attr_coarse(A =:= B, W, H, G) -->
{sys_attr_linear(A, W, (P,Q)),
sys_attr_linear(B, W, (R,S)),
sys_simp_sub(P, R, U),
sys_simp_sub(S, Q, V)},
({U = 1} ->
sys_attr_inter(V, H, E),
sys_inter_bound(E, W, G);
{U = -1} ->
{sys_simp_neg(V, K)},
sys_attr_inter(K, H, E),
sys_inter_bound(E, W, G);
{fail}).
sys_attr_coarse(A =< B, W, H, G) -->
{sys_attr_linear(A, W, (P,Q)),
sys_attr_linear(B, W, (R,S)),
sys_simp_sub(P, R, U),
sys_simp_sub(S, Q, V)},
({U = 1} ->
sys_attr_inter(V, H, E),
{sys_inter_lower(E, W, G)};
{U = -1} ->
{sys_simp_neg(V, K)},
sys_attr_inter(K, H, E),
{sys_inter_upper(E, W, G)};
{fail}).
sys_attr_coarse(A < B, W, H, G) -->
{sys_attr_linear(A+1, W, (P,Q)),
sys_attr_linear(B, W, (R,S)),
sys_simp_sub(P, R, U),
sys_simp_sub(S, Q, V)},
({U = 1} ->
sys_attr_inter(V, H, E),
{sys_inter_lower(E, W, G)};
{U = -1} ->
{sys_simp_neg(V, K)},
sys_attr_inter(K, H, E),
{sys_inter_upper(E, W, G)};
{fail}).
sys_attr_coarse(B >= A, W, H, G) -->
{sys_attr_linear(A, W, (P,Q)),
sys_attr_linear(B, W, (R,S)),
sys_simp_sub(P, R, U),
sys_simp_sub(S, Q, V)},
({U = 1} ->
sys_attr_inter(V, H, E),
{sys_inter_lower(E, W, G)};
{U = -1} ->
{sys_simp_neg(V, K)},
sys_attr_inter(K, H, E),
{sys_inter_upper(E, W, G)};
{fail}).
sys_attr_coarse(B > A, W, H, G) -->
{sys_attr_linear(A+1, W, (P,Q)),
sys_attr_linear(B, W, (R,S)),
sys_simp_sub(P, R, U),
sys_simp_sub(S, Q, V)},
({U = 1} ->
sys_attr_inter(V, H, E),
{sys_inter_lower(E, W, G)};
{U = -1} ->
{sys_simp_neg(V, K)},
sys_attr_inter(K, H, E),
{sys_inter_upper(E, W, G)};
{fail}).
% sys_inter_bound(+Pair, +Var, -Goal)
sys_inter_bound(L..H, X, sys_mach_bound(L, H, X)) --> !.
sys_inter_bound(P, X, true) --> [X is P].
% sys_inter_lower(+Pair, +Var, -Goal)
sys_inter_lower(_..H, X, sys_mach_bound(-0rInf, H, X)) :- !.
sys_inter_lower(P, X, sys_mach_bound(-0rInf, P, X)).
% sys_inter_upper(+Pair, +Var, -Goal)
sys_inter_upper(L.._, X, sys_mach_bound(L, 0rInf, X)) :- !.
sys_inter_upper(P, X, sys_mach_bound(P, 0rInf, X)).
/***********************************************************/
/* Linear Forms */
/***********************************************************/
% sys_attr_linear(+Expr, +Var, -Pair)
sys_attr_linear((V :: _), W, (1,0)) :- W == V, !.
sys_attr_linear(T, _, (0,T)) :- T = (_ :: _), !.
sys_attr_linear(-A, W, (R,S)) :- !,
sys_attr_linear(A, W, (P,Q)),
sys_simp_neg(P, R),
sys_simp_neg(Q, S).
sys_attr_linear(A+B, W, (U,V)) :- !,
sys_attr_linear(A, W, (P,Q)),
sys_attr_linear(B, W, (R,S)),
sys_simp_add(P, R, U),
sys_simp_add(Q, S, V).
sys_attr_linear(A-B, W, (U,V)) :- !,
sys_attr_linear(A, W, (P,Q)),
sys_attr_linear(B, W, (R,S)),
sys_simp_sub(P, R, U),
sys_simp_sub(Q, S, V).
sys_attr_linear(A*B, W, (U,V)) :- !,
sys_attr_linear(A, W, (P,Q)),
sys_attr_linear(B, W, (R,S)),
(P = 0 ->
sys_simp_mul(Q, R, U),
sys_simp_mul(Q, S, V);
R = 0 ->
sys_simp_mul(P, S, U),
sys_simp_mul(Q, S, V);
fail).
sys_attr_linear(T, _, (0,T)).
% sys_simp_neg(+Expr, -Expr)
sys_simp_neg(A, B) :- integer(A), !, B is -A.
sys_simp_neg(-X, X) :- !.
sys_simp_neg(X, -X).
% sys_simp_add(+Expr, +Expr, -Expr)
sys_simp_add(A, B, C) :- integer(A), integer(B), !, C is A+B.
sys_simp_add(0, Y, Y) :- !.
sys_simp_add(X, 0, X) :- !.
sys_simp_add(X, Y, X+Y).
% sys_simp_sub(+Expr, +Expr, -Expr)
sys_simp_sub(A, B, C) :- integer(A), integer(B), !, C is A-B.
sys_simp_sub(0, Y, R) :- !, sys_simp_neg(Y, R).
sys_simp_sub(X, 0, X) :- !.
sys_simp_sub(X, Y, X-Y).
% sys_simp_mul(+Expr, +Expr, -Expr)
sys_simp_mul(A, B, C) :- integer(A), integer(B), !, C is A*B.
sys_simp_mul(0, _, 0) :- !.
sys_simp_mul(_, 0, 0) :- !.
sys_simp_mul(1, Y, Y) :- !.
sys_simp_mul(X, 1, X) :- !.
sys_simp_mul(-1, Y, R) :- !, sys_simp_neg(Y, R).
sys_simp_mul(X, -1, R) :- !, sys_simp_neg(X, R).
sys_simp_mul(X, Y, X*Y).
/***********************************************************/
/* Cacheable Functors */
/***********************************************************/
/**
* sys_site_cond(G, F):
* The predicate succeeds in F with the compilation of G.
*/
% sys_site_cond(+Goal, -Goal)
sys_site_cond(X is B, R) :- !,
sys_site_point(B, D),
sys_site_is(X, D, R).
sys_site_cond(sys_mach_bound(A, B, X), R) :- !,
sys_site_point(A, C),
sys_site_point(B, D),
sys_site_bound(C, D, X, R).
sys_site_cond(A =:= B, R) :- !,
sys_site_point(A, C),
sys_site_point(B, D),
ir_site_new(C =:= D, R).
sys_site_cond(A =\= B, R) :- !,
sys_site_point(A, C),
sys_site_point(B, D),
ir_site_new(C =\= D, R).
sys_site_cond(A < B, R) :- !,
sys_site_point(A, C),
sys_site_point(B, D),
ir_site_new(C < D, R).
sys_site_cond(A =< B, R) :- !,
sys_site_point(A, C),
sys_site_point(B, D),
ir_site_new(C =< D, R).
sys_site_cond(A > B, R) :- !,
sys_site_point(A, C),
sys_site_point(B, D),
ir_site_new(C > D, R).
sys_site_cond(A >= B, R) :- !,
sys_site_point(A, C),
sys_site_point(B, D),
ir_site_new(C >= D, R).
sys_site_cond(true, R) :- !,
R = true.
sys_site_cond(G, R) :-
ir_site_new(G, R).
% sys_site_is(+Expr, +Expr, +Var, -Goal)
sys_site_is(X, A, true) :- integer(A), !,
X = A.
sys_site_is(X, A, R) :-
ir_site_new(X is A, R).
% sys_site_bound(+Expr, +Expr, +Var, -Goal)
sys_site_bound(A, B, X, R) :- var(X), integer(A), integer(B), !,
ir_site_new(between(A, B, X), R).
sys_site_bound(A, B, X, true) :- integer(A), integer(B), !,
A =< X, X =< B.
sys_site_bound(A, B, X, R) :-
ir_site_new(sys_mach_bound(A, B, X), R).
/***********************************************************/
/* Expression Folding */
/***********************************************************/
/**
* sys_site_point(A, P):
* The predicate succeeds in P with a point expression of A.
*/
% sys_site_point(+Expr, -Expr)
sys_site_point((V :: _), V) :- !.
sys_site_point(-A, R) :- !,
sys_site_point(A, B),
sys_site_neg(B, R).
sys_site_point(min(A,B), R) :- !,
sys_site_point(A, C),
sys_site_point(B, D),
sys_site_min(C, D, R).
sys_site_point(max(A,B), R) :- !,
sys_site_point(A, C),
sys_site_point(B, D),
sys_site_max(C, D, R).
sys_site_point(A+B, R) :- !,
sys_site_point(A, C),
sys_site_point(B, D),
sys_site_add(C, D, R).
sys_site_point(A-B, R) :- !,
sys_site_point(A, C),
sys_site_point(B, D),
sys_site_sub(C, D, R).
sys_site_point(A*B, R) :- !,
sys_site_point(A, C),
sys_site_point(B, D),
sys_site_mul(C, D, R).
sys_site_point(T, T).
% sys_site_neg(+Expr, -Expr)
sys_site_neg(A, B) :- integer(A), !,
B is -A.
sys_site_neg(X, R) :-
ir_site_new(-X, R).
% sys_site_min(+Expr, +Expr, -Expr)
sys_site_min(A, B, C) :- integer(A), integer(B), !,
C is min(A,B).
sys_site_min(X, Y, Y) :- X == 0rInf, !.
sys_site_min(X, Y, X) :- Y == 0rInf, !.
sys_site_min(X, Y, R) :-
ir_site_new(min(X,Y), R).
% sys_site_max(+Expr, +Expr, -Expr)
sys_site_max(A, B, C) :- integer(A), integer(B), !,
C is max(A,B).
sys_site_max(X, Y, Y) :- X == -0rInf, !.
sys_site_max(X, Y, X) :- Y == -0rInf, !.
sys_site_max(X, Y, R) :-
ir_site_new(max(X,Y), R).
% sys_site_add(+Expr, +Expr, -Expr)
sys_site_add(A, B, C) :- integer(A), integer(B), !,
C is A+B.
sys_site_add(X, Y, Y) :- X == 0, !.
sys_site_add(X, Y, X) :- Y == 0, !.
sys_site_add(X, Y, R) :-
ir_site_new(X+Y, R).
% sys_site_sub(+Expr, +Expr, -Expr)
sys_site_sub(A, B, C) :- integer(A), integer(B), !,
C is A-B.
sys_site_sub(X, Y, R) :- X == 0, !, sys_site_neg(Y, R).
sys_site_sub(X, Y, X) :- Y == 0, !.
sys_site_sub(X, Y, R) :-
ir_site_new(X-Y, R).
% sys_site_mul(+Expr, +Expr, -Expr)
sys_site_mul(A, B, C) :- integer(A), integer(B), !,
C is A*B.
sys_site_mul(X, _, 0) :- X == 0, !.
sys_site_mul(_, Y, 0) :- Y == 0, !.
sys_site_mul(X, Y, R) :-
ir_site_new(X*Y, R).
/****************************************************************/
/* Error Texts */
/****************************************************************/
% strings(+Atom, +Atom, -Atom)
:- multifile(strings/3).
strings('domain_error.score_opt', de, 'Scoring erwartet, gefunden ~q..').
strings('resource_error.range_missing', de, 'Domain fehlt.').
strings('domain_error.score_opt', '', 'Scoring expected, found ~q.').
strings('resource_error.range_missing', '', 'Domain missing').