reaction_editor.pl 9.78 KB
Newer Older
Thierry Martinez's avatar
Thierry Martinez committed
1
:- module(
Thierry Martinez's avatar
Thierry Martinez committed
2
  reaction_editor,
Thierry Martinez's avatar
Thierry Martinez committed
3
  [
Thierry Martinez's avatar
Thierry Martinez committed
4
    % Commands
Thierry Martinez's avatar
Thierry Martinez committed
5 6
    add_reaction/1,
    list_reactions/0,
Thierry Martinez's avatar
ode  
Thierry Martinez committed
7 8
    simplify_all_reactions/0,
    add_reaction/4,
Thierry Martinez's avatar
Thierry Martinez committed
9 10 11
    % Public API
    is_reaction_model/0,
    check_reaction_model/0,
12
    list_model_reactions/0,
Thierry Martinez's avatar
Thierry Martinez committed
13
    reaction/5,
Thierry Martinez's avatar
Thierry Martinez committed
14 15
    reaction/4,
    enumerate_molecules/1,
Thierry Martinez's avatar
ode  
Thierry Martinez committed
16
    solution_to_list/2,
17 18
    list_to_solution/2,
    compute_ode_for_reaction_model/0
Thierry Martinez's avatar
Thierry Martinez committed
19 20 21
  ]
).

Thierry Martinez's avatar
ode  
Thierry Martinez committed
22 23 24 25

:- devdoc('\\section{Commands}').


Thierry Martinez's avatar
Thierry Martinez committed
26
add_reaction(Reaction) :-
Thierry Martinez's avatar
Thierry Martinez committed
27
  biocham_command,
Thierry Martinez's avatar
Thierry Martinez committed
28
  type(Reaction, reaction),
Thierry Martinez's avatar
Thierry Martinez committed
29 30
  doc('
    adds reaction rules to the current set of reactions.
Thierry Martinez's avatar
Thierry Martinez committed
31 32
    This command is implicit: reaction rules can be added directly in
    reaction models.
Thierry Martinez's avatar
Thierry Martinez committed
33
  '),
Thierry Martinez's avatar
ode  
Thierry Martinez committed
34 35 36 37 38 39
  \+ (
    reaction(Reaction, Kinetics, Reactants, Products),
    \+ (
      add_reaction(Kinetics, Reactants, Products, false)
    )
  ).
Thierry Martinez's avatar
Thierry Martinez committed
40

Thierry Martinez's avatar
Thierry Martinez committed
41

Thierry Martinez's avatar
ode  
Thierry Martinez committed
42 43 44 45 46 47 48 49 50 51 52 53 54 55
%simplify_all_reactions :-
%  biocham_command,
%  doc('
%    replaces each reaction by a simplified form, by grouping common molecules,
%    identifying catalysts, and by using the canonical molecule for aliases.
%  '),
%  \+ (
%    item([kind: reaction, id: Id, item: Reaction]),
%    \+ (
%      delete_item(Id),
%      simplify_reaction(Reaction, SimplifiedReaction),
%      add_item([kind: reaction, item: SimplifiedReaction])
%    )
%  ).
Thierry Martinez's avatar
Thierry Martinez committed
56 57


Thierry Martinez's avatar
Thierry Martinez committed
58
list_reactions :-
Thierry Martinez's avatar
Thierry Martinez committed
59
  biocham_command,
Thierry Martinez's avatar
Thierry Martinez committed
60 61
  doc('lists the current set of reaction rules.'),
  check_reaction_model,
Thierry Martinez's avatar
Thierry Martinez committed
62
  list_items([kind: reaction]).
Thierry Martinez's avatar
Thierry Martinez committed
63

Thierry Martinez's avatar
Thierry Martinez committed
64

Thierry Martinez's avatar
ode  
Thierry Martinez committed
65 66 67
:- devdoc('\\section{Public API}').


Thierry Martinez's avatar
Thierry Martinez committed
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
is_reaction_model :-
   devdoc('
     succeeds if the current model is a reaction model
     (i.e., does not contain any influence rules).
   '),
   \+ item([kind: influence]).


check_reaction_model :-
  (
    is_reaction_model
  ->
    true
  ;
    throw(error(not_a_reaction_model, check_reaction_model))
  ).


86 87 88 89 90 91 92 93 94 95 96 97 98
list_model_reactions :-
  devdoc('
    lists all the reaction rules in a loadable syntax
    (auxiliary predicate of list_model).
  '),
  \+ (
    item([no_inheritance, kind: reaction, item: Reaction]),
    \+ (
      format('~w.\n', [Reaction])
    )
  ).


Thierry Martinez's avatar
Thierry Martinez committed
99 100 101
prolog:error_message(not_a_reaction_model) -->
  ['Not a reaction model'].

Thierry Martinez's avatar
ode  
Thierry Martinez committed
102 103

add_reaction(Kinetics, Left, Right, Reversible) :-
Thierry Martinez's avatar
Thierry Martinez committed
104 105 106 107 108 109 110 111 112 113
  \+ (
    (
      member(_ * Object, Left)
    ;
      member(_ * Object, Right)
    ),
    \+ (
      check_identifier_kind(Object, object)
    )
  ),
Thierry Martinez's avatar
ode  
Thierry Martinez committed
114
  make_reaction(Kinetics, Left, Right, Reversible, Reaction),
Thierry Martinez's avatar
Thierry Martinez committed
115
  check_reaction_model,
Thierry Martinez's avatar
ode  
Thierry Martinez committed
116 117 118
  add_item([kind: reaction, item: Reaction]).


Thierry Martinez's avatar
Thierry Martinez committed
119
simplify_all_reactions :-
Thierry Martinez's avatar
ode  
Thierry Martinez committed
120 121 122 123 124
%  biocham_command,
%  doc('
%    replaces each reaction by a simplified form, by grouping common molecules,
%    identifying catalysts, and by using the canonical molecule for aliases.
%  '),
Thierry Martinez's avatar
Thierry Martinez committed
125
  \+ (
Thierry Martinez's avatar
Thierry Martinez committed
126
    item([kind: reaction, id: Id, item: Reaction]),
Thierry Martinez's avatar
Thierry Martinez committed
127 128
    \+ (
      delete_item(Id),
Thierry Martinez's avatar
Thierry Martinez committed
129
      simplify_reaction(Reaction, SimplifiedReaction),
Thierry Martinez's avatar
Thierry Martinez committed
130
      add_item([kind: reaction, item: SimplifiedReaction])
Thierry Martinez's avatar
Thierry Martinez committed
131 132 133
    )
  ).

Thierry Martinez's avatar
Thierry Martinez committed
134

Thierry Martinez's avatar
Thierry Martinez committed
135
reaction(Item, Kinetics, Reactants, Products, Reversible) :-
Thierry Martinez's avatar
Thierry Martinez committed
136
  (
Thierry Martinez's avatar
Thierry Martinez committed
137
    Item = (Kinetics for Body)
Thierry Martinez's avatar
Thierry Martinez committed
138 139 140
  ->
    true
  ;
Thierry Martinez's avatar
Thierry Martinez committed
141
    Kinetics = 'MA'(1),
Thierry Martinez's avatar
Thierry Martinez committed
142 143
    Body = Item
  ),
Thierry Martinez's avatar
Thierry Martinez committed
144
  (
Thierry Martinez's avatar
Thierry Martinez committed
145 146
    Body = (Left =[ Catalyst ]=> Right)
  ->
Thierry Martinez's avatar
Thierry Martinez committed
147
    Reversible = false
Thierry Martinez's avatar
Thierry Martinez committed
148 149 150
  ;
    Body = (Left <=[ Catalyst ]=> Right)
  ->
Thierry Martinez's avatar
Thierry Martinez committed
151
    Reversible = true
Thierry Martinez's avatar
Thierry Martinez committed
152
  ;
Thierry Martinez's avatar
Thierry Martinez committed
153
    Body = (Left => Right)
Thierry Martinez's avatar
Thierry Martinez committed
154
  ->
Thierry Martinez's avatar
Thierry Martinez committed
155
    Reversible = false,
Thierry Martinez's avatar
Thierry Martinez committed
156 157
    Catalyst = '_'
  ;
Thierry Martinez's avatar
Thierry Martinez committed
158
    Body = (Left <=> Right)
Thierry Martinez's avatar
Thierry Martinez committed
159
  ->
Thierry Martinez's avatar
Thierry Martinez committed
160
    Reversible = true,
Thierry Martinez's avatar
Thierry Martinez committed
161 162
    Catalyst = '_'
  ),
Thierry Martinez's avatar
Thierry Martinez committed
163 164 165
  solution_to_canonical_list(Left, LeftMolecules),
  solution_to_canonical_list(Right, RightMolecules),
  solution_to_canonical_list(Catalyst, CatalystMolecules),
Thierry Martinez's avatar
Thierry Martinez committed
166 167 168
  append(CatalystMolecules, LeftMolecules, Reactants),
  append(CatalystMolecules, RightMolecules, Products).

Thierry Martinez's avatar
Thierry Martinez committed
169 170
reaction(Item, Kinetics, Reactants, Products) :-
  reaction(Item, PairKinetics, LeftMolecules, RightMolecules, Reversible),
Thierry Martinez's avatar
Thierry Martinez committed
171
  (
Thierry Martinez's avatar
Thierry Martinez committed
172
    Reversible = true
Thierry Martinez's avatar
Thierry Martinez committed
173
  ->
Thierry Martinez's avatar
Thierry Martinez committed
174
    pair_kinetics(PairKinetics, ForwardKinetics, BackwardKinetics),
Thierry Martinez's avatar
Thierry Martinez committed
175 176
    (
      Kinetics = ForwardKinetics,
Thierry Martinez's avatar
Thierry Martinez committed
177 178
      Reactants = LeftMolecules,
      Products = RightMolecules
Thierry Martinez's avatar
Thierry Martinez committed
179 180
    ;
      Kinetics = BackwardKinetics,
Thierry Martinez's avatar
Thierry Martinez committed
181 182
      Reactants = RightMolecules,
      Products = LeftMolecules
Thierry Martinez's avatar
Thierry Martinez committed
183 184 185
    )
  ;
    Kinetics = PairKinetics,
Thierry Martinez's avatar
Thierry Martinez committed
186 187
    Reactants = LeftMolecules,
    Products = RightMolecules
Thierry Martinez's avatar
Thierry Martinez committed
188 189
  ).

Thierry Martinez's avatar
Thierry Martinez committed
190

Thierry Martinez's avatar
Thierry Martinez committed
191 192 193 194 195 196 197 198 199 200
pair_kinetics(PairKinetics, ForwardKinetics, BackwardKinetics) :-
  (
    PairKinetics = (ForwardKinetics, BackwardKinetics)
  ->
    true
  ;
    ForwardKinetics = PairKinetics,
    BackwardKinetics = PairKinetics
  ).

Thierry Martinez's avatar
Thierry Martinez committed
201

Thierry Martinez's avatar
Thierry Martinez committed
202 203 204 205 206
solution_to_canonical_list(Solution, List) :-
  solution_to_list(Solution, NonCanonicalList),
  canonical_solution(NonCanonicalList, List).


Thierry Martinez's avatar
Thierry Martinez committed
207
solution_to_list('_', []) :-
Thierry Martinez's avatar
Thierry Martinez committed
208 209
  !.

Thierry Martinez's avatar
Thierry Martinez committed
210
solution_to_list(A + B, Solution) :-
Thierry Martinez's avatar
Thierry Martinez committed
211
  !,
Thierry Martinez's avatar
Thierry Martinez committed
212 213
  solution_to_list(A, SolutionA),
  solution_to_list(B, SolutionB),
Thierry Martinez's avatar
Thierry Martinez committed
214 215
  append(SolutionA, SolutionB, Solution).

Thierry Martinez's avatar
Thierry Martinez committed
216
solution_to_list(Coefficient * Object, Solution) :-
Thierry Martinez's avatar
Thierry Martinez committed
217 218 219
  !,
  Solution = [Coefficient * Object].

Thierry Martinez's avatar
Thierry Martinez committed
220 221 222
solution_to_list(Object, [1 * Object]).


Thierry Martinez's avatar
Thierry Martinez committed
223 224
list_to_solution([], '_') :-
  !.
Thierry Martinez's avatar
Thierry Martinez committed
225

Thierry Martinez's avatar
Thierry Martinez committed
226 227
list_to_solution(List, Solution) :-
  reverse(List, [Head | Tail]),
Thierry Martinez's avatar
Thierry Martinez committed
228 229 230 231 232 233 234
  list_to_solution(Tail, Head, Solution).

list_to_solution([], CoefficientObject, Object) :-
  coefficient_object(CoefficientObject, Object).

list_to_solution([Head | Tail], CoefficientObject, Solution) :-
  coefficient_object(CoefficientObject, Object),
Thierry Martinez's avatar
Thierry Martinez committed
235
  Solution = SolutionTail + Object,
Thierry Martinez's avatar
Thierry Martinez committed
236 237 238 239 240 241
  list_to_solution(Tail, Head, SolutionTail).


coefficient_object(1 * Object, Object) :-
  !.

Thierry Martinez's avatar
Thierry Martinez committed
242 243 244
coefficient_object(1.0 * Object, Object) :-
  !.

Thierry Martinez's avatar
Thierry Martinez committed
245 246 247
coefficient_object(CoefficientObject, CoefficientObject).


Thierry Martinez's avatar
Thierry Martinez committed
248 249
simplify_reaction(Reaction, SimplifiedReaction) :-
  reaction(Reaction, Kinetics, LeftMolecules, RightMolecules, Reversible),
Thierry Martinez's avatar
Thierry Martinez committed
250 251
  make_reaction(
    Kinetics, LeftMolecules, RightMolecules, Reversible, SimplifiedReaction
Thierry Martinez's avatar
Thierry Martinez committed
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
  ).


simplify_kinetics(Kinetics, KineticsSimplified) :-
  (
    Kinetics = (LeftKinetics, RightKinetics)
  ->
    simplify(LeftKinetics, LeftKineticsSimplified),
    simplify(RightKinetics, RightKineticsSimplified),
    (
      LeftKineticsSimplified = RightKineticsSimplified
    ->
      KineticsSimplified = LeftKineticsSimplified
    ;
      KineticsSimplified = (LeftKineticsSimplified, RightKineticsSimplified)
    )
  ;
    simplify(Kinetics, KineticsSimplified)
  ).


Thierry Martinez's avatar
Thierry Martinez committed
273
simplify_solution(Solution, SimplifiedSolution) :-
Thierry Martinez's avatar
Thierry Martinez committed
274
  factorize_solution(Solution, SimplifiedSolution).
Thierry Martinez's avatar
Thierry Martinez committed
275 276 277 278 279 280 281 282 283 284 285 286


canonical_solution([], []).

canonical_solution(
  [Coefficient * Object | Tail], [Coefficient * Canonical | CanonicalTail]
) :-
  canonical(Object, Canonical),
  canonical_solution(Tail, CanonicalTail).


factorize_solution([], []).
Thierry Martinez's avatar
Thierry Martinez committed
287

Thierry Martinez's avatar
Thierry Martinez committed
288
factorize_solution([Coefficient * Object | Tail], SimplifiedSolution) :-
Thierry Martinez's avatar
Thierry Martinez committed
289 290 291 292 293 294 295 296
  collect_object(Tail, Object, TailCoefficient, Others),
  simplify(Coefficient + TailCoefficient, SimplifiedCoefficient),
  (
    SimplifiedCoefficient = 0
  ->
    simplify_solution(Others, SimplifiedCoefficient)
  ;
    SimplifiedSolution = [SimplifiedCoefficient * Object | SimplifiedTail],
Thierry Martinez's avatar
Thierry Martinez committed
297
    simplify_solution(Others, SimplifiedTail)
Thierry Martinez's avatar
Thierry Martinez committed
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
  ).


collect_object([], _Object, 0, []).

collect_object([Coefficient * Object | Tail], Object, Sum, Others) :-
  !,
  Sum = Coefficient + TailCoefficient,
  collect_object(Tail, Object, TailCoefficient, Others).

collect_object([CoefficientObject | Tail], Object, Sum, Others) :-
  Others = [CoefficientObject | OthersTail],
  collect_object(Tail, Object, Sum, OthersTail).


Thierry Martinez's avatar
Thierry Martinez committed
313
simplify_catalyst([], Right, [], [], Right).
Thierry Martinez's avatar
Thierry Martinez committed
314 315 316 317 318 319

simplify_catalyst([Head | Tail], Right, NewLeft, Catalyst, NewRight) :-
  (
    select(Head, Right, OthersRight)
  ->
    Catalyst = [Head | CatalystTail],
Thierry Martinez's avatar
Thierry Martinez committed
320 321 322 323 324
    simplify_catalyst(Tail, OthersRight, NewLeft, CatalystTail, NewRight)
  ;
    NewLeft = [Head | LeftTail],
    simplify_catalyst(Tail, Right, LeftTail, Catalyst, NewRight)
  ).
Thierry Martinez's avatar
Thierry Martinez committed
325 326


Thierry Martinez's avatar
Thierry Martinez committed
327 328 329 330 331
make_reaction(Kinetics, LeftMolecules, RightMolecules, Reversible, Reaction) :-
  simplify_kinetics(Kinetics, KineticsSimplified),
  simplify_solution(LeftMolecules, LeftSimplified),
  simplify_solution(RightMolecules, RightSimplified),
  simplify_catalyst(LeftSimplified, RightSimplified, Left, Catalyst, Right),
Thierry Martinez's avatar
ode  
Thierry Martinez committed
332 333 334 335 336 337 338 339
  (
    append(Left, Catalyst, Reactants),
    kinetics(Reactants, 'MA'(1), KineticsSimplified)
  ->
    KineticsSimplifiedBis = 'MA'(1)
  ;
    KineticsSimplifiedBis = KineticsSimplified
  ),
Thierry Martinez's avatar
Thierry Martinez committed
340
  make_reaction(
Thierry Martinez's avatar
ode  
Thierry Martinez committed
341
    KineticsSimplifiedBis, Left, Catalyst, Right, Reversible, Reaction
Thierry Martinez's avatar
Thierry Martinez committed
342 343 344 345
  ).


make_reaction(Kinetics, Left, Catalyst, Right, Reversible, Reaction) :-
Thierry Martinez's avatar
Thierry Martinez committed
346 347 348
  (
    Kinetics = 'MA'(1)
  ->
Thierry Martinez's avatar
Thierry Martinez committed
349
    Reaction = Body
Thierry Martinez's avatar
Thierry Martinez committed
350
  ;
Thierry Martinez's avatar
Thierry Martinez committed
351
    Reaction = (Kinetics for Body)
Thierry Martinez's avatar
Thierry Martinez committed
352 353 354 355 356
  ),
  list_to_solution(Left, LeftSolution),
  list_to_solution(Catalyst, CatalystSolution),
  list_to_solution(Right, RightSolution),
  (
Thierry Martinez's avatar
Thierry Martinez committed
357
    Reversible = true
Thierry Martinez's avatar
Thierry Martinez committed
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
  ->
    (
      CatalystSolution = '_'
    ->
      Body = (LeftSolution <=> RightSolution)
    ;
      Body = (LeftSolution <=[ CatalystSolution ]=> RightSolution)
    )
  ;
    (
      CatalystSolution = '_'
    ->
      Body = (LeftSolution => RightSolution)
    ;
      Body = (LeftSolution =[ CatalystSolution ]=> RightSolution)
    )
  ).
Thierry Martinez's avatar
Thierry Martinez committed
375 376 377 378 379 380 381 382 383 384 385


enumerate_molecules(Molecules) :-
  setof(
    Molecule,
    enumerate_molecule(Molecule),
    Molecules
  ).


enumerate_molecule(Molecule) :-
Thierry Martinez's avatar
Thierry Martinez committed
386
  item([kind: reaction, item: Item]),
Thierry Martinez's avatar
Thierry Martinez committed
387
  reaction(Item, _Kinetics, Reactants, Products, _Reversible),
Thierry Martinez's avatar
Thierry Martinez committed
388 389 390 391 392
  (
    member(_ * Molecule, Reactants)
  ;
    member(_ * Molecule, Products)
  ).
Thierry Martinez's avatar
NuSMV  
Thierry Martinez committed
393 394

enumerate_molecule(Molecule) :-
Thierry Martinez's avatar
Thierry Martinez committed
395
  item([kind: initial_state, item: Item]),
Thierry Martinez's avatar
NuSMV  
Thierry Martinez committed
396 397 398 399 400
  (
    Item = present(Molecule)
  ;
    Item = present(Molecule, _Concentration)
  ;
401
    Item = absent(Molecule)
Thierry Martinez's avatar
NuSMV  
Thierry Martinez committed
402
  ).
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427


compute_ode_for_reaction_model :-
  \+ (
    item([kind: reaction, item: Item]),
    reaction(Item, Kinetics, Reactants, Products),
    \+ (
      kinetics(Reactants, Kinetics, KineticsExpression),
      add_molecules(Reactants, -KineticsExpression),
      add_molecules(Products, KineticsExpression)
    )
  ).


add_molecules(Molecules, Kinetics) :-
  \+ (
    member(Molecule, Molecules),
    \+ (
      add_molecule(Molecule, Kinetics)
    )
  ).


add_molecule(Coefficient * Molecule, Kinetics) :-
  ode_add_expression_to_molecule(Coefficient * Kinetics, Molecule).