Commit dcef3978 authored by Mathieu Hemery's avatar Mathieu Hemery

Introduce the determine_boundary function (still buggy)

parent cf83205f
......@@ -7,6 +7,7 @@
always_negative/1,
always_positive/1,
determine_sign/2,
determine_boundary/3,
normalize_number/2,
is_null/1,
zero_like/1,
......@@ -19,6 +20,7 @@
:- use_module(doc).
:- use_module(util).
:- set_prolog_flag(float_overflow, infinity).
:- dynamic(canonical/3).
......@@ -693,13 +695,93 @@ arithmetic_operation(_ ^ _).
% Check if Expr is assure to be always negative/positive, fail if it can change sign
% or if it is impossible to decide
always_positive(Expr) :-
determine_boundary(Expr, I, _U),
I >= 0.
always_negative(Expr) :-
determine_sign(Expr, zero);
determine_sign(Expr, neg).
determine_boundary(Expr, _I, U),
U =< 0.
always_positive(Expr) :-
determine_sign(Expr, zero);
determine_sign(Expr, pos).
%always_negative(Expr) :-
% determine_sign(Expr, zero);
% determine_sign(Expr, neg).
%
%always_positive(Expr) :-
% determine_sign(Expr, zero);
% determine_sign(Expr, pos).
%! determine_boundary(+Expr, -Up, -Down)
%
% Try to evaluate the boundary of an expression
determine_boundary(X, N, N) :-
is_numeric(X, N),
!.
determine_boundary(X, 0, 1.0Inf) :-
atom(X),
!.
determine_boundary(A+B, IAB, UAB) :-
determine_boundary(A, IA, UA),
determine_boundary(B, IB, UB),
IAB is IA+IB,
UAB is UA+UB.
determine_boundary(A-B, IAB, UAB) :-
determine_boundary(A, IA, UA),
determine_boundary(B, IB, UB),
IAB is IA-UB,
UAB is UA-IB.
determine_boundary(-A, ImA, UmA) :-
determine_boundary(A, IA, UA),
ImA is -UA,
UmA is -IA.
determine_boundary(A*B, IAB, UAB) :-
determine_boundary(A, IA, UA),
determine_boundary(B, IB, UB),
((IA=0; IB=0) -> T1 = 0; T1 is IA*IB),
((UA=0; IB=0) -> T2 = 0; T2 is UA*IB),
((IA=0; UB=0) -> T3 = 0; T3 is IA*UB),
((UA=0; UB=0) -> T4 = 0; T4 is UA*UB),
min_list([T1, T2, T3, T4], IAB),
max_list([T1, T2, T3, T4], UAB).
determine_boundary(A/B, IAB, UAB) :-
determine_boundary(A, IA, UA),
determine_boundary(B, IB, UB),
((IB =:= inf; IB =:= -inf) -> T1 = 0; T1 is IA/IB),
((UB =:= inf; UB =:= -inf) -> T2 = 0; T2 is IA/UB),
((IB =:= inf; IB =:= -inf) -> T3 = 0; T3 is UA/IB),
((UB =:= inf; UB =:= -inf) -> T4 = 0; T4 is UA/UB),
min_list([T1, T2, T3, T4], IAB),
max_list([T1, T2, T3, T4], UAB).
determine_boundary(A^N, IAB, UAB) :-
determine_boundary(A, IA, UA),
is_numeric(N, NN),
(
NN > 0
->
IAB is IA^NN,
UAB is UA^NN
;
IAB is UA^NN,
UAB is IA^NN
).
determine_boundary(exp(A), IAB, UAB) :-
determine_boundary(A, IA, UA),
IAB is exp(IA),
UAB is exp(UA).
determine_boundary(sin(_X), -1, 1).
determine_boundary(cos(_X), -1, 1).
%! determine_sign(+Expr, -Sign)
......
......@@ -23,6 +23,15 @@ test('determine_sign', []) :-
determine_sign((x-1)^k1, pos),
determine_sign((x-1)^k2, dnk).
test('always_positive_negative', []) :-
parameter([k1 = 2, k2 = 3]),
always_positive((a+1)^2),
always_negative(-exp(a)),
always_positive(a/(a+1)),
always_positive((2+a)*0),
always_negative((2+a)*0),
always_positive((x-1)^k1),
true.
test('is_null', []) :-
is_null(a*0*1/2),
......
......@@ -49,6 +49,7 @@ test('test_wf_reactant', []) :-
test('test_wf_inhibitor', []) :-
with_output_to(atom(_), (
parameter([k=1, n=2, k100=10]),
test_wf_inhibitor(a, b/(1+a)),
test_wf_inhibitor(a, b/(k+a)^2),
test_wf_inhibitor(c1, v10*t3^n/(k100^n+t3^n+c1^n)),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment