-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcosa_add_promiscuity_constraints.py
143 lines (118 loc) · 5.65 KB
/
cosa_add_promiscuity_constraints.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
"""Contains function for adding promiscuity constraints."""
# IMPORTS #
# External
import cobra
import copy
import pulp
from typing import Any, Dict
# PUBLIC FUNCTIONS #
def cosa_add_promiscuity_constraints(
optmdfpathway_base_problem: pulp.LpProblem, optmdfpathway_base_variables: Dict[Any, Any],
cobra_model: cobra.Model, dG0_values: Dict[Any, Any]) -> pulp.LpProblem:
"""This function adds the TCOSA promiscuity constraints to the pulp problem.
The promuscuity constraints ensure that out of all generated forward and reverse
and TCOSA reactions, only one of the descendants of an original iML1515 reaction
can be active at the same time.
Args:
optmdfpathway_base_problem (pulp.LpProblem): The pulp problem.
optmdfpathway_base_variables (Dict[Any, Any]): The pulp problem's base variables dict.
cobra_model (cobra.Model): The cobra model on which the pulp problem is based upon.
dG0_values (Dict[Any, Any]): The used dG0 values.
Returns:
pulp.LpProblem: The pulp problem enhanced by the promiscuity constraints.
"""
for reaction in cobra_model.reactions:
key = reaction.id
if key not in dG0_values.keys():
continue
newkeys = [key]
if "_FWD" in key:
newkeys.append(key.replace("_FWD", "_REV"))
elif "_REV" in key:
newkeys.append(key.replace("_REV", "_FWD"))
if "_ORIGINAL_NAD_" in key:
for newkey in copy.deepcopy(newkeys):
newkeys.append(newkey.replace("_ORIGINAL_NAD_", "_VARIANT_NADP_"))
elif "_ORIGINAL_NADP_" in key:
for newkey in copy.deepcopy(newkeys):
newkeys.append(newkey.replace("_ORIGINAL_NADP_", "_VARIANT_NAD_"))
elif "_VARIANT_NAD_" in key:
for newkey in copy.deepcopy(newkeys):
newkeys.append(newkey.replace("_VARIANT_NAD_", "_ORIGINAL_NADP_"))
elif "_VARIANT_NADP_" in key:
for newkey in copy.deepcopy(newkeys):
newkeys.append(newkey.replace("_VARIANT_NADP_", "_ORIGINAL_NAD_"))
#####
if len(newkeys) <= 1:
continue
current_z_cluster_sum: pulp.LpAffineExpression = 0.0
for newkey in newkeys:
current_z_variable = optmdfpathway_base_variables[f"z_var_{newkey}"]
current_z_cluster_sum += current_z_variable
var_current_z_cluster_sum = pulp.LpVariable(
name=f"var_z_cluster_sum_{newkeys[0]}",
lowBound=0.0,
upBound=1.0,
cat=pulp.LpContinuous,
)
optmdfpathway_base_problem += current_z_cluster_sum - var_current_z_cluster_sum == 0
optmdfpathway_base_problem += var_current_z_cluster_sum <= 1
return optmdfpathway_base_problem
def cosa_add_stoichiometric_promiscuity_constraints(
optmdfpathway_base_problem: pulp.LpProblem, optmdfpathway_base_variables: Dict[Any, Any],
cobra_model: cobra.Model, dG0_values: Dict[Any, Any]) -> pulp.LpProblem:
"""This function adds the TCOSA promiscuity constraints to the pulp problem in the case that no thermodynamic constraints are used.
The promuscuity constraints ensure that out of all generated forward and reverse
and TCOSA reactions, only one of the descendants of an original iML1515 reaction
can be active at the same time.
Args:
optmdfpathway_base_problem (pulp.LpProblem): The pulp problem.
optmdfpathway_base_variables (Dict[Any, Any]): The pulp problem's base variables dict.
cobra_model (cobra.Model): The cobra model on which the pulp problem is based upon.
dG0_values (Dict[Any, Any]): The used dG0 values.
Returns:
pulp.LpProblem: The pulp problem enhanced by the promiscuity constraints.
"""
current_cluster = 0
for reaction in cobra_model.reactions:
key = reaction.id
newkeys = [key]
if "_FWD" in key:
newkeys.append(key.replace("_FWD", "_REV"))
elif "_REV" in key:
newkeys.append(key.replace("_REV", "_FWD"))
if "_ORIGINAL_NAD_" in key:
for newkey in copy.deepcopy(newkeys):
newkeys.append(newkey.replace("_ORIGINAL_NAD_", "_VARIANT_NADP_"))
elif "_ORIGINAL_NADP_" in key:
for newkey in copy.deepcopy(newkeys):
newkeys.append(newkey.replace("_ORIGINAL_NADP_", "_VARIANT_NAD_"))
elif "_VARIANT_NAD_" in key:
for newkey in copy.deepcopy(newkeys):
newkeys.append(newkey.replace("_VARIANT_NAD_", "_ORIGINAL_NADP_"))
elif "_VARIANT_NADP_" in key:
for newkey in copy.deepcopy(newkeys):
newkeys.append(newkey.replace("_VARIANT_NADP_", "_ORIGINAL_NAD_"))
#####
if len(newkeys) <= 1:
continue
current_cluster += 1
current_z_cluster_sum: pulp.LpAffineExpression = 0.0
for newkey in newkeys:
new_z_cluster_variable = pulp.LpVariable(
name=f"var_z_cluster_var_{newkey}_{current_cluster}",
lowBound=0.0,
upBound=1.0,
cat=pulp.LpBinary,
)
optmdfpathway_base_problem += optmdfpathway_base_variables[newkey] <= 1_500 * new_z_cluster_variable
current_z_cluster_sum += new_z_cluster_variable
var_current_z_cluster_sum = pulp.LpVariable(
name=f"var_z_cluster_sum_{newkeys[0]}_{current_cluster}",
lowBound=0.0,
upBound=1.0,
cat=pulp.LpBinary,
)
optmdfpathway_base_problem += current_z_cluster_sum - var_current_z_cluster_sum == 0
optmdfpathway_base_problem += var_current_z_cluster_sum <= 1
return optmdfpathway_base_problem