Skip to main content

A client library for the MIP Solver API

Project description

ReMIP Client

ReMIP Client is a Python client for the ReMIP optimization server. It lets you solve complex Mixed-Integer Programming (MIP) problems using a remote, high-performance solver, and it's compatible with the popular PuLP modeling library.

You can use this client in standard Python scripts, in a web browser, or in a Node.js application.

Key Features

  • PuLP Compatible: Integrates seamlessly with your existing PuLP models.
  • Remote Solving: Offload heavy optimization tasks to a powerful remote server. No local solver installation is needed.
  • Cross-Environment: Run the same optimization code in Python, a browser (with Pyodide), or Node.js.
  • Real-time Monitoring: Use streaming mode to get live updates on the solver's progress.

Prerequisites

The ReMIP server must be running for the client to work. The examples below assume the server is running and accessible at http://localhost:8000.

For instructions on how to run the server, please see the documentation in the remip/ directory.

Installation

For a Standard Python (CPython) Project

# Navigate to the remip-client directory
cd remip-client

# Install the client and its dependencies
uv pip install -e .

For Browser or Node.js (Pyodide)

When using the client with Pyodide, you first need to build and serve the client's .whl file. Pyodide installs packages from URLs.

# 1. Navigate to the remip-client directory
cd remip-client

# 2. Build the wheel file
uv run python -m build --wheel
# This creates a file like `dist/remip_client-0.1.0-py3-none-any.whl`

# 3. Start a local server to provide this file to Pyodide
python -m http.server 8888
# Now the wheel is available at http://localhost:8888/dist/remip_client-0.1.0-py3-none-any.whl

Usage Examples

Example 1: Standard Python Environment

This is the most common use case. The client integrates directly with PuLP's synchronous solve() method.

Note: Ensure the ReMIP server is running before executing this code.

from pulp import LpProblem, LpVariable, LpMaximize, LpStatus
from remip_client.solver import ReMIPSolver

# 1. Define a PuLP problem
prob = LpProblem("simple_test", LpMaximize)
x = LpVariable("x", 0, 1, cat='Binary')
y = LpVariable("y", 0, 1, cat='Binary')
prob += x + y, "objective"
prob += 2*x + y <= 2, "constraint1"

# 2. Initialize the remote solver
solver = ReMIPSolver(url="http://localhost:8000", stream=False)

# 3. Solve the problem using PuLP's standard method
prob.solve(solver)

# 4. Print the results
print(f"Status: {LpStatus[prob.status]}")
for v in prob.variables():
    print(f"{v.name} = {v.varValue}")

Example 2: In a Web Browser with Pyodide

This example creates a self-contained HTML file that runs a ReMIP optimization problem in the browser.

Note: Ensure the ReMIP server is running. You must also serve this HTML file and the dist directory from a local web server (e.g., by running python -m http.server 8888 in the remip-client directory).

<!-- index.html -->
<html>
  <head>
    <title>ReMIP Client - Browser Demo</title>
    <meta charset="UTF-8">
    <script src="https://cdn.jsdelivr.net/pyodide/v0.25.0/full/pyodide.js"></script>
    <style>
      body { font-family: sans-serif; line-height: 1.5; }
      h2, h3 { color: #333; }
      pre { background-color: #f4f4f4; padding: 1em; border-radius: 5px; white-space: pre-wrap; word-wrap: break-word; }
      #output-display { border: 1px solid #ccc; }
    </style>
  </head>
  <body>
    <h2>ReMIP Client Browser Demo</h2>
    <p>This example runs a PuLP optimization problem entirely in your browser using Pyodide and the ReMIP Client.</p>

    <h3>Python Code</h3>
    <pre id="code-display"></pre>

    <h3>Live Output</h3>
    <pre id="output-display">Loading Pyodide and setting up environment...</pre>

    <script type="text/javascript">
      const pythonCode = `
from pulp import LpProblem, LpVariable, LpMaximize, LpStatus
from remip_client.solver import ReMIPSolver

async def solve_problem():
    print("--- Defining PuLP Problem ---")
    prob = LpProblem("browser_test", LpMaximize)
    x = LpVariable("x", 0, 1, cat='Binary')
    prob += x, "objective"

    print("--- Initializing Solver ---")
    # Make sure your ReMIP server is running and accessible
    solver = ReMIPSolver(url="http://localhost:8000")

    print("--- Solving Problem (asynchronously) ---")
    await solver.solve(prob)

    print("\n--- Results ---")
    print(f"Status: {LpStatus[prob.status]}")
    print(f"Result for x: {x.varValue}")

# Return the coroutine to be awaited by JavaScript
solve_problem()
`;

      // Display the code on the page
      document.getElementById("code-display").textContent = pythonCode.trim();
      const outputElement = document.getElementById("output-display");

      function printToPage(text) {
        outputElement.textContent += text + "\n";
      }

      async function main() {
        try {
          // Load Pyodide and set up the output stream
          let pyodide = await loadPyodide({
            stdout: printToPage,
            stderr: printToPage
          });

          outputElement.textContent = "Pyodide loaded. Installing packages...\n";
          await pyodide.loadPackage("micropip");
          const micropip = pyodide.pyimport("micropip");

          // Install the ReMIP client wheel from your local server
          const wheelUrl = "http://localhost:8888/dist/remip_client-0.1.0-py3-none-any.whl";
          printToPage(`Installing wheel from ${wheelUrl}...`);
          await micropip.install(wheelUrl);
          printToPage("Installation complete.\n");

          // Run the main Python code
          await pyodide.runPythonAsync(pythonCode);
          printToPage("\n✅ Demo finished successfully!");

        } catch (error) {
          printToPage(`\n❌ An error occurred: ${error}`);
        }
      }
      main();
    </script>
  </body>
</html>

Example 3: In a Node.js Environment with Pyodide

This example uses the client in a Node.js script.

Note: Ensure the ReMIP server is running before executing this code.

// solve.js
const { loadPyodide } = require("pyodide");
const path = require("path");
const fs = require("fs");
const http = require("http");

// --- Simple HTTP Server to serve the wheel file ---
const server = http.createServer((req, res) => {
    const filePath = path.join(__dirname, req.url);
    fs.readFile(filePath, (err, data) => {
        if (err) {
            res.writeHead(404);
            res.end(JSON.stringify(err));
            return;
        }
        res.writeHead(200);
        res.end(data);
    });
});

const PORT = 8888;

async function main() {
    server.listen(PORT, () => console.log(`Server listening on http://localhost:${PORT}`));

    try {
        console.log("Loading Pyodide in Node.js...");
        const pyodide = await loadPyodide();

        const distDir = path.join(__dirname, "dist");
        const wheelFile = fs.readdirSync(distDir).find(f => f.endsWith(".whl"));
        if (!wheelFile) throw new Error("Wheel file not found. Run 'uv run python -m build --wheel' first.");

        await pyodide.loadPackage("micropip");
        const micropip = pyodide.pyimport("micropip");

        const wheelUrl = `http://localhost:${PORT}/dist/${wheelFile}`;
        console.log(`Installing wheel from ${wheelUrl}`);
        await micropip.install(wheelUrl);

        const pythonCode = `
from pulp import LpProblem, LpVariable, LpMaximize, LpStatus
from remip_client.solver import ReMIPSolver

async def solve_problem():
    print("--- Defining PuLP Problem in Node.js ---")
    prob = LpProblem("node_js_test", LpMaximize)
    x = LpVariable("x", 0, 1, cat='Binary')
    prob += x, "objective"

    solver = ReMIPSolver(url="http://localhost:8000")

    print("--- Solving Problem (asynchronously) ---")
    await solver.solve(prob)

    print("--- Results ---")
    print(f"Status: {LpStatus[prob.status]}")
    print(f"Result for x: {x.varValue}")

# Return the coroutine to be awaited by JavaScript
solve_problem()
`;
        await pyodide.runPythonAsync(pythonCode);
    } finally {
        server.close();
    }
}

main().catch(err => {
    console.error(err);
    server.close();
    process.exit(1);
});

Solver Options

You can customize the solver's behavior when you create a ReMIPSolver instance.

  • url (str): The URL of your ReMIP server. Defaults to "http://localhost:8000".
  • stream (bool): If True, the solver requests a stream of live progress from the server. Defaults to False.
  • timeout (float): The maximum time in seconds for the solver to run. If the time limit is reached, the solver returns the best solution found so far. Defaults to 60.

License

This project is licensed under the Apache License 2.0.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

remip_client-0.3.3.tar.gz (14.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

remip_client-0.3.3-py3-none-any.whl (8.8 kB view details)

Uploaded Python 3

File details

Details for the file remip_client-0.3.3.tar.gz.

File metadata

  • Download URL: remip_client-0.3.3.tar.gz
  • Upload date:
  • Size: 14.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for remip_client-0.3.3.tar.gz
Algorithm Hash digest
SHA256 43eaef86127c44744746abc9b96356c6a31d3ee7365b1c232d5d5fbda416e897
MD5 50b2e04e473506e6b0aca26fb9459200
BLAKE2b-256 0f3384a5b745c69572a04ea64ba6bf988a041feb03d56b428c2b23532f51e1f7

See more details on using hashes here.

Provenance

The following attestation bundles were made for remip_client-0.3.3.tar.gz:

Publisher: release.yml on ohtaman/remip

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file remip_client-0.3.3-py3-none-any.whl.

File metadata

  • Download URL: remip_client-0.3.3-py3-none-any.whl
  • Upload date:
  • Size: 8.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for remip_client-0.3.3-py3-none-any.whl
Algorithm Hash digest
SHA256 091b675a6de43f1ffbea72125e6b688308cd7b63b4107ffa8bbee44d18391826
MD5 43e8abe8c1302d79b52e78dd4a2f1fc2
BLAKE2b-256 2a44a02879ebbd1826225507d2b7478235e63f59e297560f60a29d65f582cc69

See more details on using hashes here.

Provenance

The following attestation bundles were made for remip_client-0.3.3-py3-none-any.whl:

Publisher: release.yml on ohtaman/remip

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page