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 -----------------------------------------------
							 |