Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add python 3.12 to CI #184

Merged
merged 10 commits into from
May 3, 2024
2 changes: 1 addition & 1 deletion .github/workflows/CI.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- 3.9
- "3.10"
- "3.11"
# - "3.12"
- "3.12"
os:
- ubuntu-latest
- macos-latest
Expand Down
2 changes: 2 additions & 0 deletions doc/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ Upcoming Version

* Up to now the `rhs` argument in the `add_constraints` function was not supporting an expression as an input type. This is now added.

* Linopy now supports python 3.12.

Version 0.3.8
-------------

Expand Down
16 changes: 14 additions & 2 deletions linopy/solvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import os
import re
import subprocess as sub
import sys
from pathlib import Path

import numpy as np
Expand Down Expand Up @@ -128,7 +129,7 @@
if np.isnan(solution.objective):
return

if io_api == "mps":
if io_api == "mps" and sys.version_info < (3, 12):
logger.info(
"Adjusting objective sign due to switched coefficients in MPS file."
)
Expand Down Expand Up @@ -175,6 +176,12 @@
"Keyword argument `io_api` has to be one of `lp`, `mps' or None"
)

# CBC does not like the OBJSENSE line in MPS files, which new highspy versions write
if io_api == "mps" and model.sense == "max" and sys.version_info >= (3, 12):
raise ValueError(

Check warning on line 181 in linopy/solvers.py

View check run for this annotation

Codecov / codecov/patch

linopy/solvers.py#L181

Added line #L181 was not covered by tests
"GLPK does not support maximization in MPS format for Python 3.12+"
)

problem_fn = model.to_file(problem_fn)

# printingOptions is about what goes in solution file
Expand Down Expand Up @@ -282,6 +289,12 @@
"Keyword argument `io_api` has to be one of `lp`, `mps` or None"
)

# GLPK does not like the OBJSENSE line in MPS files, which new highspy versions write
if io_api == "mps" and model.sense == "max" and sys.version_info >= (3, 12):
raise ValueError(
"GLPK does not support maximization in MPS format for Python 3.12+"
)

problem_fn = model.to_file(problem_fn)
suffix = problem_fn.suffix[1:]

Expand Down Expand Up @@ -358,7 +371,6 @@

solution = safe_get_solution(status, get_solver_solution)
maybe_adjust_objective_sign(solution, model.objective.sense, io_api)

return Result(status, solution)


Expand Down
7 changes: 4 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@

SOLVERS = [
"gurobipy",
"highspy",
"cplex; platform_system != 'Darwin' and python_version <= '3.11'",
"highspy>=1.5.0; python_version < '3.12'",
"highspy>=1.7.1.dev1; python_version >= '3.12'",
"cplex; platform_system != 'Darwin' and python_version < '3.12'",
"mosek",
"mindoptpy",
"mindoptpy; python_version < '3.12'",
"coptpy",
"xpress; platform_system != 'Darwin' and python_version < '3.11'",
"pyscipopt; platform_system != 'Darwin'",
Expand Down
12 changes: 9 additions & 3 deletions test/test_optimization.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import logging
import platform
import sys

import numpy as np
import pandas as pd
Expand Down Expand Up @@ -384,9 +385,14 @@ def test_model_maximization(model_maximization, solver, io_api):
m = model_maximization
assert m.objective.sense == "max"
assert m.objective.value is None
status, condition = m.solve(solver, io_api=io_api)
assert status == "ok"
assert np.isclose(m.objective.value, 3.3)

if solver in ["cbc", "glpk"] and io_api == "mps" and sys.version_info >= (3, 12):
with pytest.raises(ValueError):
m.solve(solver, io_api=io_api)
else:
status, condition = m.solve(solver, io_api=io_api)
assert status == "ok"
assert np.isclose(m.objective.value, 3.3)


@pytest.mark.parametrize("solver,io_api", params)
Expand Down
Loading