301 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
		
		
			
		
	
	
			301 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
|   | % math-utilities.pl =========================================================== | ||
|  | % auxiliary predicates for math*.pl constraint solvers | ||
|  | % thom fruehwirth 1991-92, revised 930518,931223,940304 | ||
|  | % 961030 christian holzbaur, SICStus adaption | ||
|  | 
 | ||
|  | :- use_module( library('chr/getval')). | ||
|  | :- use_module( library('chr/matching')). | ||
|  | :- use_module( library('chr/ordering'), [globalize/1,var_compare/3]). | ||
|  | 
 | ||
|  | 
 | ||
|  | % SETTINGS -------------------------------------------------------------------- | ||
|  | 
 | ||
|  | % for use in is/2: precision, slack variables, simulated infimum, etc. | ||
|  | 
 | ||
|  | % Code works with flag prefer_rationals on or off | ||
|  | % and with float_precision single or double | ||
|  | 
 | ||
|  | % adapt precision for zero/1 test | ||
|  | :- ( current_module(eclipse) ->  | ||
|  | 	get_flag(float_precision,G) | ||
|  |    ; | ||
|  | 	G = double | ||
|  |    ), | ||
|  |    (G==single -> setval(precision,1.0e-06),setval(mprecision,-1.0e-06) | ||
|  |    ; | ||
|  |     G==double -> setval(precision,1.0e-12),setval(mprecision,-1.0e-12) | ||
|  |    ). | ||
|  | 
 | ||
|  | slack(X,X).	% :- X>=0. | ||
|  | 
 | ||
|  | inf(   3.40282e38). | ||
|  | minf( -3.40282e38). | ||
|  | sup(   1.0e-45). | ||
|  | msup( -1.0e-45). | ||
|  | 
 | ||
|  | :- multifile portray/1. | ||
|  | 
 | ||
|  | portray( X) :- math_portray( X, Xp), print( Xp). | ||
|  | 
 | ||
|  | 
 | ||
|  | % PRETTY PRINT --------------------------------------------------------------- | ||
|  | 
 | ||
|  | % for math-gauss.pl and math-elim.pl | ||
|  | math_portray(equals(P,C),P1=:=0):- zero(C),!, | ||
|  | 	make_poly(P,P1). | ||
|  | math_portray(equals(P,C),P1=:=C1):-!, | ||
|  | 	MC is (-C), | ||
|  | 	avoid_float(MC,C1), | ||
|  | 	make_poly(P,P1). | ||
|  | % for math-fougau.pl | ||
|  | math_portray(eq(P,C,(=:=)),P1=:=C1):-!, | ||
|  |         MC is (-C), | ||
|  |         avoid_float(MC,C1), | ||
|  |         make_poly(P,P1). | ||
|  | math_portray(eq(P,C,'>'('=')),P1>=C1):-!, | ||
|  |         MC is (-C), | ||
|  |         avoid_float(MC,C1), | ||
|  |         make_poly(P,P1). | ||
|  | math_portray(eq(P,C,'>'('>')),P1>C1):-!, | ||
|  |         MC is (-C), | ||
|  |         avoid_float(MC,C1), | ||
|  |         make_poly(P,P1). | ||
|  | % for all three math*pl solvers | ||
|  | math_portray(eqnonlin(X,(E)),X=:=E):-!. | ||
|  | 
 | ||
|  | 
 | ||
|  | make_poly([],0). | ||
|  | make_poly([X*C],-CX):- C<0,!, | ||
|  | 	C1 is (-C), | ||
|  | 	avoid_float(C1,C2), | ||
|  | 	make_mono(C2,X,CX). | ||
|  | make_poly([X*C],CX):-!, | ||
|  | 	avoid_float(C,C1), | ||
|  | 	make_mono(C1,X,CX). | ||
|  | make_poly([X*C|P],P1-CX):- C<0,!, | ||
|  | 	C1 is (-C), | ||
|  | 	avoid_float(C1,C2), | ||
|  | 	make_mono(C2,X,CX), | ||
|  | 	make_poly(P,P1). | ||
|  | make_poly([X*C|P],P1+CX):- | ||
|  | 	avoid_float(C,C1), | ||
|  | 	make_mono(C1,X,CX), | ||
|  | 	make_poly(P,P1). | ||
|  | 
 | ||
|  | make_mono(C,X,CX):- nonvar(X),X=slack(Y),!,make_mono(C,Y,CX). | ||
|  | make_mono(C,X,CX1):- nonvar(X),number(X),!,CX is C*X,avoid_float(CX,CX1). | ||
|  | make_mono(1,X,X):-!. | ||
|  | % make_mono(1_1,X,X):-!. | ||
|  | make_mono(C,X,C*X). | ||
|  | 
 | ||
|  | 
 | ||
|  | % AUXILIARY PREDICATES ------------------------------------------------------- | ||
|  | 
 | ||
|  | nonground( X) :- ground( X), !, fail. | ||
|  | nonground( _). | ||
|  | 
 | ||
|  | % | ||
|  | % sort X*K,slack(_)*K with globalized Xs | ||
|  | % | ||
|  | sort1(A,B):- | ||
|  | 	msort(A,C), | ||
|  | 	((C=[X*_|_],nonvar(X),X=slack(_))->A=B;B=C). % slacks unordered why? | ||
|  | 
 | ||
|  | msort( L, S) :- | ||
|  | 	length( L, Len), | ||
|  | 	msort( Len, L, [], S). | ||
|  | 
 | ||
|  | msort( 0, L,     L, []) :- !. | ||
|  | msort( 1, [X|L], L, [X]) :- !. | ||
|  | msort( N, L0, L2, S) :- | ||
|  | 	P is N>>1, | ||
|  | 	Q is N-P, | ||
|  | 	msort( P, L0, L1, Sp), | ||
|  | 	msort( Q, L1, L2, Sq), | ||
|  | 	merge( Sp, Sq, S). | ||
|  | 
 | ||
|  | merge( [], B, B) :- !. | ||
|  | merge( A, [], A) :- !. | ||
|  | merge( [A|As], [B|Bs], Res) :- | ||
|  | 	cmp( R, A, B), | ||
|  | 	merge( R, A, As, B, Bs, Res). | ||
|  | 
 | ||
|  | merge( =, A, As, _, Bs, [A|Rest]) :- merge( As, Bs,     Rest). | ||
|  | merge( <, A, As, B, Bs, [A|Rest]) :- merge( As, [B|Bs], Rest). | ||
|  | merge( >, A, As, B, Bs, [B|Rest]) :- merge( [A|As], Bs, Rest). | ||
|  | 
 | ||
|  | cmp( R, X, Y) :- var(X), var(Y), !, var_compare( R, X, Y). | ||
|  | cmp( R, X, _) :- var(X), !, R = (<). | ||
|  | cmp( R, _, Y) :- var(Y), !, R = (>). | ||
|  | cmp( R, X, Y) :- | ||
|  | 	functor( X, Fx, Ax), | ||
|  | 	functor( Y, Fy, Ay), | ||
|  | 	compare( Rr, Ax/Fx, Ay/Fy), | ||
|  | 	( Rr = (=), | ||
|  | 	  Ax > 0 -> | ||
|  | 	    cmp_args( 1,Ax, X, Y, R) | ||
|  | 	;    | ||
|  | 	    R = Rr | ||
|  |         ). | ||
|  | 
 | ||
|  | cmp_args( N,M, _, _, R) :- N>M, !, R = (=). | ||
|  | cmp_args( N,M, X, Y, R) :- | ||
|  | 	arg( N, X, Ax), | ||
|  | 	arg( N, Y, Ay), | ||
|  | 	cmp( Rr, Ax, Ay), | ||
|  | 	( Rr = (=) -> | ||
|  | 	    N1 is N+1, | ||
|  | 	    cmp_args( N1,M, X, Y, R) | ||
|  | 	; | ||
|  | 	    R = Rr | ||
|  | 	). | ||
|  | 
 | ||
|  | 
 | ||
|  | rev([],L,L). | ||
|  | rev([X|L1],L2,L3):- rev(L1,[X|L2],L3). | ||
|  | 
 | ||
|  | extract(X*C2,P0,P) ?- delete(Y*C2,P0,P),X==Y,!. | ||
|  | 
 | ||
|  | delete( X, [X|L],  L). | ||
|  | delete( Y, [X|Xs], [X|Xt]) :- | ||
|  | 	delete( Y, Xs, Xt). | ||
|  | 
 | ||
|  | zero( slack(S)) ?- !, zero( S). | ||
|  | zero(C):-     | ||
|  |     float(C) ->  | ||
|  | 	getval(precision,P), | ||
|  | 	getval(mprecision,MP), | ||
|  | 	MP < C,    % cope with imprecision | ||
|  | 	C < P       | ||
|  |     ; | ||
|  | 	C=:=0. | ||
|  | 
 | ||
|  | nonzero(C):- zero(C), !, fail. | ||
|  | nonzero(_). | ||
|  | 
 | ||
|  | unwrap( slack(S), X) ?- !, X=S. | ||
|  | unwrap( X,        X). | ||
|  | 
 | ||
|  | is_div( C1, C2, C3) :- | ||
|  | 	unwrap( C1, C11), | ||
|  | 	unwrap( C2, C21), | ||
|  | 	unwrap( C3, C31), | ||
|  | 	is_divu( C11, C21, C31). | ||
|  | 
 | ||
|  | is_divu(C1,C2,C3):- zero(C1),!,C3=0. | ||
|  | is_divu(C1,C2,C3):- X is -(C1/C2),  % minus here to get sign needed in handlers | ||
|  | 	avoid_float(X,C3). | ||
|  | 
 | ||
|  | is_mul( C1, C2, C3) :- | ||
|  | 	unwrap( C1, C11), | ||
|  | 	unwrap( C2, C21), | ||
|  | 	unwrap( C3, C31), | ||
|  | 	is_mulu( C11, C21, C31). | ||
|  | 
 | ||
|  | is_mulu(C1,C2,C3):- zero(C1),!,C3=0. | ||
|  | is_mulu(C1,C2,C3):- zero(C2),!,C3=0. | ||
|  | is_mulu(C1,C2,C3):- X is C1*C2,  | ||
|  | 	avoid_float(X,C3). | ||
|  | 
 | ||
|  | avoid_float(X,C3):- | ||
|  | 	float(X) -> Y is round(X),Z is X-Y,(zero(Z)-> C3 is integer(Y);C3=X) ; C3=X. | ||
|  | 
 | ||
|  | 
 | ||
|  | simplifyable(X*C,P,P1):- delete(X*C,P,P1),ground(X),!. | ||
|  | 
 | ||
|  | 
 | ||
|  | % HANDLING SLACK VARIABLES ---------------------------------------------------- | ||
|  | 
 | ||
|  | all_slacks([]). | ||
|  | all_slacks([slack(Sl)*C|P]) ?-			% check_slack(Sl), | ||
|  | 	all_slacks(P). | ||
|  | 
 | ||
|  | all_slacks([],_). | ||
|  | all_slacks([slack(Sl)*C|P],S) ?-		% check_slack(Sl), | ||
|  | 	sign(C,S), | ||
|  | 	all_slacks(P,S). | ||
|  | 
 | ||
|  | check_slack( S) :- find_constraint( S, basic(_)#_), !. | ||
|  | check_slack( _) :- raise_exception( slack). | ||
|  | 
 | ||
|  | sign(C,0):- zero(C),!. | ||
|  | sign(C,S):- C>0 -> S=1 ; S=(-1). | ||
|  | 
 | ||
|  | all_zeroes([]). | ||
|  | all_zeroes([slack(0)*C|P]) :- | ||
|  | 	all_zeroes(P). | ||
|  | 
 | ||
|  | 
 | ||
|  | % COMPUTING WITH POLYNOMIALS ------------------------------------------------- | ||
|  | 
 | ||
|  | % gets rounded constant C from is_div/3 | ||
|  | mult_const(eq0(C1,P1),C,eq0(0 ,[])):- C=:=0,!. | ||
|  | mult_const(eq0(C1,P1),C,eq0(C1,P1)):- C=:=1,!. | ||
|  | mult_const(eq0(C1,P1),C2,eq0(C,P)):- | ||
|  | 	(zero(C1) -> C=0 ; C is C1*C2), | ||
|  | 	mult_const1(P1,C2,P). | ||
|  |  mult_const1([],C,[]). | ||
|  |  mult_const1([Xi*Ci|Poly],C,PolyR):- | ||
|  | 	(zero(Ci) -> PolyR=NPoly ; NCi is Ci*C,PolyR=[Xi*NCi|NPoly]), | ||
|  | 	mult_const1(Poly,C,NPoly). | ||
|  | 
 | ||
|  | % gets input from const_mult/3 | ||
|  | add_eq0(eq0(C1,P1),eq0(C2,P2),eq0(C,P0)):- | ||
|  | 	Ci is C1+C2, | ||
|  | 	(zero(Ci) -> C=0 ; C=Ci), | ||
|  | 	add_eq1(P1,P2,P0). | ||
|  | %	sort(P,P0). | ||
|  |  add_eq1([],Poly,Poly):-!. | ||
|  |  add_eq1(Poly,[],Poly):-!. | ||
|  |  add_eq1([Xi1*Ci1|Poly1],Poly21,Poly):- | ||
|  | 	delete(Xi2*Ci2,Poly21,Poly2),Xi2==Xi1, | ||
|  | 	!, | ||
|  | 	Ci is Ci1+Ci2, | ||
|  | 	(zero(Ci) -> Poly=Poly3 ; Poly=[Xi1*Ci|Poly3]), | ||
|  | 	add_eq1(Poly1,Poly2,Poly3). | ||
|  |  add_eq1([Xi1*Ci1|Poly1],Poly2,[Xi1*Ci1|Poly3]):- | ||
|  | 	add_eq1(Poly1,Poly2,Poly3). | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | normalize(A,B,P2,C1):- | ||
|  |         normalize1(A-B,P), | ||
|  | 	P=eq0(C1,P1),rev(P1,[],P1R),globalize(P1R), | ||
|  | 	sort1(P1,P2).                                  | ||
|  | 
 | ||
|  |  normalize1(V,P) ?- var(V),!, | ||
|  | 	P=eq0(0,[V*1]). | ||
|  |  normalize1(C,P) ?- ground(C),!, | ||
|  | 	C1 is C,P=eq0(C1,[]). | ||
|  |  normalize1(slack(V),P) ?- !, | ||
|  | 	P=eq0(0,[slack(V)*1]). | ||
|  |  normalize1((+E),P) ?-!, | ||
|  | 	normalize1(E,P). | ||
|  |  normalize1((-E),P) ?-!, | ||
|  | 	normalize1(E,P1), | ||
|  | 	mult_const(P1,(-1),P). | ||
|  |  normalize1(A*B,C) ?- ground(A),!, | ||
|  | 	normalize1(B,BN), | ||
|  | 	mult_const(BN,A,C). | ||
|  |  normalize1(B*A,C) ?- ground(A),!, | ||
|  | 	normalize1(B,BN), | ||
|  | 	mult_const(BN,A,C). | ||
|  |  normalize1(B/A,C) ?- ground(A),!, | ||
|  | 	normalize1(B,BN), | ||
|  | 	A1 is 1/A, | ||
|  | 	mult_const(BN,A1,C).  | ||
|  |  normalize1(A-B,C) ?- !, | ||
|  | 	normalize1(A,AN), | ||
|  | 	normalize1((-B),BN), | ||
|  | 	add_eq0(AN,BN,C). | ||
|  |  normalize1(A+B,C) ?- !, | ||
|  | 	normalize1(A,AN), | ||
|  | 	normalize1(B,BN), | ||
|  | 	add_eq0(AN,BN,C). | ||
|  |  normalize1(E,C) ?- | ||
|  | 	C=eq0(0,[CX*1]), | ||
|  | 	eqnonlin(CX,E).     % add a nonlinear equation constraint | ||
|  | 
 | ||
|  | 
 | ||
|  | % end of file math-utilities.pl ----------------------------------------------- |