Commit fd1ff122 authored by Mathieu Hemery's avatar Mathieu Hemery
Browse files

Merge branch 'feature/remove_fraction' into develop

parents ae6d6c33 831b1d38
......@@ -53,7 +53,9 @@
ode/2,
ode/3,
ode_add_expression_to_molecule/2,
ode_predicate/1
ode_predicate/1,
remove_fraction/2,
normalize_ode/1
]).
% Only for separate compilation/linking
......@@ -126,7 +128,9 @@ list_ode :-
(
get_current_ode_system(Id),
list_items([parent: Id, kind: ode]),
list_items([parent: Id, kind: initial_concentration])
list_items([parent: Id, kind: initial_concentration]),
list_items([parent: Id, kind: parameter]),
list_items([parent: Id, kind: function])
)
)
;
......@@ -422,15 +426,23 @@ remove_fraction :-
by the GCD. WARNING: the resulting ODE system is NOT equivalent to the starting one.'),
new_ode_system(NewId),
set_ode_system_name(NewId, without_fraction_ode),
normalize_ode(ListOde),
maplist(remove_fraction, ListOde, NewListOde),
maplist(add_ode(NewId), NewListOde),
with_current_ode_system((
get_current_ode_system(Id),
findall(X, ode(Id, X, Expr), ListVar),
forall(
ode(Id, X, Expr),
(
remove_fraction(Expr, ListVar, NewExpr),
add_ode(NewId, d( X ) / dt = NewExpr)
))
item([parent: Id, kind:parameter, item: Item]),
add_item([parent: NewId, kind:parameter, item: Item])
),
forall(
item([parent: Id, kind: function, item: Item]),
add_item([parent: NewId, kind: function, item: Item])
),
forall(
item([parent: Id, kind:initial_concentration, item: Item]),
add_item([parent: NewId, kind:initial_concentration, item: Item])
)
)),
select_ode_system(without_fraction_ode).
......@@ -577,6 +589,18 @@ add_ode(Id, ODE) :-
add_item([parent: Id, kind: ode, key: X, item: Item]).
change_ode(Id, ODE) :-
(
parse_ode(ODE, X, Item)
->
true
;
throw(error(illformed_ode(ODE)))
),
delete_item([parent: Id, kind: ode, key: X]),
add_item([parent: Id, kind: ode, key: X, item: Item]).
import_reactions_from_ode_system(Id) :-
check_cleaned(ode:assoc/2),
enumerate_terms_in_odes(Id),
......@@ -1269,9 +1293,10 @@ ode_add_expression_to_molecule(NewExpression, Molecule) :-
% remove all the fraction in an expression by multiplying all terms by the common
% denominator
remove_fraction(Expr, LV, NewExpr) :-
find_common_denominator(Expr, LV, Denominator),
multiply_each_term(Expr, Denominator, NewExpr).
remove_fraction(d( X )/dt = Expr, d( X )/dt = NewExpr) :-
find_common_denominator(Expr, Denominator),
multiply_each_term(Expr, Denominator, ExprTempo),
simplify(ExprTempo, NewExpr).
%! find_common_denominator(+Expr, +ListVariable, -ListDenominator)
......@@ -1279,36 +1304,23 @@ remove_fraction(Expr, LV, NewExpr) :-
% list all the denominator present in Expr, ListVariable is given as context in order to
% be able to skip parameters
find_common_denominator(_Term/Den + Expr, LV, [Den|Tail]) :-
find_common_denominator(Expr + _Num/Den, [Den|Tail]) :-
!,
find_common_denominator(Expr, LV, Tail).
find_common_denominator(Expr, Tail).
find_common_denominator(_Term/Den - Expr, LV, [Den|Tail]) :-
find_common_denominator(Expr + _Num, Tail) :-
!,
find_common_denominator(Expr, LV, Tail).
find_common_denominator(Expr, Tail).
find_common_denominator(_Term + Expr, LV, Tail) :-
!,
find_common_denominator(Expr, LV, Tail).
find_common_denominator(_Term - Expr, LV, Tail) :-
!,
find_common_denominator(Expr, LV, Tail).
find_common_denominator(_Term/Den, _LV, [Den]) :- !.
find_common_denominator(_Term, _LV, []).
find_common_denominator(_Term/Den, [Den]) :- !.
find_common_denominator(_Term, []).
%! multiply_each_term(+Expr, +ListDenominator, -NexExpr)
%
%
multiply_each_term(Head + Expr, Denominator, NewHead + NewExpr) :-
!,
multiply_term(Head, Denominator, NewHead),
multiply_each_term(Expr, Denominator, NewExpr).
multiply_each_term(Head - Expr, Denominator, NewHead - NewExpr) :-
multiply_each_term(Expr + Head, Denominator, NewExpr + NewHead) :-
!,
multiply_term(Head, Denominator, NewHead),
multiply_each_term(Expr, Denominator, NewExpr).
......@@ -1318,9 +1330,133 @@ multiply_each_term(Expr, Denominator, NewExpr) :-
multiply_term(Expr, Denominator, NewExpr).
multiply_term(Num/Den, Denominator, NewNum) :-
!,
subtract(Denominator, [Den], ToMult),
mult_by(Num, ToMult, NewNum).
mult_by(Num, [Head|Tail], NNum*Head) :-
mult_by(Num, Tail, NNum).
multiply_term(Num, Denominator, NewNum) :-
mult_by(Num, Denominator, NewNum).
mult_by(Num, [Head|Tail], NNum) :- !,
mult_by(Num, Tail, NumTempo),
distribute(NumTempo*Head, NNum).
mult_by(Num, [], Num).
%%%%%%%%%%%%%%%%%%%%%%%%%
%%% ODE NORMALIZATION %%%
%%%%%%%%%%%%%%%%%%%%%%%%%
%! normalize_ode(-Assoc)
%
% Return the normal form of the current ode system as a list: [d( X )/dt = Expr, etc.]
normalize_ode(NormalForm) :-
with_current_ode_system((
get_current_ode_system(Id),
findall(X, ode(Id, X, Expr), ListVar),
findall(
d( X )/dt = NewExpr,
(
ode(Id, X, Expr),
normalize_expression(Expr, ListVar, NewExpr)
),
NormalForm
)
)).
normalize_expression(Expr + Term, ListVar, NExpr + NTerm) :- !,
normalize_term(Term, ListVar, NTerm),
normalize_expression(Expr, ListVar, NExpr).
normalize_expression(Expr - Term, ListVar, NExpr + NTerm) :- !,
normalize_term(Term*(-1), ListVar, NTerm),
normalize_expression(Expr, ListVar, NExpr).
normalize_expression(-Term, ListVar, NTerm) :- !,
normalize_term(Term*(-1), ListVar, NTerm).
normalize_expression(Term, ListVar, NTerm) :-
normalize_term(Term, ListVar, NTerm).
normalize_term(Term, ListVar, NewTerm) :-
filter_denominator(Term, Numerator, Denominator),
filter_other(Numerator, ListVar, Numbers, Parameters, Variables),
rewrite_term(Numbers, Parameters, Variables, Denominator, NewTerm).
%! filter_denominator(Term, Numerator, Denominator)
filter_denominator(Term*X^N, Num, [NTerm|Den]) :-
number(N), N<0, !,
Nm is -N,
(
Nm = 1
->
NTerm = X
;
NTerm = X^Nm
),
filter_denominator(Term, Num, Den).
filter_denominator(Term*X^N, [X^N|Num], Den) :- !,
number(N), N>0, !,
filter_denominator(Term, Num, Den).
filter_denominator(Term*X, [X|Num], Den) :- !,
filter_denominator(Term, Num, Den).
filter_denominator(Term/X, Num, [X|Den]) :- !,
filter_denominator(Term, Num, Den).
filter_denominator(X^N, [], [NTerm]) :- !,
number(N), N<0, !,
Nm is -N,
(
Nm = 1
->
NTerm = X
;
NTerm = X^Nm
).
filter_denominator(X, [X], []).
filter_other([Head|Tail], LV, [Head|Numbers], Parameters, Variables) :-
number(Head),!,
filter_other(Tail, LV, Numbers, Parameters, Variables).
filter_other([Head|Tail], LV, Numbers, Parameters, [Head|Variables]) :-
member(Head, LV),!,
filter_other(Tail, LV, Numbers, Parameters, Variables).
filter_other([Head|Tail], LV, Numbers, [Head|Parameters], Variables) :- !,
filter_other(Tail, LV, Numbers, Parameters, Variables).
filter_other([],_LV,[],[],[]).
rewrite_term(Numbers, Parameter_list, Variable_list, Denominator, Term) :-
(
multiply_them(Numbers, Rate_list),
RateTempo is Rate_list
->
Rate = [RateTempo]
;
Rate = []
),
append([Rate, Parameter_list,Variable_list], Stuff_list),
(
multiply_them_rev(Stuff_list, Stuff)
->
true
;
Stuff = 1
),
(
Denominator = []
->
Term = Stuff
;
multiply_them(Denominator, Den),
Term = Stuff/Den
).
multiply_them_rev(List, Term) :-
reverse(List, RList),
multiply_them(RList, Term).
multiply_them([Term], Term) :- !.
multiply_them([Head|Tail], Term*Head) :-
multiply_them(Tail, Term).
......@@ -96,4 +96,12 @@ test(
list_file_lines('test.tex', Lines),
delete_file('test.tex').
test(
'remove_fraction',[]) :-
remove_fraction(d(a)/dt = a/b, d(a)/dt = a),
remove_fraction(d(a)/dt = a/(b+c) + d, d(a)/dt = a + d*b + d*c),
remove_fraction(d(a)/dt = a/(b+c) + -1*d, d(a)/dt = a - d*b - d*c),
remove_fraction(d(a)/dt = a/b + c/d + e, d(a)/dt = a*d + c*b + e*b*d),
remove_fraction(d(a)/dt = a/b + c/d, d(a)/dt = a*d + c*b).
:- end_tests(ode).
Supports Markdown
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