1
%% Ported to hProlog by Tom Schrijvers, tom.schrijvers@cs.kuleuven.ac.be
3
%% $Id: gauss.chr,v 1.2 2003/10/03 14:50:37 tschrijvers Exp $
8
%% ?- X + Y #= 1, X - Y #= 1, label.
10
%% Y = -0.00000000000000000e+00
11
%% X = 1.00000000000000000e+00
13
%% ?- X + Y #= 1, X - Y #= 0, label.
15
%% Y = X = 5.00000000000000000e-01
19
%% solving linear polynomial equations by variable elimination a la Gauss
20
%% thom fruehwirth 910610,911213,920124,930602,931223, 980311
21
%% 961107 christian holzbaur for SICStus CHR
22
%% complete for equalities, leaves equalities implicit, slow
23
%% may loop if variables of the equations are unified
27
:- export (#=)/2, label/0.
45
%% math-utilities.pl ===========================================================
46
%% auxiliary predicates for math*.pl constraint solvers
47
%% thom fruehwirth 1991-92, revised 930518,931223,940304
48
%% 961030 christian holzbaur, SICStus adaption
50
%% SETTINGS --------------------------------------------------------------------
52
:- op(100,xfx,equals).
54
%% with float_precision single or double
55
%% adapt precision for zero/1 test
56
%% :- ( current_module(eclipse) ->
57
%% get_flag(float_precision,G)
61
%% ( G==single -> setval(precision,1.0e-06),setval(mprecision,-1.0e-06)
63
%% G==double -> setval(precision,1.0e-12),setval(mprecision,-1.0e-12)
65
getval(precision,1.0e-06).
66
getval(mprecision,-1.0e-06).
71
%% AUXILIARY PREDICATES -------------------------------------------------------
74
%% sort X*K,slack(_)*K with globalized Xs
78
( (C=[X*_|_],nonvar(X),X=slack(_))->A=B;B=C). % slacks unordered why?
82
msort( Len, L, [], S).
84
msort( 0, L, L, []) :- ! .
85
msort( 1, [X|L], L, [X]) :- ! .
86
msort( N, L0, L2, S) :-
89
msort( P, L0, L1, Sp),
90
msort( Q, L1, L2, Sq),
93
gmerge( [], B, B) :- ! .
94
gmerge( A, [], A) :- ! .
95
gmerge( [A|As], [B|Bs], Res) :-
97
gmerge( R, A, As, B, Bs, Res).
99
gmerge( =, A, As, _, Bs, [A|Rest]) :- gmerge( As, Bs, Rest).
100
gmerge( <, A, As, B, Bs, [A|Rest]) :- gmerge( As, [B|Bs], Rest).
101
gmerge( >, A, As, B, Bs, [B|Rest]) :- gmerge( [A|As], Bs, Rest).
103
cmp( R, X, Y) :- var(X), var(Y), !, var_compare( R, X, Y) .
104
cmp( R, X, _) :- var(X), !, R = (<).
105
cmp( R, _, Y) :- var(Y), !, R = (>).
109
compare( Rr, Ax/Fx, Ay/Fy),
112
cmp_args( 1,Ax, X, Y, R)
117
cmp_args( N,M, _, _, R) :- N>M, !, R = (=).
118
cmp_args( N,M, X, Y, R) :-
124
cmp_args( N1,M, X, Y, R)
131
rev([X|L1],L2,L3):- rev(L1,[X|L2],L3).
133
gdelete( X, [X|L], L).
134
gdelete( Y, [X|Xs], [X|Xt]) :-
137
zero(X) :- nonvar(X), X = slack(S), !, zero( S).
141
getval(mprecision,MP),
142
MP < C, % cope with imprecision
148
( nonvar(X), X = slack(Y) ->
154
is_div( C1, C2, C3) :-
158
is_divu( C11, C21, C31).
160
is_divu(C1,C2,C3):- zero(C1),!,C3=0.
161
is_divu(C1,C2,C3):- X is -(C1/C2), % minus here to get sign needed in handlers
165
float(X) -> Y is round(X),Z is X-Y,(zero(Z)-> C3 is floor(Y);C3=X) ; C3=X.
168
%% HANDLING SLACK VARIABLES ----------------------------------------------------
170
%% COMPUTING WITH POLYNOMIALS -------------------------------------------------
172
%% gets rounded constant C from is_div/3
173
mult_const(eq0(C1,P1),C,eq0(0 ,[])):- C=:=0,! .
174
mult_const(eq0(C1,P1),C,eq0(C1,P1)):- C=:=1,! .
175
mult_const(eq0(C1,P1),C2,eq0(C,P)):-
176
( zero(C1) -> C=0 ; C is C1*C2),
177
mult_const1(P1,C2,P).
178
mult_const1([],C,[]).
179
mult_const1([Xi*Ci|Poly],C,PolyR):-
180
( zero(Ci) -> PolyR=NPoly ; NCi is Ci*C,PolyR=[Xi*NCi|NPoly]),
181
mult_const1(Poly,C,NPoly).
183
%% gets input from const_mult/3
184
add_eq0(eq0(C1,P1),eq0(C2,P2),eq0(C,P0)):-
186
( zero(Ci) -> C=0 ; C=Ci),
189
add_eq1([],Poly,Poly):- ! .
190
add_eq1(Poly,[],Poly):- ! .
191
add_eq1([Xi1*Ci1|Poly1],Poly21,Poly):-
192
gdelete(Xi2*Ci2,Poly21,Poly2),Xi2==Xi1,
195
( zero(Ci) -> Poly=Poly3 ; Poly=[Xi1*Ci|Poly3]),
196
add_eq1(Poly1,Poly2,Poly3).
197
add_eq1([Xi1*Ci1|Poly1],Poly2,[Xi1*Ci1|Poly3]):-
198
add_eq1(Poly1,Poly2,Poly3).
202
normalize(A,B,P2,C1):-
204
P=eq0(C1,P1),rev(P1,[],P1R), globalize(P1R),
207
normalize1(V,P) :- var(V),!,
209
normalize1(C,P) :- ground(C),!,
210
call(C1 is C), P=eq0(C1,[]).
211
normalize1(slack(V),P) :- !,
212
P=eq0(0,[slack(V)*1]).
213
normalize1((+E),P) :- !,
215
normalize1((-E),P) :- !,
217
mult_const(P1,(-1),P).
218
normalize1(A*B,C) :- ground(A),!,
221
normalize1(B*A,C) :- ground(A),!,
224
normalize1(B/A,C) :- ground(A),!,
228
normalize1(A-B,C) :- !,
232
normalize1(A+B,C) :- !,
236
%% normalize1(E,C) :-
238
%% eqnonlin(CX,E). % add a nonlinear equation constraint
241
%% end of file math-utilities.pl -----------------------------------------------
243
:- constraints (equals)/2.
244
%% Poly equals Const, where Poly is list of monomials Variable*Coefficient
246
eliminate(X) @ [X*Coeff1|P1] equals C1 \ P equals C2
247
<=> gdelete(X*Coeff2,P,P2) | is_div(Coeff2,Coeff1,C), mult_const(eq0(C1,P1),C,eq0(C1C,P1C)), add_eq0(eq0(C2,P2),eq0(C1C,P1C),eq0(C3,P3)), P3 equals C3.
250
:- constraints (#=)/2.
251
%% curly brackets as wrapper to avoid name clash with built-in =:=
253
%% split @ f( (C, Cs)) <=> f( C ), f( Cs ).
255
normalize @ '#='(A,B) <=>
256
normalize(A,B,Poly,Const),
259
:- constraints label/0.
261
label \ equals([V * C], N) # ID <=> var(V), number(C), number(N) | V is -N / C pragma passive(ID).
262
label \ equals([],N) # ID <=> N =:= 0 pragma passive(ID).
265
/* end of file gauss.chr ------------------------------------------------*/