BYU-PRISM / GEKKO

GEKKO Python for Machine Learning and Dynamic Optimization

Home Page:https://machinelearning.byu.edu

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Feature request: web app integration

MuTsunTsai opened this issue · comments

My web app is looking for a MINLP solver, and I came across GEKKO which works perfectly for my use case when running locally. I was hoping to run GEKKO through Pyodide, but that seems impossible at this point, for:

  • Local execution requires running the APMonitor binary, which is of course not supported by Pyodide.
  • Remote execution requires socket connection, which is also not supported by Pyodide (see FAQ)

I would really love to see a solution to this. This can be done by creating a Pyodide-compatible build of GEKKO, or by directly compiling APMonitor into WebAssembly and call it from JavaScript.

Thanks for the suggestion and for highlighting the challenge for running MINLP solutions in Pyodide. The Pyodide project looks very interesting with bringing Python functionality to the web-browser. I've added this as a feature request. I'm not sure if the mixed Fortran90 / C++ code will compile into WebAssembly with cpython-emscripten, but we'll look at it.

Thanks for the link. Another way to tackle this is to set up a Flask server that can handle your MINLP request with a JavaScript version of a Gekko. Here's an example setup:

HTML + JavaScript:

This code creates a simple form in HTML to input the initial value for the variable y and sends it to the server to solve the equation (y^2 = 1) using Gekko.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Gekko Optimization via JavaScript</title>
</head>
<body>
    <h1>Simple Gekko Solver</h1>
    <form id="gekkoForm">
        <label for="initialY">Initial y value:</label>
        <input type="text" id="initialY" name="initialY" value="2">
        <button type="button" onclick="sendData()">Solve</button>
    </form>
    <div id="result"></div>

    <script>
        function sendData() {
            var initialY = document.getElementById('initialY').value;
            fetch('http://your-server-address/solve', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({initialY: initialY})
            })
            .then(response => response.json())
            .then(data => {
                document.getElementById('result').innerText = 'Solution y: ' + data.result;
            })
            .catch((error) => {
                console.error('Error:', error);
            });
        }
    </script>
</body>
</html>

Python Server Code:

This is a simple Flask server application that receives the initial value, solves the optimization problem using Gekko, and sends back the result.

from flask import Flask, request, jsonify
from gekko import GEKKO

app = Flask(__name__)

@app.route('/solve', methods=['POST'])
def solve():
    data = request.get_json()
    initial_y = float(data['initialY'])

    m = GEKKO()            # Create GEKKO model
    y = m.Var(value=initial_y)  # Define variable, initial value from JS
    m.Equation(y**2 == 1)  # Define equation
    m.solve(disp=False)    # Solve

    return jsonify(result=y.value[0])

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

Deployment:

  • Deploy the HTML file on a web server or open it directly in a browser.
  • The Python Flask app should be deployed on a server where Python and Gekko are installed. Ensure that the server's firewall allows HTTP requests on the port you choose (default is 5000).

This setup assumes that the server hosting the Python code is accessible through http://your-server-address. Adjust the URL in the JavaScript code to match your server's actual address.

The other option is to use the public server and have your pyiodide application create a gk0_model.apm file that can be transmitted to the server for solution. That way, you wouldn't need to host your own Flask server.

@APMonitor Unfortunately, establishing such a backend is beyond the scope of my project. My main goal is to provide offline capability to my web app, so WASM solutions will be the top choices, and if I really need to do this with remote APIs, I might as well just use one from the NEOS server.