Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
70cff2d
add knitro
eminyouskn Feb 7, 2026
d762c2f
set initial values positive to avoid numeric errors.
eminyouskn Feb 7, 2026
9f838c1
refine assertions in test_nlp_reopt for numerical stability
eminyouskn Feb 7, 2026
4cc48d6
refactor KNITRO.
eminyouskn Feb 7, 2026
b5bc164
refactor KNITRO callback handling and data structures
eminyouskn Feb 8, 2026
8de683f
Merge branch 'metab0t:master' into master
eminyouskn Feb 8, 2026
80c18b1
refine tests.
eminyouskn Feb 8, 2026
923baa8
remove start vars initialization.
eminyouskn Feb 8, 2026
65db2dc
refactor KNITRO model structures and callback.
eminyouskn Feb 8, 2026
bb92a26
clean up.
eminyouskn Feb 8, 2026
46be0f9
add doc
eminyouskn Feb 8, 2026
48363bc
clean: remove unused KNITRO API.
eminyouskn Feb 9, 2026
e119018
doc: use KNITRO 15.1
eminyouskn Feb 9, 2026
7da7b77
update model attributes getter and setter.
eminyouskn Feb 9, 2026
da95378
use sparse CppAD structures.
eminyouskn Feb 9, 2026
1ccb630
clean: remove commented-out code in CallbackEvaluator
eminyouskn Feb 9, 2026
2591433
add knitro to missing tests.
eminyouskn Feb 9, 2026
03da077
clean: remove commented-out code in CallbackEvaluator
eminyouskn Feb 10, 2026
4af2b89
remove result object
eminyouskn Feb 10, 2026
4a4d59c
clean up and refactor
eminyouskn Feb 10, 2026
c00a6fc
clean and refactor.
eminyouskn Feb 10, 2026
b362cb6
fix: negate dual value in get_constraint_dual function
eminyouskn Feb 10, 2026
d6e9b5e
test: update assertion for objective value in test_clnlbeam
eminyouskn Feb 10, 2026
2c5f0a6
clang format
eminyouskn Feb 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,25 @@ if(DEFINED ENV{XPRESSDIR})
target_include_directories(xpress_model_ext PRIVATE $ENV{XPRESSDIR}/include)
endif()

# KNITRO
add_library(knitro_model STATIC)
target_sources(knitro_model PRIVATE
include/pyoptinterface/knitro_model.hpp
lib/knitro_model.cpp
)
target_link_libraries(knitro_model PUBLIC core cppad_interface)

nanobind_add_module(
knitro_model_ext

STABLE_ABI NB_STATIC NB_DOMAIN pyoptinterface

lib/knitro_model_ext.cpp
lib/knitro_model_ext_constants.cpp
)
target_link_libraries(knitro_model_ext PUBLIC knitro_model)
install(TARGETS knitro_model_ext LIBRARY DESTINATION ${POI_INSTALL_DIR})

# stub
nanobind_add_stub(
core_ext_stub
Expand Down Expand Up @@ -342,6 +361,13 @@ nanobind_add_stub(
OUTPUT ${POI_INSTALL_DIR}/xpress_model_ext.pyi
)

nanobind_add_stub(
knitro_model_ext_stub
INSTALL_TIME
MODULE pyoptinterface._src.knitro_model_ext
OUTPUT ${POI_INSTALL_DIR}/knitro_model_ext.pyi
)

set(ENABLE_TEST_MAIN OFF BOOL "Enable test c++ function with a main.cpp")
if(ENABLE_TEST_MAIN)
add_executable(test_main lib/main.cpp)
Expand Down
8 changes: 8 additions & 0 deletions docs/source/api/pyoptinterface.knitro.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pyoptinterface.knitro package
====================================

.. automodule:: pyoptinterface.knitro
:members:
:inherited-members:
:undoc-members:
:show-inheritance:
122 changes: 122 additions & 0 deletions docs/source/attribute/knitro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
### Supported [model attribute](#pyoptinterface.ModelAttribute)

:::{list-table}
:header-rows: 1

* - Attribute
- Get
- Set
* - Name
-
-
* - ObjectiveSense
-
-
* - DualStatus
-
-
* - PrimalStatus
-
-
* - RawStatusString
-
-
* - TerminationStatus
-
-
* - BarrierIterations
-
-
* - DualObjectiveValue
-
-
* - NodeCount
-
-
* - NumberOfThreads
-
-
* - ObjectiveBound
-
-
* - ObjectiveValue
-
-
* - RelativeGap
-
-
* - Silent
-
-
* - SimplexIterations
-
-
* - SolverName
-
-
* - SolverVersion
-
-
* - SolveTimeSec
-
-
* - TimeLimitSec
-
-
:::

### Supported [variable attribute](#pyoptinterface.VariableAttribute)

:::{list-table}
:header-rows: 1

* - Attribute
- Get
- Set
* - Value
-
-
* - LowerBound
-
-
* - UpperBound
-
-
* - Domain
-
-
* - PrimalStart
-
-
* - Name
-
-
* - IISLowerBound
-
-
* - IISUpperBound
-
-
* - ReducedCost
-
-
:::

### Supported [constraint attribute](#pyoptinterface.ConstraintAttribute)

:::{list-table}
:header-rows: 1

* - Attribute
- Get
- Set
* - Name
-
-
* - Primal
-
-
* - Dual
-
-
:::
25 changes: 21 additions & 4 deletions docs/source/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ The typical paths where the dynamic library of optimizers are located are as fol
- `/opt/gurobi1100/macos_universal2/lib`
- `/opt/gurobi1100/macos_universal2/lib`
* - Xpress
- `C:\xpressmp\bin`
- `C:\xpressmp\bin`
- `/opt/xpressmp/lib`
- `/Applications/FICO Xpress/xpressmp/lib`
- `/Applications/FICO Xpress/xpressmp/lib`
Expand All @@ -101,7 +101,11 @@ The typical paths where the dynamic library of optimizers are located are as fol
- `/opt/highs/lib`
- `/opt/highs/lib`
- `/opt/highs/lib`

* - KNITRO
- `C:\Program Files\Artelys\KNITRO 15.1\lib`
- `/opt/knitro/15.1/lib`
- `/opt/knitro/15.1/lib`
- `/opt/knitro/15.1/lib`
:::

### Gurobi
Expand Down Expand Up @@ -158,6 +162,15 @@ For Ipopt, the automatic detection looks for the following things in order:

We recommend using the official binary from [GitHub](https://github.com/coin-or/Ipopt/releases) if you work on Windows, since compiling Ipopt on Windows from source is not an easy task.

### KNITRO

The currently supported version is **15.1.x**. Other versions may work but are not tested.

For KNITRO, the automatic detection looks for the following things in order:
1. The environment variable `KNITRODIR` set by the installer of KNITRO
2. `knitro.dll`/`libknitro.so`/`libknitro.dylib` in the system loadable path
3. The installation of `knitro` PyPI package.

## Manually specifying the path of the dynamic library of optimizer

If the automatic detection fails or you want to use the optimizer in a customized location, you can manually specify the path of the dynamic library of the optimizer.
Expand Down Expand Up @@ -211,7 +224,7 @@ The typical paths where the dynamic library of optimizers are located are as fol
- `/opt/copt72/lib/libcopt.dylib`
- `/opt/copt72/lib/libcopt.dylib`
* - Xpress
- `C:\xpressmp\bin\xprs.dll`
- `C:\xpressmp\bin\xprs.dll`
- `/opt/xpressmp/lib/libxprs.so`
- `/Applications/FICO Xpress/xpressmp/lib/libxprs.dylib`
- `/Applications/FICO Xpress/xpressmp/lib/libxprs.dylib`
Expand All @@ -225,7 +238,11 @@ The typical paths where the dynamic library of optimizers are located are as fol
- `/opt/highs/lib/libhighs.so`
- `/opt/highs/lib/libhighs.dylib`
- `/opt/highs/lib/libhighs.dylib`

* - KNITRO
- `C:\Program Files\Artelys\KNITRO 15.1\lib\knitro.dll`
- `/opt/knitro/15.1/lib/libknitro.so`
- `/opt/knitro/15.1/lib/libknitro.dylib`
- `/opt/knitro/15.1/lib/libknitro.dylib`
:::

## Let's build a simple model and solve it
Expand Down
118 changes: 118 additions & 0 deletions docs/source/knitro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# KNITRO

## Initial setup

```python
from pyoptinterface import knitro

model = knitro.Model()
```

You need to follow the instructions in [Getting Started](getting_started.md#knitro) to set up the optimizer correctly.

## The capability of `knitro.Model`

### Supported constraints

:::{list-table}
:header-rows: 1
* - Constraint
- Supported
* - <project:#model.add_linear_constraint>
- ✅
* - <project:#model.add_quadratic_constraint>
- ✅
* - <project:#model.add_second_order_cone_constraint>
- ✅
* - <project:#model.add_exp_cone_constraint>
- ❌
* - <project:#model.add_sos_constraint>
- ❌
* - <project:#model.add_nl_constraint>
- ✅
:::

```{include} attribute/knitro.md
```

## Solver-specific operations

### Parameters

For [solver-specific parameters](https://www.artelys.com/app/docs/knitro/2_userGuide/knitroOptions.html), we provide `get_raw_parameter` and `set_raw_parameter` methods to get and set the parameters.

```python
model = knitro.Model()

# Set the value of a parameter by name
model.set_raw_parameter("algorithm", 1)
model.set_raw_parameter("feastol", 1e-8)
model.set_raw_parameter("opttol", 1e-8)

# Set the value of a parameter by ID (using knitro.KN constants)
model.set_raw_parameter(knitro.KN.PARAM_MAXIT, 1000)
```

We also provide `knitro.KN` to contain common constants from the KNITRO C API.

```python
# Using constants for parameter IDs
model.set_raw_parameter(knitro.KN.PARAM_FEASTOL, 1e-6)

# Algorithm selection
model.set_raw_parameter(knitro.KN.PARAM_NLP_ALGORITHM, knitro.KN.NLP_ALG_BAR_DIRECT)

# Output level
model.set_raw_parameter(knitro.KN.PARAM_OUTLEV, knitro.KN.OUTLEV_ITER)

# MIP parameters
model.set_raw_parameter(knitro.KN.PARAM_MIP_METHOD, knitro.KN.MIP_METHOD_BB)
model.set_raw_parameter(knitro.KN.PARAM_MIP_OPTGAPREL, 1e-4)
```

### Variable and Constraint Properties

Common variable and constraint properties are provided through PyOptInterface dedicated methods:

**Variable methods:**
- **Bounds**: `set_variable_lb`, `get_variable_lb`, `set_variable_ub`, `get_variable_ub`
- **Type and name**: `set_variable_name`, `get_variable_name`, `set_variable_domain`
- **Starting point**: `set_variable_start`
- **Solution values**: `get_value`, `get_variable_rc`

**Constraint methods:**
- **Name**: `set_constraint_name`, `get_constraint_name`
- **Solution values**: `get_constraint_primal`, `get_constraint_dual`

**Usage examples:**

Variable properties:
```python
# Bounds
model.set_variable_lb(variable, 0.0)
lb = model.get_variable_lb(variable)
model.set_variable_ub(variable, 10.0)
ub = model.get_variable_ub(variable)

# Type and name
model.set_variable_name(variable, "x")
name = model.get_variable_name(variable)

# Starting point
model.set_variable_start(variable, 1.0)

# Solution values
value = model.get_value(variable)
rc = model.get_variable_rc(variable)
```

Constraint properties:
```python
# Name
model.set_constraint_name(constraint, "c1")
name = model.get_constraint_name(constraint)

# Solution values
primal = model.get_constraint_primal(constraint)
dual = model.get_constraint_dual(constraint)
```
3 changes: 2 additions & 1 deletion include/pyoptinterface/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,8 @@ enum class ConstraintType
COPT_ExpCone,
COPT_NL,
IPOPT_NL,
Xpress_Nlp
Xpress_Nlp,
KNITRO_NL,
};

enum class SOSType
Expand Down
Loading