Streamlit cloud with Pyomo and IPOPT

Hi there,

I try to create a simple Streamlit application for some people in our team that do not know how to code. In their work, they would need to solve an optimization problem, where they only need to change some parameters from time to time (the problem structure stays the same). The problem structure is nonlinear, so in a first step, I try to use IPOPT as an open-source solver.

A simple example script is pasted below. The code runs on a local machine with GLPK (for the equivalent linear problem) or IPOPT (if there is that squared part in the objective function as shown below). However, when I try to deploy the app on Streamlit cloud, the following error pops up (for linear problems with GLPK it works after following these inputs: Using PYOMO + GLPK on Streamlit Share - #3 by Tianoklein1):

File "/home/adminuser/venv/lib/python3.9/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 534, in _run_script
    exec(code, module.__dict__)
File "/mount/src/streamlit_optimization/streamlit_app.py", line 98, in <module>
    solver.solve(model)
File "/home/adminuser/venv/lib/python3.9/site-packages/pyomo/opt/base/solvers.py", line 533, in solve
    self.available(exception_flag=True)
File "/home/adminuser/venv/lib/python3.9/site-packages/pyomo/opt/solver/shellcmd.py", line 141, in available
    raise ApplicationError(msg % self.name)

And the console output reads as follows:

WARNING: Could not locate the 'ipopt' executable, which is required for solver ipopt

2023-12-28 09:01:26.848 Uncaught app exception
Traceback (most recent call last):
  File "/home/adminuser/venv/lib/python3.9/site packages/streamlit/runtime/scriptrunner/script_runner.py", line 534, in _run_script exec(code, module.__dict__)
  File "/mount/src/streamlit_optimization/streamlit_app.py", line 98, in <module>
    solver.solve(model)
  File "/home/adminuser/venv/lib/python3.9/site packages/pyomo/opt/base/solvers.py", line 533, in solve
    self.available(exception_flag=True)
  File "/home/adminuser/venv/lib/python3.9/site-packages/pyomo/opt/solver/shellcmd.py", line 141, in available
    raise ApplicationError(msg % self.name)
pyomo.common.errors.ApplicationError: No executable found for solver 'ipopt'

Where basically the outputs of Streamlit tell me that โ€œipopt is not foundโ€. I tried installing it by including coinor-libipopt-dev in the packages.txt file and the following line in the .devcontainer/devcontainer.json file

"updateContentCommand": "[ -f packages.txt ] && sudo apt update && sudo apt upgrade && sudo xargs apt install -y <packages.txt && sudo apt-get install -y coinor-libipopt-dev && pip3 install --user -r requirements.txt"

So my question is now, how do I find out the path on the cloud so that pyomo knows where to look for IPOPT? Additionally, is the installation procedure correct (it is the first time I try that out :slight_smile:)

Thanks for your help and sorry for the long topic!

Script:

import streamlit as st
import pyomo.environ as pyo

# STREAMLIT INPUTS
####################################################################
st.title("Choose properties")

# Slider for coefficients of objective function
obj_coef_c1 = st.slider(r"Choose objective function coefficient $c_1$:", 
                     min_value=1.0, max_value=12.0, value=2.0, step=0.1)
obj_coef_c2 = st.slider(r"Choose objective function coefficient $c_2$:", 
                     min_value=1.0, max_value=12.0, value=3.0, step=0.1)

# Slider for coefficients of constraint function
constr_coef_a1 = st.slider(r"Choose constraint function coefficient $a_1$:", 
                     min_value=1.0, max_value=12.0, value=3.0, step=0.1)
constr_coef_a2 = st.slider(r"Choose constraint function coefficient $a_2$:", 
                     min_value=1.0, max_value=12.0, value=4.0, step=0.1)

# Slider for b value of constraint function
constr_coef_b = st.slider(r"Choose constraint value $b$:", 
                     min_value=0.0, max_value=5.0, value=1.0, step=0.1)


# PYOMO MODEL
####################################################################
# Create a concrete model
model = pyo.ConcreteModel()

# Create variables, objective function and constraints
model.decisionvariable = pyo.Var([1,2], domain=pyo.NonNegativeReals)
model.obj = pyo.Objective(expr = obj_coef_c1*model.decisionvariable[1]**2 + obj_coef_c2*model.decisionvariable[2])
model.Constraint1 = pyo.Constraint(expr = constr_coef_a1*model.decisionvariable[1] + constr_coef_a2*model.decisionvariable[2] >= constr_coef_b)

# Choose solver and solve model
solver = pyo.SolverFactory('ipopt')
solver.solve(model) 


# STREAMLIT OUTPUTS
####################################################################
st.title("Optimal solution")

st.header("Decision variables")
st.write(model.decisionvariable[1]())
st.write(model.decisionvariable[2]())

st.header("Objective function")
st.write(model.obj())