Giter VIP home page Giter VIP logo

metab0t / pyoptinterface Goto Github PK

View Code? Open in Web Editor NEW
94.0 3.0 2.0 1.87 MB

Efficient modeling interface for mathematical optimization in Python

Home Page: https://metab0t.github.io/PyOptInterface/

License: Other

CMake 0.83% C++ 66.89% Python 31.34% Julia 0.92% AMPL 0.03%
conic-programs linear-programming mathematical-modelling mathematical-programming mixed-integer-programming modeling-language optimization python quadratic-programming

pyoptinterface's Introduction

PyOptInterface (Python Optimization Interface)

PyOptInterface is an open-source Python library to provide a unified API to construct and solve optimization models with various optimizers.

The detailed documentation can be found here.

Key features compared with other modeling interfaces

It is designed as a very thin wrapper of native C API of optimizers and attempts to provide common abstractions of an algebraic modelling environment including model, variable, constraint and expression with the least overhead of performance.

The key features of PyOptInterface include:

  • Very fast speed to construct optimization model (10x faster than Pyomo, comparable with JuMP.jl and some official Python bindings provided by vendors of optimizer)
  • Low overhead to modify and re-solve the problem incrementally (including adding/removing variables/constraints, changing objective function, etc.)
  • Unified API to cover common usages, write once and the code works for all optimizers
  • You still have escape hatch to query or modify solver-specific parameter/attribute/information for different optimizers directly like the vendor-specific Python binding of optimizer

Benchmark

The benchmark comparing PyOptInterface with some other modeling interfaces can be found here. PyOptInterface is among the fastest modeling interfaces in terms of model construction time.

Installation

PyOptInterface is available on PyPI. You can install it via pip:

pip install pyoptinterface

After installation, you can import the package in Python console:

import pyoptinterface as poi

PyOptInterface has no dependencies other than Python itself. However, to use it with a specific optimizer, you need to install the corresponding optimizer manually. The details can be found on the configurations of optimizers.

In order to provide out-of-the-box support for open source optimizers (currently we support HiGHS), PyOptInterface can also be installed with pre-built optimizers. You can install them via pip:

pip install pyoptinterface[highs]

It will install a full-featured binary version of HiGHS optimizer via highsbox, which can be used with PyOptInterface.

What kind of problems can PyOptInterface solve?

It currently supports the following problem types:

  • Linear Programming (LP)
  • Mixed-Integer Linear Programming (MILP)
  • Quadratic Programming (QP)
  • Mixed-Integer Quadratic Programming (MIQP)
  • Quadratically Constrained Quadratic Programming (QCQP)
  • Mixed-Integer Quadratically Constrained Quadratic Programming (MIQCQP)
  • Second-Order Cone Programming (SOCP)
  • Mixed-Integer Second-Order Cone Programming (MISOCP)

What optimizers does PyOptInterface support?

It currently supports the following optimizers:

Short Example

import pyoptinterface as poi
from pyoptinterface import highs

model = highs.Model()

x = model.add_variable(lb=0, ub=1, domain=poi.VariableDomain.Continuous, name="x")
y = model.add_variable(lb=0, ub=1, domain=poi.VariableDomain.Integer, name="y")

con = model.add_linear_constraint(x+y, poi.Geq, 1.2, name="con")

obj = 2*x
model.set_objective(obj, poi.ObjectiveSense.Minimize)

model.set_model_attribute(poi.ModelAttribute.Silent, False)
model.optimize()

print(model.get_model_attribute(poi.ModelAttribute.TerminationStatus))
# TerminationStatusCode.OPTIMAL

x_val = model.get_value(x)
# 0.2

y_val = model.get_value(y)
# 1.0

License

PyOptInterface is licensed under MPL-2.0 License.

It uses nanobind, fmtlib and martinus/unordered_dense as dependencies.

The design of PyOptInterface is inspired by JuMP.jl.

Some solver-related code in src folder is adapted from the corresponding solver interface package in JuMP.jl ecosystem, which is licensed under MIT License.

The header files in thirdparty/solvers directory are from the corresponding distribution of optimizers and are licensed under their own licenses.

pyoptinterface's People

Contributors

metab0t avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

pyoptinterface's Issues

Advice re performance

Hey, nice library! I'm having a play with it to see how it performs with a very simple model with varying numbers of variables.

With the script below I'm getting these results

100 vars:	2.49 ms
1000 vars:	9.67 ms
10000 vars:	717.49 ms
20000 vars:	2794.24 ms
50000 vars:	17723.34 ms

It's looking like the runtime is very non-linear. The same problem in other similar solvers tends to increase quite linearly.
Profiling this via kernprof -l -v example.py (pip install line_profiler first and decorate run with @profile) I see that the bulk of the time seems to be spent in the optimisation:

Timer unit: 1e-06 s

Total time: 20.9067 s
File: example.py
Function: run at line 6

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     6                                           @profile
     7                                           def run(n_vars: int):
     8         5          2.0      0.4      0.0      t1 = time.perf_counter()
     9         5        604.0    120.8      0.0      model = highs.Model()
    10         5        184.0     36.8      0.0      model.set_raw_parameter("log_to_console", False)
    11         5          6.0      1.2      0.0      model.set_raw_parameter("output_flag", False)
    12                                           
    13         5     129217.0  25843.4      0.6      x = model.add_variables(list(range(n_vars)), lb=0.0, ub=1.0)
    14         5      10588.0   2117.6      0.1      model.add_linear_constraint(poi.quicksum(x), poi.Eq, 1.0)
    15         5      31477.0   6295.4      0.2      objective = poi.quicksum([i * x[i] for i in range(n_vars)])
    16         5       1035.0    207.0      0.0      model.set_objective(objective, poi.ObjectiveSense.Maximize)
    17         5   20733173.0 4146634.6     99.2      model.optimize()
    18                                           
    19         5        276.0     55.2      0.0      assert math.isclose(model.get_value(objective), n_vars - 1)
    20         5          6.0      1.2      0.0      t2 = time.perf_counter()
    21         5        123.0     24.6      0.0      print(f"{n_vars} vars:\t{(t2 - t1) * 1000:.2f} ms")

Do you have any advice on whether there's any change I could make to my code to improve it?

import math
import time
import pyoptinterface as poi
from pyoptinterface import highs


def run(n_vars: int):
    t1 = time.perf_counter()
    model = highs.Model()
    model.set_raw_parameter("log_to_console", False)
    model.set_raw_parameter("output_flag", False)

    x = model.add_variables(list(range(n_vars)), lb=0.0, ub=1.0)
    model.add_linear_constraint(poi.quicksum(x), poi.Eq, 1.0)
    objective = poi.quicksum([i * x[i] for i in range(n_vars)])
    model.set_objective(objective, poi.ObjectiveSense.Maximize)
    model.optimize()

    assert math.isclose(model.get_value(objective), n_vars - 1)
    t2 = time.perf_counter()
    print(f"{n_vars} vars:\t{(t2 - t1) * 1000:.2f} ms")


for n_vars_ in (100, 1_000, 10_000, 20_000, 50_000):
    run(n_vars_)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.