"""
## GAMSSOURCE: https://www.gams.com/latest/noalib_ml/libhtml/noalib_protein.html
## LICENSETYPE: Requires license
## MODELTYPE: NLP
Optimal production of secreted protein in a fed-batch reactor.
Park, S., Ramirez, W.F., Optimal production of secreted protein in fed-batch
reactors. A.I.Ch.E. Journal, 34, 1988, pp.1550-1558.
"""
from __future__ import annotations
import os
import gamspy.math as gams_math
from gamspy import (
Alias,
Container,
Equation,
Model,
Options,
Parameter,
Set,
Variable,
)
def main():
m = Container(
system_directory=os.getenv("SYSTEM_DIRECTORY", None),
)
n = 500
# SET #
nh = Set(
m,
name="nh",
records=[str(i) for i in range(n + 1)],
description="Number of subintervals",
)
# ALIAS #
k = Alias(m, name="k", alias_with=nh)
# SCALARS #
tf = Parameter(m, name="tf", records=10, description="final time")
x1_0 = Parameter(
m, name="x1_0", records=1, description="initial value for x1"
)
x2_0 = Parameter(
m, name="x2_0", records=5, description="initial value for x2"
)
x3_0 = Parameter(
m, name="x3_0", records=0, description="initial value for x3"
)
x4_0 = Parameter(
m, name="x4_0", records=0, description="initial value for x4"
)
x5_0 = Parameter(
m, name="x5_0", records=1, description="initial value for x5"
)
h = Parameter(m, name="h")
h[...] = tf / n
# VARIABLES #
x1 = Variable(m, name="x1", domain=nh)
x2 = Variable(m, name="x2", domain=nh)
x3 = Variable(m, name="x3", domain=nh)
x4 = Variable(m, name="x4", domain=nh)
x5 = Variable(m, name="x5", domain=nh)
u = Variable(m, name="u", domain=nh, description="control variable")
a1 = Variable(m, name="a1", domain=nh)
a2 = Variable(m, name="a2", domain=nh)
a3 = Variable(m, name="a3", domain=nh)
# EQUATIONS #
state1 = Equation(
m,
name="state1",
type="regular",
domain=nh,
description="state equation 1",
)
state2 = Equation(
m,
name="state2",
type="regular",
domain=nh,
description="state equation 2",
)
state3 = Equation(
m,
name="state3",
type="regular",
domain=nh,
description="state equation 3",
)
state4 = Equation(
m,
name="state4",
type="regular",
domain=nh,
description="state equation 4",
)
state5 = Equation(
m,
name="state5",
type="regular",
domain=nh,
description="state equation 5",
)
ea1 = Equation(m, name="ea1", type="regular", domain=nh)
ea2 = Equation(m, name="ea2", type="regular", domain=nh)
ea3 = Equation(m, name="ea3", type="regular", domain=nh)
eobj = x4[str(n)] * x5[str(n)] # Objective function
state1[nh[k.lead(1)]] = x1[k.lead(1)] == (
x1[k]
+ (h / 2)
* (
a1[k] * x1[k]
- u[k] * x1[k] / x5[k]
+ a1[k.lead(1)] * x1[k.lead(1)]
- u[k.lead(1)] * x1[k.lead(1)] / x5[k.lead(1)]
)
)
state2[nh[k.lead(1)]] = x2[k.lead(1)] == (
x2[k]
+ (h / 2)
* (
-7.3 * a1[k] * x1[k]
- u[k] * (x2[k] - 20) / x5[k]
- 7.3 * a1[k.lead(1)] * x1[k.lead(1)]
- u[k.lead(1)] * (x2[k.lead(1)] - 20) / x5[k.lead(1)]
)
)
state3[nh[k.lead(1)]] = x3[k.lead(1)] == (
x3[k]
+ (h / 2)
* (
a2[k] * x1[k]
- u[k] * x3[k] / x5[k]
+ a2[k.lead(1)] * x1[k.lead(1)]
- u[k.lead(1)] * x3[k.lead(1)] / x5[k.lead(1)]
)
)
state4[nh[k.lead(1)]] = x4[k.lead(1)] == (
x4[k]
+ (h / 2)
* (
a3[k] * (x3[k] - x4[k])
- u[k] * x4[k] / x5[k]
+ a3[k.lead(1)] * (x3[k.lead(1)] - x4[k.lead(1)])
- u[k.lead(1)] * x4[k.lead(1)] / x5[k.lead(1)]
)
)
state5[nh[k.lead(1)]] = x5[k.lead(1)] == x5[k] + (h / 2) * (
u[k] + u[k.lead(1)]
)
ea1[nh[k]] = a1[k] == 21.87 * x2[k] / ((x2[k] + 0.4) * (x2[k] + 62.5))
ea2[nh[k]] = a2[k] == (x2[k] * gams_math.exp(-5 * x2[k])) / (0.1 + x2[k])
ea3[nh[k]] = a3[k] == 4.75 * a1[k] / (0.12 + a1[k])
# Initial point
x1.l[nh] = 1.0
x2.l[nh] = 5.0
x3.l[nh] = 0.0
x4.l[nh] = 0.0
x5.l[nh] = 1.0
u.l[nh] = 0.0
x1.fx["0"] = x1_0
x2.fx["0"] = x2_0
x3.fx["0"] = x3_0
x4.fx["0"] = x4_0
x5.fx["0"] = x5_0
# Bounds
u.lo[nh] = 0.0
u.up[nh] = 5
protein = Model(
m,
name="protein",
equations=m.getEquations(),
problem="nlp",
sense="max",
objective=eobj,
)
protein.solve(options=Options(time_limit=60000, iteration_limit=80000))
print(
"Objective Function Value: ", round(protein.objective_value, 4), "\n"
)
# REPORTING PARAMETER #
rep = Parameter(m, name="rep", domain=[nh, "*"])
rep[nh, "x1"] = x1.l[nh]
rep[nh, "x2"] = x2.l[nh]
rep[nh, "x3"] = x3.l[nh]
rep[nh, "x4"] = x4.l[nh]
rep[nh, "x5"] = x5.l[nh]
rep[nh, "u"] = u.l[nh]
rep.pivot().round(3).to_csv("protein_report.csv")
# End of protein
if __name__ == "__main__":
main()