pyoframe 1.0.0a0__tar.gz → 1.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/.github/actions/setup_optimizers_linux/action.yml +29 -27
- pyoframe-1.1.0/.github/dependabot.yml +11 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/.github/workflows/ci.yml +10 -6
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/.gitignore +1 -1
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/.pre-commit-config.yaml +1 -1
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/PKG-INFO +13 -14
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/README.md +3 -3
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/.nav.yml +1 -1
- pyoframe-1.1.0/docs/contribute/index.md +65 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/examples/diet.md +3 -3
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/examples/facility_location.md +4 -4
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/index.md +1 -1
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/learn/advanced-concepts/internals.md +8 -3
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/learn/advanced-concepts/performance.md +6 -6
- pyoframe-1.1.0/docs/learn/concepts/.nav.yml +4 -0
- pyoframe-1.1.0/docs/learn/concepts/addition.md +234 -0
- pyoframe-1.1.0/docs/learn/concepts/solver-access.md +108 -0
- pyoframe-1.1.0/docs/learn/concepts/special-functions.md +12 -0
- pyoframe-1.1.0/docs/learn/get-started/.nav.yml +5 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/learn/get-started/basic-example/example-with-dimensions.md +19 -22
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/learn/get-started/basic-example/example.md +4 -4
- pyoframe-1.1.0/docs/learn/get-started/basics.md +347 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/learn/get-started/installation.md +21 -13
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/learn/get-started/power_grid_example.ipynb +2 -4
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/learn/migrate/v1.0.md +28 -9
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/overrides/main.html +5 -4
- pyoframe-1.1.0/docs/reference/.nav.yml +5 -0
- pyoframe-1.1.0/docs/reference/bases/.nav.yml +3 -0
- pyoframe-1.1.0/docs/reference/bases/BaseBlock.md +3 -0
- pyoframe-1.1.0/docs/reference/bases/BaseOperableBlock.md +3 -0
- pyoframe-1.1.0/docs/reference/index.md +28 -0
- pyoframe-1.0.0a0/docs/reference/pyoframe.Config.md → pyoframe-1.1.0/docs/reference/public/Config.md +3 -3
- pyoframe-1.1.0/docs/reference/types/.nav.yml +2 -0
- pyoframe-1.1.0/docs/reference/types/Operable.md +3 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/why-pyoframe/index.md +1 -1
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/why-pyoframe/pyoframe-performance.ipynb +5 -5
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/mkdocs.yml +2 -2
- {pyoframe-1.0.0a0/src → pyoframe-1.1.0}/pyoframe.egg-info/PKG-INFO +13 -14
- {pyoframe-1.0.0a0/src → pyoframe-1.1.0}/pyoframe.egg-info/SOURCES.txt +50 -9
- {pyoframe-1.0.0a0/src → pyoframe-1.1.0}/pyoframe.egg-info/requires.txt +7 -8
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/pyproject.toml +20 -15
- pyoframe-1.1.0/scripts/generate_api_reference.py +25 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/scripts/griffe_extensions.py +1 -1
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/src/pyoframe/__init__.py +2 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/src/pyoframe/_arithmetic.py +179 -177
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/src/pyoframe/_constants.py +103 -57
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/src/pyoframe/_core.py +308 -204
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/src/pyoframe/_model.py +49 -29
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/src/pyoframe/_model_element.py +34 -18
- pyoframe-1.1.0/src/pyoframe/_monkey_patch.py +38 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/src/pyoframe/_objective.py +4 -6
- pyoframe-1.1.0/src/pyoframe/_param.py +99 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/src/pyoframe/_utils.py +10 -11
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/src/pyoframe/_version.py +3 -3
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/README.md +1 -1
- pyoframe-1.1.0/tests/examples/cutting_stock_problem/results/problem-copt-machine.lp +89 -0
- pyoframe-1.1.0/tests/examples/cutting_stock_problem/results/problem-copt-pretty.lp +190 -0
- pyoframe-1.1.0/tests/examples/cutting_stock_problem/results/problem-highs-machine.lp +183 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/diet_problem/model.py +5 -9
- pyoframe-1.1.0/tests/examples/diet_problem/results/problem-copt-machine.lp +29 -0
- pyoframe-1.1.0/tests/examples/diet_problem/results/problem-copt-pretty.lp +36 -0
- pyoframe-1.1.0/tests/examples/diet_problem/results/problem-highs-machine.lp +21 -0
- pyoframe-1.1.0/tests/examples/diet_problem/results/solution-copt-machine.sol +11 -0
- pyoframe-1.1.0/tests/examples/diet_problem/results/solution-copt-pretty.sol +11 -0
- pyoframe-1.1.0/tests/examples/diet_problem/results/solution-highs-machine.sol +69 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/facility_location/model.py +8 -19
- pyoframe-1.1.0/tests/examples/facility_problem/results/problem-copt-machine.lp +29 -0
- pyoframe-1.1.0/tests/examples/facility_problem/results/problem-copt-pretty.lp +41 -0
- pyoframe-1.1.0/tests/examples/facility_problem/results/problem-highs-machine.lp +29 -0
- pyoframe-1.1.0/tests/examples/facility_problem/results/solution-copt-machine.sol +27 -0
- pyoframe-1.1.0/tests/examples/facility_problem/results/solution-copt-pretty.sol +27 -0
- pyoframe-1.1.0/tests/examples/facility_problem/results/solution-highs-machine.sol +50 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/portfolio_optim/model.py +32 -13
- pyoframe-1.1.0/tests/examples/portfolio_optim/results/problem-copt-machine.lp +20 -0
- pyoframe-1.1.0/tests/examples/portfolio_optim/results/problem-copt-pretty.lp +24 -0
- pyoframe-1.1.0/tests/examples/portfolio_optim/results/problem-highs-machine.lp +14 -0
- pyoframe-1.1.0/tests/examples/portfolio_optim/results/problem-highs-pretty.lp +14 -0
- pyoframe-1.1.0/tests/examples/portfolio_optim/results/solution-copt-machine.sol +7 -0
- pyoframe-1.1.0/tests/examples/portfolio_optim/results/solution-copt-pretty.sol +7 -0
- pyoframe-1.1.0/tests/examples/portfolio_optim/results/solution-highs-machine.sol +37 -0
- pyoframe-1.1.0/tests/examples/portfolio_optim/results/solution-highs-pretty.sol +37 -0
- pyoframe-1.1.0/tests/examples/production_planning/results/problem-copt-machine.lp +11 -0
- pyoframe-1.1.0/tests/examples/production_planning/results/problem-copt-pretty.lp +13 -0
- pyoframe-1.1.0/tests/examples/production_planning/results/problem-highs-machine.lp +9 -0
- pyoframe-1.1.0/tests/examples/production_planning/results/solution-copt-machine.sol +5 -0
- pyoframe-1.1.0/tests/examples/production_planning/results/solution-copt-pretty.sol +5 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/production_planning/results/solution-highs-machine.sol +10 -10
- pyoframe-1.1.0/tests/examples/pumped_storage/results/problem-copt-machine.lp +8146 -0
- pyoframe-1.1.0/tests/examples/pumped_storage/results/problem-copt-pretty.lp +20447 -0
- pyoframe-1.1.0/tests/examples/pumped_storage/results/problem-highs-machine.lp +8860 -0
- pyoframe-1.1.0/tests/examples/pumped_storage/results/solution-copt-machine.sol +4382 -0
- pyoframe-1.1.0/tests/examples/pumped_storage/results/solution-copt-pretty.sol +4382 -0
- pyoframe-1.1.0/tests/examples/pumped_storage/results/solution-highs-machine.sol +7317 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/sudoku/model.py +1 -1
- pyoframe-1.1.0/tests/examples/sudoku/results/problem-copt-machine.lp +1469 -0
- pyoframe-1.1.0/tests/examples/sudoku/results/problem-copt-pretty.lp +1513 -0
- pyoframe-1.1.0/tests/examples/sudoku/results/problem-highs-machine.lp +1813 -0
- pyoframe-1.1.0/tests/examples/sudoku/results/solution-copt-machine.sol +731 -0
- pyoframe-1.1.0/tests/examples/sudoku/results/solution-copt-pretty.sol +731 -0
- pyoframe-1.1.0/tests/examples/sudoku/results/solution-highs-machine.sol +1090 -0
- pyoframe-1.0.0a0/tests/test_arithmetic.py → pyoframe-1.1.0/tests/test_addition.py +132 -249
- pyoframe-1.1.0/tests/test_arithmetic.py +259 -0
- pyoframe-1.1.0/tests/test_constraint.py +38 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/test_examples.py +27 -9
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/test_io.py +8 -5
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/test_model.py +7 -9
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/test_names.py +3 -3
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/test_objective.py +0 -4
- pyoframe-1.1.0/tests/test_param.py +29 -0
- pyoframe-1.1.0/tests/test_variable.py +78 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/util.py +5 -2
- pyoframe-1.0.0a0/docs/contribute/index.md +0 -51
- pyoframe-1.0.0a0/docs/learn/concepts/.nav.yml +0 -4
- pyoframe-1.0.0a0/docs/learn/concepts/building-blocks.md +0 -17
- pyoframe-1.0.0a0/docs/learn/concepts/solver-access.md +0 -43
- pyoframe-1.0.0a0/docs/learn/concepts/special-functions.md +0 -227
- pyoframe-1.0.0a0/docs/learn/get-started/.nav.yml +0 -4
- pyoframe-1.0.0a0/docs/reference/index.md +0 -7
- pyoframe-1.0.0a0/docs/reference/pandas.DataFrame.to_expr.md +0 -3
- pyoframe-1.0.0a0/docs/reference/polars.DataFrame.to_expr.md +0 -3
- pyoframe-1.0.0a0/scripts/generate_api_reference.py +0 -34
- pyoframe-1.0.0a0/src/pyoframe/_monkey_patch.py +0 -80
- pyoframe-1.0.0a0/tests/examples/cutting_stock_problem/results/problem-highs-machine.lp +0 -183
- pyoframe-1.0.0a0/tests/examples/diet_problem/results/problem-highs-machine.lp +0 -21
- pyoframe-1.0.0a0/tests/examples/diet_problem/results/solution-highs-machine.sol +0 -69
- pyoframe-1.0.0a0/tests/examples/facility_problem/results/problem-highs-machine.lp +0 -29
- pyoframe-1.0.0a0/tests/examples/facility_problem/results/solution-highs-machine.sol +0 -50
- pyoframe-1.0.0a0/tests/examples/production_planning/results/problem-highs-machine.lp +0 -9
- pyoframe-1.0.0a0/tests/examples/pumped_storage/results/problem-highs-machine.lp +0 -8876
- pyoframe-1.0.0a0/tests/examples/pumped_storage/results/solution-highs-machine.sol +0 -7317
- pyoframe-1.0.0a0/tests/examples/sudoku/results/problem-highs-machine.lp +0 -1813
- pyoframe-1.0.0a0/tests/examples/sudoku/results/solution-highs-machine.sol +0 -1090
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/.gitattributes +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/.github/CODEOWNERS +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/.github/actions/setup_optimizers_macos/action.yml +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/.github/actions/setup_optimizers_windows/action.yml +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/.github/workflows/format.yml +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/.github/workflows/lines_changed_counter.yml +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/.github/workflows/lint.yml +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/.github/workflows/publish_doc.yml +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/.github/workflows/publish_doc_dev.yml +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/.github/workflows/publish_to_pypi.yml +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/.github/workflows/test_doc.yml +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/.vscode/launch.json +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/.vscode/settings.json +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/CHANGELOG.md +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/LICENSE +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/conftest.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/examples/.nav.yml +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/examples/index.md +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/examples/portfolio_optimization.md +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/examples/production.md +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/javascripts/feedback.js +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/learn/advanced-concepts/.nav.yml +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/learn/advanced-concepts/datastructure.md +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/learn/advanced-concepts/quadratics.md +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/learn/advanced-concepts/troubleshooting.md +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/learn/get-started/basic-example/food_data.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/learn/get-started/basic-example/foods.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/learn/get-started/basic-example/foods_to_nutrients.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/learn/get-started/basic-example/nutrients.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/learn/get-started/basic-example/results.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/learn/get-started/three-bus.png +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/overrides/partials/actions.html +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/overrides/partials/comments.html +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/overrides/partials/integrations/analytics/custom.html +0 -0
- {pyoframe-1.0.0a0/docs/reference → pyoframe-1.1.0/docs/reference/public}/.nav.yml +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/stylesheets/extra.css +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/why-pyoframe/data_py.parquet +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/why-pyoframe/gen_py.parquet +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/docs/why-pyoframe/three-bus-four-gen.png +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/giscus.json +0 -0
- {pyoframe-1.0.0a0/src → pyoframe-1.1.0}/pyoframe.egg-info/dependency_links.txt +0 -0
- {pyoframe-1.0.0a0/src → pyoframe-1.1.0}/pyoframe.egg-info/top_level.txt +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/scripts/archive/benchmark_assign_ids_constraints.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/scripts/archive/benchmark_assign_ids_constraints_2.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/scripts/archive/benchmark_assign_ids_variables.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/scripts/archive/benchmark_attr_performance.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/setup.cfg +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/__init__.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/conftest.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/__init__.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/cutting_stock_problem/__init__.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/cutting_stock_problem/input_data/orders.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/cutting_stock_problem/input_data/parameters.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/cutting_stock_problem/model.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/cutting_stock_problem/results/objective.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/cutting_stock_problem/results/problem-gurobi-machine.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/cutting_stock_problem/results/problem-gurobi-pretty.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/cutting_stock_problem/results/problem-highs-pretty.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/diet_problem/README.md +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/diet_problem/__init__.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/diet_problem/input_data/foods.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/diet_problem/input_data/foods_to_nutrients.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/diet_problem/input_data/nutrients.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/diet_problem/model_gurobipy.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/diet_problem/results/Buy.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/diet_problem/results/Buy_ub.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/diet_problem/results/max_nutrients.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/diet_problem/results/min_nutrients.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/diet_problem/results/objective.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/diet_problem/results/problem-gurobi-machine.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/diet_problem/results/problem-gurobi-pretty.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/diet_problem/results/problem-highs-pretty.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/diet_problem/results/solution-gurobi-machine.sol +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/diet_problem/results/solution-gurobi-pretty.sol +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/diet_problem/results/solution-highs-pretty.sol +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/facility_location/__init__.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/facility_location/results/objective.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/facility_location/results/problem-gurobi-machine.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/facility_location/results/problem-gurobi-pretty.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/facility_problem/__init__.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/facility_problem/input_data/plants.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/facility_problem/input_data/transport_costs.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/facility_problem/input_data/wharehouses.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/facility_problem/model.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/facility_problem/model_gurobipy.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/facility_problem/results/objective.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/facility_problem/results/open.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/facility_problem/results/problem-gurobi-machine.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/facility_problem/results/problem-gurobi-pretty.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/facility_problem/results/problem-highs-pretty.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/facility_problem/results/solution-gurobi-machine.sol +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/facility_problem/results/solution-gurobi-pretty.sol +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/facility_problem/results/solution-highs-pretty.sol +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/facility_problem/results/transport.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/portfolio_optim/input_data/assets.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/portfolio_optim/input_data/covariance.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/portfolio_optim/input_data/portfolio_params.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/portfolio_optim/results/con_min_return.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/portfolio_optim/results/con_weights_sum.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/portfolio_optim/results/objective.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/portfolio_optim/results/problem-gurobi-machine.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/portfolio_optim/results/problem-gurobi-pretty.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/portfolio_optim/results/solution-gurobi-machine.sol +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/portfolio_optim/results/solution-gurobi-pretty.sol +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/portfolio_optim/results/weight.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/production_planning/__init__.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/production_planning/input_data/machines_availability.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/production_planning/input_data/processing_times.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/production_planning/input_data/products_profit.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/production_planning/model.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/production_planning/results/objective.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/production_planning/results/problem-gurobi-machine.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/production_planning/results/problem-gurobi-pretty.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/production_planning/results/problem-highs-pretty.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/production_planning/results/solution-gurobi-machine.sol +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/production_planning/results/solution-gurobi-pretty.sol +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/production_planning/results/solution-highs-pretty.sol +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/production_planning/results/solution.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/pumped_storage/README.md +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/pumped_storage/__init__.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/pumped_storage/input_data/elspot-prices_2021_hourly_eur.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/pumped_storage/model.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/pumped_storage/results/Pump.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/pumped_storage/results/Storage_level.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/pumped_storage/results/Turb.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/pumped_storage/results/objective.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/pumped_storage/results/problem-gurobi-machine.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/pumped_storage/results/problem-gurobi-pretty.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/pumped_storage/results/problem-highs-pretty.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/pumped_storage/results/solution-gurobi-machine.sol +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/pumped_storage/results/solution-gurobi-pretty.sol +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/pumped_storage/results/solution-highs-pretty.sol +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/sudoku/__init__.py +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/sudoku/input_data/initial_numbers.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/sudoku/results/problem-gurobi-machine.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/sudoku/results/problem-gurobi-pretty.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/sudoku/results/problem-highs-pretty.lp +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/sudoku/results/solution-gurobi-machine.sol +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/sudoku/results/solution-gurobi-pretty.sol +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/sudoku/results/solution-highs-pretty.sol +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/examples/sudoku/results/solution.csv +0 -0
- {pyoframe-1.0.0a0 → pyoframe-1.1.0}/tests/test_solver.py +0 -0
|
@@ -8,9 +8,12 @@ inputs:
|
|
|
8
8
|
GUROBI_WLS:
|
|
9
9
|
description: "..."
|
|
10
10
|
required: true
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
COPT_LICENSE_KEY:
|
|
12
|
+
description: "..."
|
|
13
|
+
required: true
|
|
14
|
+
COPT_LICENSE_DAT:
|
|
15
|
+
description: "..."
|
|
16
|
+
required: true
|
|
14
17
|
# MOSEK_LICENSE:
|
|
15
18
|
# description: "..."
|
|
16
19
|
# required: true
|
|
@@ -46,8 +49,7 @@ runs:
|
|
|
46
49
|
run: |
|
|
47
50
|
curl -L -o ~/installers/gurobi.tar.gz https://packages.gurobi.com/12.0/gurobi12.0.2_linux64.tar.gz
|
|
48
51
|
curl -L -o ~/installers/idaes-solvers.tar.gz https://github.com/IDAES/idaes-ext/releases/download/3.4.2/idaes-solvers-ubuntu2204-x86_64.tar.gz
|
|
49
|
-
|
|
50
|
-
# curl -L -o ~/installers/copt.tar.gz https://pub.shanshu.ai/download/copt/7.2.8/linux64/CardinalOptimizer-7.2.8-lnx64.tar.gz
|
|
52
|
+
curl -L -o ~/installers/copt.tar.gz https://pub.shanshu.ai/download/copt/7.2.11/linux64/CardinalOptimizer-7.2.11-lnx64.tar.gz
|
|
51
53
|
# curl -L -o ~/installers/mosek.tar.bz2 https://download.mosek.com/stable/10.2.0/mosektoolslinux64x86.tar.bz2
|
|
52
54
|
|
|
53
55
|
- name: Setup Gurobi Installation
|
|
@@ -76,28 +78,28 @@ runs:
|
|
|
76
78
|
timeout_minutes: 1
|
|
77
79
|
command: gurobi_cl
|
|
78
80
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
81
|
+
- name: Setup COPT Installation
|
|
82
|
+
shell: bash
|
|
83
|
+
env:
|
|
84
|
+
COPT_LICENSE_KEY: ${{ inputs.COPT_LICENSE_KEY }}
|
|
85
|
+
COPT_LICENSE_DAT: ${{ inputs.COPT_LICENSE_DAT }}
|
|
86
|
+
run: |
|
|
87
|
+
tar xfz ~/installers/copt.tar.gz -C ~/
|
|
88
|
+
ls ~/copt72
|
|
89
|
+
# set environment variables
|
|
90
|
+
export COPT_HOME="${HOME}/copt72"
|
|
91
|
+
echo "COPT_HOME=${COPT_HOME}" >> $GITHUB_ENV
|
|
92
|
+
echo "PATH=${PATH}:${COPT_HOME}/bin" >> $GITHUB_ENV
|
|
93
|
+
echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${COPT_HOME}/lib" >> $GITHUB_ENV
|
|
94
|
+
echo $COPT_HOME
|
|
95
|
+
echo "$COPT_LICENSE_KEY" > ${COPT_HOME}/license.key
|
|
96
|
+
echo "$COPT_LICENSE_DAT" > ${COPT_HOME}/license.dat
|
|
97
|
+
echo "COPT_LICENSE_DIR=${COPT_HOME}" >> $GITHUB_ENV
|
|
98
|
+
- name: Test COPT
|
|
99
|
+
if: ${{ inputs.CHECK_LICENSE == 'true' }}
|
|
100
|
+
shell: bash
|
|
101
|
+
run: |
|
|
102
|
+
copt_cmd -c "quit"
|
|
101
103
|
|
|
102
104
|
# - name: Setup MOSEK Installation
|
|
103
105
|
# shell: bash
|
|
@@ -45,9 +45,9 @@ jobs:
|
|
|
45
45
|
username: ${{ github.triggering_actor }}
|
|
46
46
|
env:
|
|
47
47
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
48
|
-
# If neither has permissions and no 'safe to test' label throw error
|
|
48
|
+
# If neither has permissions and no 'safe to test' label and not dependabot throw error
|
|
49
49
|
- name: Check User Permission
|
|
50
|
-
if: steps.checkAccess.outputs.require-result == 'false' && steps.checkTriggeringAccess.outputs.require-result == 'false' && !contains(github.event.pull_request.labels.*.name, 'safe to test')
|
|
50
|
+
if: steps.checkAccess.outputs.require-result == 'false' && steps.checkTriggeringAccess.outputs.require-result == 'false' && !contains(github.event.pull_request.labels.*.name, 'safe to test') && (github.actor != 'dependabot[bot]')
|
|
51
51
|
shell: bash
|
|
52
52
|
run: |
|
|
53
53
|
echo "${{ github.triggering_actor }} does not have permissions on this repo."
|
|
@@ -55,7 +55,8 @@ jobs:
|
|
|
55
55
|
exit 1
|
|
56
56
|
run:
|
|
57
57
|
if: |
|
|
58
|
-
(github.event_name == '
|
|
58
|
+
(github.event_name == 'pull_request_target' && github.actor == 'dependabot[bot]') ||
|
|
59
|
+
(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && github.actor != 'dependabot[bot]') ||
|
|
59
60
|
(github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository) ||
|
|
60
61
|
(github.event_name != 'pull_request_target' && github.event_name != 'pull_request')
|
|
61
62
|
runs-on: ubuntu-latest
|
|
@@ -80,12 +81,15 @@ jobs:
|
|
|
80
81
|
with:
|
|
81
82
|
python-version: ${{ matrix.python-version }}
|
|
82
83
|
cache: "pip"
|
|
83
|
-
- name:
|
|
84
|
-
|
|
85
|
-
- uses: ./.github/actions/setup_optimizers_linux
|
|
84
|
+
- name: Setup optimizers
|
|
85
|
+
uses: ./.github/actions/setup_optimizers_linux
|
|
86
86
|
with:
|
|
87
87
|
GUROBI_WLS: ${{ secrets.GUROBI_WLS }}
|
|
88
|
+
COPT_LICENSE_KEY: ${{ secrets.COPT_LICENSE_KEY }}
|
|
89
|
+
COPT_LICENSE_DAT: ${{ secrets.COPT_LICENSE_DAT }}
|
|
88
90
|
CHECK_LICENSE: true
|
|
91
|
+
- name: Install dependencies
|
|
92
|
+
run: pip install -e .[dev]
|
|
89
93
|
- name: Run tests and collect coverage
|
|
90
94
|
run: pytest --cov
|
|
91
95
|
- name: Upload coverage to Codecov
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyoframe
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: Blazing fast linear program interface
|
|
5
5
|
Author-email: Bravos Power <dev@bravospower.com>
|
|
6
6
|
License-Expression: MIT
|
|
7
|
-
Project-URL: Homepage, https://bravos-power.github.io/pyoframe/
|
|
8
|
-
Project-URL: documentation, https://bravos-power.github.io/pyoframe/
|
|
7
|
+
Project-URL: Homepage, https://bravos-power.github.io/pyoframe/latest
|
|
8
|
+
Project-URL: documentation, https://bravos-power.github.io/pyoframe/latest
|
|
9
9
|
Project-URL: repository, https://github.com/Bravos-Power/pyoframe/
|
|
10
10
|
Project-URL: Issues, https://github.com/Bravos-Power/pyoframe/issues
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -16,28 +16,27 @@ Requires-Python: >=3.9
|
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
License-File: LICENSE
|
|
18
18
|
Requires-Dist: polars~=1.0
|
|
19
|
-
Requires-Dist: numpy
|
|
20
19
|
Requires-Dist: pyarrow
|
|
21
|
-
Requires-Dist: pandas
|
|
22
|
-
Requires-Dist: pyoptinterface
|
|
20
|
+
Requires-Dist: pandas<3
|
|
21
|
+
Requires-Dist: pyoptinterface==0.5.1
|
|
23
22
|
Provides-Extra: highs
|
|
24
|
-
Requires-Dist: highsbox; extra == "highs"
|
|
23
|
+
Requires-Dist: highsbox<=1.12.0; extra == "highs"
|
|
25
24
|
Provides-Extra: ipopt
|
|
26
25
|
Requires-Dist: pyoptinterface[nlp]; extra == "ipopt"
|
|
27
|
-
Requires-Dist: llvmlite<=0.
|
|
26
|
+
Requires-Dist: llvmlite<=0.46.0; extra == "ipopt"
|
|
28
27
|
Provides-Extra: dev
|
|
29
28
|
Requires-Dist: ruff==0.12.11; extra == "dev"
|
|
30
29
|
Requires-Dist: polars>=1.32.3; extra == "dev"
|
|
31
30
|
Requires-Dist: pytest==8.4.1; extra == "dev"
|
|
32
31
|
Requires-Dist: pytest-cov==6.2.1; extra == "dev"
|
|
33
|
-
Requires-Dist: sybil[pytest]==9.
|
|
32
|
+
Requires-Dist: sybil[pytest]==9.3.0; extra == "dev"
|
|
34
33
|
Requires-Dist: pre-commit==4.3.0; extra == "dev"
|
|
35
34
|
Requires-Dist: gurobipy==12.0.3; extra == "dev"
|
|
36
35
|
Requires-Dist: coverage==7.10.6; extra == "dev"
|
|
37
36
|
Requires-Dist: ipykernel==6.30.1; extra == "dev"
|
|
38
|
-
Requires-Dist: highsbox; extra == "dev"
|
|
37
|
+
Requires-Dist: highsbox<=1.12.0; extra == "dev"
|
|
39
38
|
Requires-Dist: pyoptinterface[nlp]; extra == "dev"
|
|
40
|
-
Requires-Dist:
|
|
39
|
+
Requires-Dist: numpy; extra == "dev"
|
|
41
40
|
Provides-Extra: docs
|
|
42
41
|
Requires-Dist: mkdocs-material~=9.6.18; extra == "docs"
|
|
43
42
|
Requires-Dist: mkdocstrings[python]~=0.30.0; extra == "docs"
|
|
@@ -57,7 +56,7 @@ Dynamic: license-file
|
|
|
57
56
|
|
|
58
57
|
[](https://codecov.io/gh/Bravos-Power/pyoframe)
|
|
59
58
|
[](https://github.com/Bravos-Power/pyoframe/actions/workflows/ci.yml)
|
|
60
|
-
[](https://Bravos-Power.github.io/pyoframe/reference/)
|
|
59
|
+
[](https://Bravos-Power.github.io/pyoframe/latest/reference/)
|
|
61
60
|
[](https://opensource.org/licenses/MIT)
|
|
62
61
|
[](https://github.com/Bravos-Power/pyoframe/issues?q=is%3Aopen+is%3Aissue+no%3Alabel)
|
|
63
62
|
[](https://github.com/Bravos-Power/pyoframe/issues?q=is%3Aopen+is%3Aissue+label%3Abug)
|
|
@@ -65,9 +64,9 @@ Dynamic: license-file
|
|
|
65
64
|
|
|
66
65
|
A library to rapidly and memory-efficiently formulate large and sparse optimization models using Pandas or Polars DataFrames.
|
|
67
66
|
|
|
68
|
-
## **[Documentation](https://bravos-power.github.io/pyoframe/)**
|
|
67
|
+
## **[Documentation](https://bravos-power.github.io/pyoframe/latest/)**
|
|
69
68
|
|
|
70
|
-
[Read the documentation](https://bravos-power.github.io/pyoframe/) to get started or to learn how to [contribute](https://bravos-power.github.io/pyoframe/contribute/index.md).
|
|
69
|
+
[Read the documentation](https://bravos-power.github.io/pyoframe/latest/) to get started or to learn how to [contribute](https://bravos-power.github.io/pyoframe/latest/contribute/index.md).
|
|
71
70
|
|
|
72
71
|
|
|
73
72
|
## Acknowledgments
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://codecov.io/gh/Bravos-Power/pyoframe)
|
|
4
4
|
[](https://github.com/Bravos-Power/pyoframe/actions/workflows/ci.yml)
|
|
5
|
-
[](https://Bravos-Power.github.io/pyoframe/reference/)
|
|
5
|
+
[](https://Bravos-Power.github.io/pyoframe/latest/reference/)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
[](https://github.com/Bravos-Power/pyoframe/issues?q=is%3Aopen+is%3Aissue+no%3Alabel)
|
|
8
8
|
[](https://github.com/Bravos-Power/pyoframe/issues?q=is%3Aopen+is%3Aissue+label%3Abug)
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
|
|
11
11
|
A library to rapidly and memory-efficiently formulate large and sparse optimization models using Pandas or Polars DataFrames.
|
|
12
12
|
|
|
13
|
-
## **[Documentation](https://bravos-power.github.io/pyoframe/)**
|
|
13
|
+
## **[Documentation](https://bravos-power.github.io/pyoframe/latest/)**
|
|
14
14
|
|
|
15
|
-
[Read the documentation](https://bravos-power.github.io/pyoframe/) to get started or to learn how to [contribute](https://bravos-power.github.io/pyoframe/contribute/index.md).
|
|
15
|
+
[Read the documentation](https://bravos-power.github.io/pyoframe/latest/) to get started or to learn how to [contribute](https://bravos-power.github.io/pyoframe/latest/contribute/index.md).
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
## Acknowledgments
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
hide:
|
|
3
|
+
- navigation
|
|
4
|
+
---
|
|
5
|
+
# Contribute
|
|
6
|
+
|
|
7
|
+
Contributions are more than welcome! Submit a pull request, or [open an issue](https://github.com/Bravos-Power/pyoframe/issues/new) and I (Martin) will gladly answer your questions on how to contribute.
|
|
8
|
+
|
|
9
|
+
## Setup a development environment
|
|
10
|
+
|
|
11
|
+
1. Clone this repository.
|
|
12
|
+
```console
|
|
13
|
+
git clone https://github.com/Bravos-Power/pyoframe
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
2. Install the dependencies.
|
|
17
|
+
```console
|
|
18
|
+
pip install --editable .[dev,docs]
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
3. Install the pre-commit hooks.
|
|
22
|
+
```console
|
|
23
|
+
pre-commit install
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Running the test suite
|
|
27
|
+
|
|
28
|
+
Run `pytest` to execute the test suite. (If you'd like to view coverage information add the flag `--cov` and then run `coverage html`.)
|
|
29
|
+
|
|
30
|
+
The only errors you should see when running the test suite are those related to a solver not being installed.
|
|
31
|
+
|
|
32
|
+
Pyoframe has several types of tests.
|
|
33
|
+
|
|
34
|
+
1. Your typical unit tests under the `tests/` folder.
|
|
35
|
+
|
|
36
|
+
2. Integration tests in `tests/test_examples.py`. These tests will run all the models in `tests/examples` and make sure that your changes haven't altered the model results (stored under `tests/examples/<model>/results`). In the rare cases where you _want_ the model results to change (e.g. if you've changed the model), you can regenerate the results using `python -m tests.test_examples`.
|
|
37
|
+
|
|
38
|
+
3. Doctests in the docstrings of the source code (`src/`).
|
|
39
|
+
|
|
40
|
+
4. Documentation tests (in `docs/`). All Python code blocks in the documentation are run to ensure the documentation doesn't become outdated. This is done using Sybil. Refer to the [Sybil documentation](https://sybil.readthedocs.io/en/latest/markdown.html#code-blocks) to learn how to create setup code or skip code blocks you don't wish to test.
|
|
41
|
+
|
|
42
|
+
!!! warning "Non-breaking spaces"
|
|
43
|
+
Be aware that Pyoframe uses non-breaking spaces to improve the formatting of expressions. If your Sybil tests are unexpectedly failing, make sure that the expected output contains all the needed non-breaking spaces.
|
|
44
|
+
|
|
45
|
+
## Writing documentation
|
|
46
|
+
|
|
47
|
+
You can preview the documentation website by running `mkdocs serve` and navigating to [`http://127.0.0.1:8000/pyoframe/`](http://127.0.0.1:8000/pyoframe/).
|
|
48
|
+
|
|
49
|
+
We use [Material Docs](https://squidfunk.github.io/mkdocs-material/) for documentation with several plugins to enable features like automatically compiling the docstrings into the reference API. Please follow the [Google docstring style](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html) and the [Google style guide](https://developers.google.com/style). We use Mike to allow readers to view the documentation for previous releases (preview available via `mike serve`).
|
|
50
|
+
|
|
51
|
+
## Linting and formatting
|
|
52
|
+
|
|
53
|
+
We use Ruff for linting and formatting. The pre-commit hooks will run `ruff format` on commit. You should also make sure `ruff check` returns no errors before submitting a PR. To format code blocks in the documentation run: `doccmd --language=python --no-pad-file --command="ruff format" docs/`.
|
|
54
|
+
|
|
55
|
+
## Additional tips
|
|
56
|
+
|
|
57
|
+
I recommend skimming or reading the [Internal Details](../learn/advanced-concepts/internals.md) page for some background on how Pyoframe works.
|
|
58
|
+
|
|
59
|
+
For core developers:
|
|
60
|
+
|
|
61
|
+
- If you use `.unique`, `.join`, `.sort`, or `.group_by` on a Polars dataframe, make sure to set the `maintain_order` parameter appropriately (typically, `maintain_order=Config.maintain_order`).
|
|
62
|
+
|
|
63
|
+
For repository maintainers:
|
|
64
|
+
|
|
65
|
+
- Our CI pipeline on Github Actions requires a Gurobi and COPT license to run. If the Gurobi license expires, generate a new one and copy the contents of the `guorbi.lic` file into the `GUROBI_WLS` Github secret (Settings -> Secrets and variables -> actions). Similarly, if the COPT license expires, request a new academic license (or email COPT sales for a free one) and copy the contents of both license files to the matching Github secrets.
|
|
@@ -28,9 +28,9 @@ m.Buy = pf.Variable(food["food"], lb=0, ub=food[["food", "stock"]])
|
|
|
28
28
|
|
|
29
29
|
nutrient_intake = (m.Buy * food_nutrients).sum_by("category")
|
|
30
30
|
m.min_nutrients = (
|
|
31
|
-
nutrients[["category", "min"]] <= nutrient_intake.
|
|
31
|
+
nutrients[["category", "min"]] <= nutrient_intake.drop_extras() # (1)!
|
|
32
32
|
)
|
|
33
|
-
m.max_nutrients = nutrient_intake.
|
|
33
|
+
m.max_nutrients = nutrient_intake.drop_extras() <= nutrients[["category", "max"]]
|
|
34
34
|
|
|
35
35
|
total_cost = (m.Buy * food[["food", "cost"]]).sum()
|
|
36
36
|
m.minimize = total_cost
|
|
@@ -39,7 +39,7 @@ m.minimize = total_cost
|
|
|
39
39
|
m.optimize()
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
1. `.
|
|
42
|
+
1. `.drop_extras()` ensures that if `min_nutrient` is `null` for certain foods, no constraint will be created for those foods. [Learn more](../learn/concepts/addition.md)
|
|
43
43
|
|
|
44
44
|
So the solution is...
|
|
45
45
|
|
|
@@ -26,12 +26,12 @@ model.customers = model.x_axis * model.y_axis # (1)!
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
model.facility_position = pf.Variable(model.facilities, model.axis, lb=0, ub=1)
|
|
29
|
-
model.customer_position_x =
|
|
29
|
+
model.customer_position_x = pf.Param(
|
|
30
30
|
{"x": range(G), "x_pos": [step / (G - 1) for step in range(G)]}
|
|
31
|
-
)
|
|
32
|
-
model.customer_position_y =
|
|
31
|
+
)
|
|
32
|
+
model.customer_position_y = pf.Param(
|
|
33
33
|
{"y": range(G), "y_pos": [step / (G - 1) for step in range(G)]}
|
|
34
|
-
)
|
|
34
|
+
)
|
|
35
35
|
|
|
36
36
|
model.max_distance = pf.Variable(lb=0)
|
|
37
37
|
|
|
@@ -12,7 +12,7 @@ hide:
|
|
|
12
12
|
- Seamlessly integrates with pandas thanks to its dataframe-centric design.
|
|
13
13
|
- Extremely **fast and memory efficient** (even for sparse problems) thanks to Polars, Rust, and Pyoptinterface.
|
|
14
14
|
- Clear Pythonic syntax for writing mathematical models.
|
|
15
|
-
- Supports Gurobi, HiGHS, and
|
|
15
|
+
- Supports Gurobi, HiGHS, Ipopt and COPT solvers.
|
|
16
16
|
- Continuously used in high-stakes production environments.
|
|
17
17
|
- 100% open-source (MIT License).
|
|
18
18
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# Internal details
|
|
2
2
|
|
|
3
|
-
Pyoframe's inner workings involve a few tricks that you should be aware of
|
|
4
|
-
if you wish to modify Pyoframe's internal code.
|
|
3
|
+
Pyoframe's inner workings involve a few tricks that you should be aware of if you wish to contribute to Pyoframe's code base.
|
|
5
4
|
|
|
6
5
|
## The zero variable
|
|
7
6
|
|
|
@@ -16,4 +15,10 @@ constant terms and also simplifies the [handling of quadratics](#quadratics).
|
|
|
16
15
|
|
|
17
16
|
Internally, [Expression][pyoframe.Expression] is used to represent both linear and quadratic mathematical expressions. When a quadratic expression is formed, column `__quadratic_variable_id` is added to [Expression.data][pyoframe.Expression.data]. If an expression's quadratic terms happen to cancel out (e.g. `(ab + c) - ab`), this column is automatically removed.
|
|
18
17
|
|
|
19
|
-
Column `__quadratic_variable_id` records the ID of the _second_ variable in a quadratic term (the `b` in `3ab`). For linear terms, which have no second variable, this column contains the [Zero Variable](#the-zero-variable).
|
|
18
|
+
Column `__quadratic_variable_id` records the ID of the _second_ variable in a quadratic term (the `b` in `3ab`). For linear terms, which have no second variable, this column contains the [Zero Variable](#the-zero-variable).
|
|
19
|
+
|
|
20
|
+
Quadratic terms are always stored such that the first term's variable ID (in column `__variable_id`) is greater or equal to the second term's variable id (in column `__quadratic_variable_id`). For example, `var_7 * var_8` would be rearranged and stored as `var_8 * var_7`. This helps simplify expressions and provides a useful guarantee: If the variable in the first column (`__variable_id`) is the Zero Variable (`var_0`) we know the variable in the second column must also be the Zero Variable and, thus, the term must be a constant.
|
|
21
|
+
|
|
22
|
+
## Division
|
|
23
|
+
|
|
24
|
+
Divisions are rearranged into multiplications when possible. Specifically, `a / b` is computed as `a * (1 / b)` (see `BaseOperableBlock.__truediv__`) except for the special case where `a` is a `float` or `int`. In that case, a Polars operation is used to compute the division (see `Expression.__rtruediv__`).
|
|
@@ -6,9 +6,9 @@ Pyoframe is already one of the fastest and most memory-efficient libraries for f
|
|
|
6
6
|
|
|
7
7
|
[Polars](https://pola.rs/) is much faster than Pandas. Moreover, if you use Pandas, there will be a (very small) overhead because Pyoframe converts all DataFrames to Polars prior to computations.
|
|
8
8
|
|
|
9
|
-
## Use integer
|
|
9
|
+
## Use integer labels
|
|
10
10
|
|
|
11
|
-
Pyoframe
|
|
11
|
+
Pyoframe works with any label data type (e.g. string labels, date labels, etc.), but integer labels are fastest and most memory efficient.
|
|
12
12
|
|
|
13
13
|
## Disable `maintain_order`
|
|
14
14
|
|
|
@@ -18,14 +18,14 @@ By default, Pyoframe ensures that the order of variables, constraints, and mathe
|
|
|
18
18
|
pf.Config.maintain_order = False
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
## Disable
|
|
21
|
+
## Disable checks for extra values
|
|
22
22
|
|
|
23
|
-
Disabling
|
|
23
|
+
Disabling checks for extra values means that, instead of raising [extra value exceptions](../concepts/addition.md), pyoframe will process sums with extra values as if [`keep_extras`][pyoframe.Expression.keep_extras] had been applied. While this may improve performance, it will silence potentially important errors meant to help you build your model. If you'd like to disable checks for extra values, we recommend you do so only after thoroughly testing your model and ensuring that all potential extra value exceptions have been handled.
|
|
24
24
|
|
|
25
|
-
The following code disables
|
|
25
|
+
The following code disables checks for extra values:
|
|
26
26
|
|
|
27
27
|
```python
|
|
28
|
-
pf.Config.
|
|
28
|
+
pf.Config.disable_extras_checks = True
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
<!-- TODO REVISIT
|