Attention une mise à jour du service Gitlab va être effectuée le mardi 30 novembre entre 17h30 et 18h00. Cette mise à jour va générer une interruption du service dont nous ne maîtrisons pas complètement la durée mais qui ne devrait pas excéder quelques minutes. Cette mise à jour intermédiaire en version 14.0.12 nous permettra de rapidement pouvoir mettre à votre disposition une version plus récente.

Commit 316968b6 authored by Mathieu Hemery's avatar Mathieu Hemery
Browse files

Merge branch 'feature/gpac' into develop

parents 9a44505a 638fd98e
......@@ -18,6 +18,7 @@ commands = [
"add_reaction",
"add_reactions_from_ode",
"add_reactions_from_ode_system",
"add_reactions_from_pivp",
"add_sbml",
"add_time_event",
"add_vertex",
......@@ -97,7 +98,6 @@ commands = [
"hybrid_static_simulation",
"import_ode",
"import_reactions_from_graph",
"infer_reactions_from_pivp",
"influence_graph",
"influence_hypergraph",
"influence_model",
......
......@@ -30,6 +30,7 @@ Rq: The distinction between pivp_string and pivp_list is not always obvious.
gpac,
[
%Commands
compile_from_expression/2,
compile_from_expression/3,
compile_from_pivp/2,
compile_from_pivp/3,
......@@ -39,7 +40,7 @@ Rq: The distinction between pivp_string and pivp_list is not always obvious.
pode/1,
pivp/1,
%API
format_pivp/2
format_pivp/3
]).
:- use_module(library(clpfd)).
......@@ -62,7 +63,43 @@ Rq: The distinction between pivp_string and pivp_list is not always obvious.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
:- initial(option(binomial_reduction: no)).
:- initial(option(lazy_negation: yes)).
:- initial(option(lazy_negatives: yes)).
%! compile_from_expression(+Expr, +Output)
%
% biocham command
%
% Creates a biochemical reaction network such that Output = Expr(t)
%
% Typical usage will be:
% ==
% :- compile_from_expression(4 + id*id, output).
% ==
compile_from_expression(Expr, Output) :-
biocham_command,
type(Expr, arithmetic_expression),
type(Output, name),
doc('
creates a biochemical reaction network such that Output = Expr(t).
'),
option(
binomial_reduction,
yesno,
_Reduction,
'Determine if the binomial reduction has to be performed'
),
option(
lazy_negatives,
yesno,
_Lazyness,
'Switch between a brutal or a lazy negation'
),
expression_to_PIVP(Expr, PIVP),
PIVP = [N, _PODE, _IC],
abstract_names(N, Output, Name_list),
main_compiler(PIVP, Name_list, time).
%! compile_from_expression(+Expr, +Input, +Output)
%
......@@ -72,7 +109,7 @@ Rq: The distinction between pivp_string and pivp_list is not always obvious.
%
% Typical usage will be:
% ==
% :- compile_from_expression(4 + id*id, time, output).
% :- compile_from_expression(4 + id*id, Input, Output).
% ==
compile_from_expression(Expr, Input, Output) :-
......@@ -81,8 +118,7 @@ compile_from_expression(Expr, Input, Output) :-
type(Input, name),
type(Output, name),
doc('
creates a biochemical reaction network such that Output = Expr(Input). Use \'time\' as
input to get Output = Expr(t).
creates a biochemical reaction network such that Output = Expr(Input).
'),
option(
binomial_reduction,
......@@ -91,18 +127,20 @@ compile_from_expression(Expr, Input, Output) :-
'Determine if the binomial reduction has to be performed'
),
option(
lazy_negation,
lazy_negatives,
yesno,
_Lazyness,
'Switch between a brutal or a lazy negation'
),
expression_to_PIVP(Expr, PIVP),
main_compiler(PIVP, Input, Output).
PIVP = [N, _PODE, _IC],
abstract_names(N, Output, Name_list),
main_compiler(PIVP, Name_list, Input).
:- doc('
\\begin{example} Compilation of the expression 4+time^2:\n
').
:- biocham(compile_from_expression(4 + id*id, time, output)).
:- biocham(compile_from_expression(4 + id*id, output)).
:- biocham(list_model).
:- biocham(numerical_simulation(time:4)). %, method:msbdf)).
:- biocham(plot).
......@@ -113,7 +151,7 @@ compile_from_expression(Expr, Input, Output) :-
:- doc('
\\begin{example} Compilation of the expression cos(time):\n
').
:- biocham(compile_from_expression(cos, time, f)).
:- biocham(compile_from_expression(cos, cos)).
:- biocham(list_model).
:- biocham(numerical_simulation(time:10)). %, method:msbdf)).
:- biocham(plot).
......@@ -125,7 +163,7 @@ compile_from_expression(Expr, Input, Output) :-
:- doc('
\\begin{example} Compilation of the expression cos(x) and computation of cos(4):\n
').
:- biocham(compile_from_expression(cos, x, r)).
:- biocham(compile_from_expression(cos, x, cos)).
:- biocham(list_model).
:- biocham(parameter(input = 4)).
:- biocham(numerical_simulation(time:10)). %, method:msbdf)).
......@@ -138,31 +176,92 @@ compile_from_expression(Expr, Input, Output) :-
:- doc('One can also compile real valued functions defined as solutions of Polynomial Initial Value Problems (PIVP), i.e. solutions of polynomial differential equations, using the following syntax:').
%! compile_from_pivp(+PIVP_string, +Output)
%
% biocham command
%
% Creates a biochemical reaction network that computes the projection of multivariate function f(t) on one variable Output,
% where f(t) is the solution of the PIVP.
%
% Typical usage will be:
% ==
% :- compile_from_pivp( ((1,(d(y)/dt=z)); (0,(d(z)/dt= (-1*y)))), y).
% ==
compile_from_pivp(PIVP, Output) :-
biocham_command,
type(PIVP, pivp),
type(Output, name),
doc('
compiles a PIVP into a CRN (with initial concentration values) that computes the projection on one variable Output as a function of time, of the multivariate function f(t) solution of the PIVP.
'),
option(
binomial_reduction,
yesno,
_Reduction,
'Determine if the binomial reduction has to be performed'
),
sort_output(PIVP, Output, PIVP_sorted),
compile_from_pivp(PIVP_sorted, time, Output).
%! compile_from_pivp(+PIVP_string, +Input , +Output)
%
% biocham command
%
% Creates a biochemical reaction network that computes the projection of multivariate function f(Input) on one variable Output,
% where f(t) is the solution of the PIVP, and Input is a time value
%
% Typical usage will be:
% ==
% :- compile_from_pivp( ((1,(d(y)/dt=z)); (0,(d(z)/dt= (-1*y)))), 4, y).
% ==
compile_from_pivp(PIVP, Input, Output) :-
biocham_command,
type(PIVP, pivp),
type(Input, name), % FF type(Input, expr),
type(Output, name),
doc('
compiles a PIVP into a CRN (with initial concentration values) that computes the value of variable Output at time Input, of the multivariate function f(t) solution of the PIVP.
'),
option(
binomial_reduction,
yesno,
_Reduction,
'Determine if the binomial reduction has to be performed'
),
sort_output(PIVP, Output, PIVP_sorted),
format_pivp(PIVP_sorted, P, Name_list),
main_compiler(P, Name_list, Input).
:- doc('
\\begin{example} Compilation of a simple oscillator with 2 species\n
\\begin{example} Compilation of a simple oscillator with 2 species (Lotka-Volterra)\n
').
:- biocham(option(lazy_negation:yes)).
:- biocham(compile_from_pivp((0.5,(d(x)/dt= x - x*y));(0.25,(d(y)/dt= x*y - 0.5*y)),time,output)).
:- biocham(option(lazy_negatives:yes)).
:- biocham(compile_from_pivp((0.5,(d(x)/dt= x - x*y));(0.25,(d(y)/dt= x*y - 0.5*y)), x)).
:- biocham(list_model).
:- biocham(numerical_simulation(time:10)). % method:msbdf
:- biocham(plot(show:{output,'A'})).
:- biocham(plot(show:{'x','y'})).
:- doc('
\\end{example}
').
%:- doc('
% \\begin{example} Compilation of a Hill function of order 2 as a function of input\n
%').
%:- biocham(option(lazy_negation:yes)).
%:- biocham(option(binomial_reduction:yes)).
%:- biocham(compile_from_pivp((0.0,(d(h)/dt= 2*x*x*y)),(1.0,(d(x)/dt= -2*x*x*y));(0.0,(d(y)/dt= 1)),input,hill)).
%:- biocham(list_model).
%:- biocham(numerical_simulation(time:10)). % method:msbdf
%:- biocham(plot(show:{hill})).
%:- biocham(plot(show:{hill}, logscale:x)).
%:- doc('
% \\end{example}
%').
:- doc('
\\begin{example} Compilation of a Hill function of order 2 as a function of input\n
').
:- biocham(option(lazy_negatives:yes)).
:- biocham(option(binomial_reduction:yes)).
:- biocham(compile_from_pivp((0.0,d(h)/dt= 2*x*x*y;1.0,d(x)/dt= -2*x*x*y;0.0,d(y)/dt=1),in,h)).
:- biocham(parameter(input=2)).
:- biocham(list_model).
:- biocham(numerical_simulation(time:10)). % method:msbdf
:- biocham(plot(show:{h})).
:- biocham(plot(show:{h}, logscale:x)).
:- doc('
\\end{example}
').
% Definition of the various grammars used in this module:
......@@ -241,73 +340,6 @@ monomial(X) :-
name(X).
%! compile_from_pivp(+PIVP_string, +Output)
%
% biocham command
%
% Creates a biochemical reaction network that computes the projection of multivariate function f(t) on one variable Output,
% where f(t) is the solution of the PIVP.
%
% Typical usage will be:
% ==
% :- compile_from_pivp( ((1,(d(y)/dt=z)); (0,(d(z)/dt= (-1*y)))), y).
% ==
compile_from_pivp(PIVP, Output) :-
biocham_command,
type(PIVP, pivp),
type(Output, name),
doc('
compiles a PIVP into a CRN (with initial concentration values) that computes the projection on one variable Output as a function of time, of the multivariate function f(t) solution of the PIVP.
'),
option(
binomial_reduction,
yesno,
_Reduction,
'Determine if the binomial reduction has to be performed'
),
compile_from_pivp(PIVP, time, Output).
%! compile_from_pivp(+PIVP_string, +Input , +Output)
%
% biocham command
%
% Creates a biochemical reaction network that computes the projection of multivariate function f(Input) on one variable Output,
% where f(t) is the solution of the PIVP, and Input is a time value
%
% Typical usage will be:
% ==
% :- compile_from_pivp( ((1,(d(y)/dt=z)); (0,(d(z)/dt= (-1*y)))), 4, y).
% ==
compile_from_pivp(PIVP, Input, Output) :-
biocham_command,
type(PIVP, pivp),
type(Input, name), % FF type(Input, expr),
type(Output, name),
doc('
compiles a PIVP into a CRN (with initial concentration values) that computes the value of variable Output at time Input, of the multivariate function f(t) solution of the PIVP.
'),
option(
binomial_reduction,
yesno,
_Reduction,
'Determine if the binomial reduction has to be performed'
),
format_pivp(PIVP, P),
main_compiler(P, Input, Output).
:- devdoc('\\begin{todo} Compilation of the cosine function as a function of time defined as the solution of a PIVP)\n
\\texttt{
:- biocham(compile_from_pivp(((1,(d(y)/dt=z)); (0,(d(z)/dt= (-1*y)))), time, output)).
:- biocham(list_model).
:- biocham(numerical_simulation(time:10)).
:- biocham(plot).
}
\\end{todo}
').
:- devdoc('
The internal data structure for PIVPs (Polynomial differential equations
Initial Value Problems) is
......@@ -321,7 +353,7 @@ compile_from_pivp(PIVP, Input, Output) :-
').
%! main_compiler(+PIVP_list, +Input, +Output)
%! main_compiler(+PIVP_list, +Name_list, +Input)
%
% Compile a PIVP_list, this predicate dispatch the various options of compilation
% it first check if the PIVP should be reduce to a binomial form
......@@ -329,27 +361,29 @@ compile_from_pivp(PIVP, Input, Output) :-
% when Input is not time it then call g_to_c_PIVP/3.
% and finally make a call to compile_to_biocham_model to make the final implementation
main_compiler(PIVP_input, Input, Output):-
main_compiler(PIVP_input, Name_list_raw, Input):-
clear_model,
get_option(fast_rate, Fast),
get_option(lazy_negation, Lazyness),
get_option(lazy_negatives, Lazyness),
get_option(binomial_reduction, Reduction),
(
Input = time
->
PIVP_non_bin = PIVP_input
PIVP_non_bin = PIVP_input,
Name_list_non_bin = Name_list_raw
;
g_to_c_PIVP(PIVP_input, PIVP_non_bin, 1.0)
g_to_c_PIVP(PIVP_input, PIVP_non_bin, 1.0),
append(Name_list_raw, [Input], Name_list_non_bin)
),
(
Reduction = yes
->
reduce_to_binomial(PIVP_non_bin,PIVP_unsigned)
reduce_to_binomial(PIVP_non_bin, Name_list_non_bin, PIVP_unsigned, Name_list_unsigned)
;
PIVP_unsigned = PIVP_non_bin
PIVP_unsigned = PIVP_non_bin,
Name_list_unsigned = Name_list_non_bin
),
PIVP_unsigned = [N,_PODE,_IV],
get_option(lazy_negation, Lazyness),
get_option(lazy_negatives, Lazyness),
(
Lazyness = yes
->
......@@ -357,7 +391,8 @@ main_compiler(PIVP_input, Input, Output):-
;
lng:rewrite_PIVP_all_negated(PIVP_unsigned, PIVP, VarNeg)
),
affect_name(N,Output,Input,VarNeg,Species_names),
sort(VarNeg, VarNegSort),
negate_name(Name_list_unsigned, VarNegSort, Species_names),
(
\+(VarNeg = [])
->
......@@ -372,17 +407,18 @@ main_compiler(PIVP_input, Input, Output):-
%%% Tools to format a PIVP_string to a PIVP_list %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%! format_pivp(+PIVP_string, -PIVP_list)
%! format_pivp(+PIVP_string, -PIVP_list, -Name_list)
%
% Generates the PIVP_list object corresponding to a given PIVP_string
% Generates the PIVP_list object and the Name_list corresponding to a given PIVP_string
format_pivp(P, [N, Pode, Init]):-
format_pivp(P, [N, Pode, Init], Name_list):-
find_variables(P, L, Init),
length(L, N), % should put 1 if no variable ?
parse_pivp(P, L, Pode).
parse_pivp(P, L, Pode),
extract_names(P, Name_list).
:- devdoc('
\\command{format_pivp/2} encodes a PIVP syntax tree into the internal list
\\command{format_pivp/3} encodes a PIVP syntax tree into the internal list
representation for PIVPs.
').
......@@ -400,6 +436,23 @@ find_variables((X;Y), L, Init):-
append(I1, I2, Init).
%! sort_output(+PIVP, +Output, -PIVP_sorted)
%
% Ensure that Output is the first variable of the PIVP (here as a string)
sort_output((IC, d(Out)/dt = Deriv), Out, (IC, d(Out)/dt = Deriv)) :- !.
sort_output((IC, d(Out)/dt = Deriv);Remainder, Out, (IC, d(Out)/dt = Deriv);Remainder) :- !.
sort_output(Remainder;(IC, d(Out)/dt = Deriv), Out, (IC, d(Out)/dt = Deriv);Remainder) :- !.
sort_output(R1;(IC, d(Out)/dt = Deriv);R2, Out, (IC, d(Out)/dt = Deriv);R1;R2) :- !.
sort_output(_PIVP1, _Out, _PIVP2) :-
print_message(warning, 'Output should be a variable of the PIVP'),
fail.
%! parse_pivp(+PIVP_string, +ListVariableNames, -Pode)
%
% Giving the PIVP_string and its variable, extract the list representation
......@@ -483,6 +536,16 @@ make_monomial([_|L], X, Y, [0|M]) :-
make_monomial(L, X, Y, M).
%! extract_names(+PIVP_string, -Name_list)
%
% Extract the names of the variables of the PIVP_string
extract_names((_IC, d(Name)/dt = _Deriv), [Name]) :- !.
extract_names((_IC, d(Name)/dt = _Deriv; Remainder), [Name|Tail]) :-
extract_names(Remainder, Tail).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Tools to manipulate PIVP_list internal objects %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
......@@ -747,11 +810,11 @@ compose_multivar_vector([P|PV], PL, [Q|QV]) :-
%%% Reduction to binomial PIVP %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%! reduce_to_binomial(PIVP,Modified_PIVP)
%! reduce_to_binomial(+PIVP, +Name_list, -Modified_PIVP, -Modified_Names)
%
% Reduce a given PIVP to a new one which only need binomial
reduce_to_binomial([N,PODE,IV],[NewN,NewPODE,NewIV]) :-
reduce_to_binomial([N,PODE,IV], Name_list, [NewN,NewPODE,NewIV], Modified_Names) :-
scan_order_multivarvector(PODE,Order),
(
Order > 2
......@@ -761,11 +824,13 @@ reduce_to_binomial([N,PODE,IV],[NewN,NewPODE,NewIV]) :-
length(ListVariable,NewN),
% binomial_branch_bound(ListAllVariable, PODE, ListVariable, NewN),
rewrite_pode(ListVariable,PODE,ListVariable,NewPODE),
generate_iv(ListVariable,IV,NewIV)
generate_iv(ListVariable,IV,NewIV),
generate_names(Name_list, ListVariable, Modified_Names)
; % PIVP is already binomial
NewN = N,
NewPODE = PODE,
NewIV = IV
NewIV = IV,
Modified_Names = Name_list
).
......@@ -1075,6 +1140,29 @@ set_new_iv([Exp|TailE],[Value|TailV],NewValue) :-
NewValue = NewValueTempo * Value^Exp
).
%! generate_names(+Name_list, +List_variable, -Modified_Names)
%
% Generate the names of the new variable
generate_names(_Name_list, [], []) :- !.
generate_names(Name_list, [Var|TailVar], [Name|TailName]) :-
write_new_name(Name_list, Var, Name_as_list),
atomic_list_concat(Name_as_list, Name),
generate_names(Name_list, TailVar, TailName).
write_new_name([], [], []) :- !.
write_new_name([_Name|TailName], [0|TailExp], Name_as_list) :- !,
write_new_name(TailName, TailExp, Name_as_list).
write_new_name([Name|TailName], [1|TailExp], [Name|Name_as_list]) :- !,
write_new_name(TailName, TailExp, Name_as_list).
write_new_name([Name|TailName], [N|TailExp], [Name,N|Name_as_list]) :- !,
write_new_name(TailName, TailExp, Name_as_list).
%! scan_order_multivarvector(+MultivarVector,-Order)
%
......@@ -1517,42 +1605,26 @@ exponant_to_solution([Exp|Tail_exp], [Name|Tail_name], Sol, Kin) :-
).
%! affect_name(+N,+Output,+Input,+Varneg,-Name_list)
%! negate_name(+Name_list_raw, +Varneg, -Name_list)
%
% Create the name of the species
% Add _p and _m to the name of variables if necessary
affect_name(N,Output,Input,Varneg,Name_list) :-
affect_name(N,0,Output,Input,Varneg,Name_list).
negate_name(NLR, VN, NL) :-
negate_name(NLR, 1, VN, NL).
affect_name(N,N,_Output,_Input,_Varneg,[]) :- !.
negate_name([], _N, [], []) :- !.
affect_name(N,Nc,Output,Input,Varneg,Name_list) :-
get_option(lazy_negation, Lazyness),
Nxt is Nc+1,
(
Nxt = 1
->
Name = Output
;
Lazyness = no,
Nxt = N
->
Name = Input
;
Nchar is Nxt+63,
char_code(Name,Nchar)
),
(
member(Nxt,Varneg)
->
name_p_m(Name,Name_p,Name_m),
add_reaction(fast*Name_p*Name_m for Name_p+Name_m=>_),
Head = [Name_p,Name_m]
;
Head = [Name]
),
affect_name(N,Nxt,Output,Input,Varneg,Tail),
append(Head,Tail,Name_list).
negate_name([Name|TailName], N, [N|TailNeg], [Name_p,Name_m|TailNewName]) :-
!,
name_p_m(Name,Name_p,Name_m),
add_reaction(fast*Name_p*Name_m for Name_p+Name_m=>_),
NN is N+1,
negate_name(TailName, NN, TailNeg, TailNewName).
negate_name([Name|TailName], N, VarNeg, [Name|TailNewName]) :-
!,
NN is N+1,
negate_name(TailName, NN, VarNeg, TailNewName).
%! name_p_m(+Name,-Positive_name,-Negative_name)
......@@ -1636,3 +1708,31 @@ expression_to_PIVP(E / F, PIVP) :-
expression_to_PIVP(E, _) :-
throw(error(illegal_expression(E), expression_to_PIVP)).
%! abstract_names(+N, +Output, -Name_list)
abstract_names(N, Output, [Output|RTail]) :-
Nm is N-1,
abstract_names(Nm, Tail),
reverse(Tail, RTail).
abstract_names(0, []) :- !.
abstract_names(N, [Head|Tail]) :-
Nm is N-1,
divmod(Nm,26,R,C),
Code is C+65,
Rep is R+1,
char_code(Letter, Code),
stutter(Rep, Letter, Head),
abstract_names(Nm, Tail).
%! stutter(N,In,Out)
stutter(1, In, In) :- !.
stutter(N, In, Out) :-
Nm is N-1,
stutter(Nm, p, Tempo),
atom_concat(In, Tempo, Out).
......@@ -9,16 +9,29 @@
test(format_pivp_exp) :-
gpac:format_pivp(((1,(d(y)/dt=(-2*y)))),
[1,[[[-2,[1]]]],[1]] ).
[1,[[[-2,[1]]]],[1]],
[y]).
test(format_pivp_cosinus) :-
gpac:format_pivp(((1,(d(y)/dt=z)); (0,(d(z)/dt= (-1*y)))),
[2,[[[1,[0, 1]]],[[-1,[1, 0]]]],[1,0]] ).
[2,[[[1,[0, 1]]],[[-1,[1, 0]]]],[1,0]],
[y,z]).
% This PIVP generates choicepoints in the cutting of y*z+3*z, hence the once
test(format_pivp_higher_order) :-
once(gpac:format_pivp(((1,(d(y)/dt=y*z+3*z)); (5,(d(z)/dt= (-1*y^3)))),
[2,[[[1,[1, 1]],[3,[0, 1]]],[[-1,[3, 0]]]],[1,5]] )).
[2,[[[1,[1, 1]],[3,[0, 1]]],[[-1,[3, 0]]]],[1,5]],
[y,z])).
test(sort_output) :-
gpac:sort_output((1,d(cos)/dt=(-1*sin);0,d(sin)/dt=cos),cos,(1,d(cos)/dt=(-1*sin);0,d(sin)/dt=cos)),
gpac:sort_output((0,d(sin)/dt=cos;1,d(cos)/dt=(-1*sin)),cos,(1,d(cos)/dt=(-1*sin);0,d(sin)/dt=cos)).
test(extract_names) :-
gpac:extract_names((1, d(a)/dt = 1; 2, d(b)/dt = 2), [a,b]).
test(generate_names) :-
gpac:generate_names([a,'Out'], [[1,2],[1,0]], [aOut2, a]).
%%% Test of g_to_c %%%
test(g_to_c_PIVP) :-
......@@ -50,11 +63,11 @@ test(generate_sufficient_variables3) :-
once(permutation(Set, [[1,0],[0,1],[0,2]])).
test(reduce_to_binomial_nomodif) :-
once(gpac:reduce_to_binomial([2,[[[1,[1, 1]]],[[-1,[1, 0]]]],[1,2]],P)),
once(gpac:reduce_to_binomial([2,[[[1,[1, 1]]],[[-1,[1, 0]]]],[1,2]],[a,b],P,[a,b])),
P = [2,[[[1,[1, 1]]],[[-1,[1, 0]]]],[1,2]].
test(reduce_to_binomial_simple) :-
once(gpac:reduce_to_binomial([2,[[[1,[1, 2]]],[[-1,[1, 0]]]],[1,2]],P)),
once(gpac:reduce_to_binomial([2,[[[1,[1, 2]]],[[-1,[1, 0]]]],[1,2]],[a,b],P,[a,b,b2])),
P = [3,[[[1, [1, 0, 1]]], [[-1, [1, 0, 0]]], [[-2, [1, 1, 0]]]],[1,2,4]].
test(scan_order_multivar) :-
......
......@@ -3,13 +3,13 @@
[
rewrite_ode/2,
%Commands