pyoframe 0.2.0__tar.gz → 1.0.0a0__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-0.2.0 → pyoframe-1.0.0a0}/.github/actions/setup_optimizers_linux/action.yml +25 -20
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.github/workflows/ci.yml +7 -3
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.github/workflows/format.yml +1 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.github/workflows/lines_changed_counter.yml +2 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.github/workflows/lint.yml +1 -0
- pyoframe-1.0.0a0/.github/workflows/publish_doc.yml +54 -0
- pyoframe-1.0.0a0/.github/workflows/publish_doc_dev.yml +43 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.github/workflows/publish_to_pypi.yml +1 -0
- pyoframe-1.0.0a0/.github/workflows/test_doc.yml +23 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.gitignore +1 -1
- pyoframe-1.0.0a0/.pre-commit-config.yaml +15 -0
- pyoframe-1.0.0a0/.vscode/launch.json +17 -0
- pyoframe-1.0.0a0/.vscode/settings.json +14 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/PKG-INFO +32 -25
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/README.md +2 -2
- pyoframe-1.0.0a0/conftest.py +93 -0
- pyoframe-1.0.0a0/docs/.nav.yml +13 -0
- pyoframe-1.0.0a0/docs/contribute/index.md +51 -0
- pyoframe-1.0.0a0/docs/examples/.nav.yml +6 -0
- pyoframe-1.0.0a0/docs/examples/diet.md +68 -0
- pyoframe-1.0.0a0/docs/examples/facility_location.md +73 -0
- pyoframe-1.0.0a0/docs/examples/index.md +8 -0
- pyoframe-1.0.0a0/docs/examples/portfolio_optimization.md +66 -0
- pyoframe-1.0.0a0/docs/examples/production.md +60 -0
- pyoframe-1.0.0a0/docs/index.md +78 -0
- pyoframe-1.0.0a0/docs/javascripts/feedback.js +26 -0
- pyoframe-1.0.0a0/docs/learn/advanced-concepts/.nav.yml +6 -0
- pyoframe-0.2.0/docs/learn/03_concepts/01_pyoframe-datastructure.md → pyoframe-1.0.0a0/docs/learn/advanced-concepts/datastructure.md +2 -2
- pyoframe-1.0.0a0/docs/learn/advanced-concepts/internals.md +19 -0
- pyoframe-1.0.0a0/docs/learn/advanced-concepts/performance.md +36 -0
- pyoframe-1.0.0a0/docs/learn/advanced-concepts/quadratics.md +33 -0
- pyoframe-1.0.0a0/docs/learn/concepts/.nav.yml +4 -0
- pyoframe-1.0.0a0/docs/learn/concepts/building-blocks.md +17 -0
- pyoframe-0.2.0/docs/learn/01_getting-started/06_accessing_the_solver.md → pyoframe-1.0.0a0/docs/learn/concepts/solver-access.md +16 -13
- pyoframe-1.0.0a0/docs/learn/concepts/special-functions.md +227 -0
- pyoframe-1.0.0a0/docs/learn/get-started/.nav.yml +4 -0
- pyoframe-1.0.0a0/docs/learn/get-started/basic-example/example-with-dimensions.md +187 -0
- pyoframe-1.0.0a0/docs/learn/get-started/basic-example/example.md +61 -0
- pyoframe-1.0.0a0/docs/learn/get-started/basic-example/food_data.csv +3 -0
- pyoframe-1.0.0a0/docs/learn/get-started/installation.md +68 -0
- {pyoframe-0.2.0/docs/learn/01_getting-started → pyoframe-1.0.0a0/docs/learn/get-started}/power_grid_example.ipynb +3 -3
- pyoframe-1.0.0a0/docs/learn/migrate/v1.0.md +105 -0
- pyoframe-1.0.0a0/docs/overrides/main.html +12 -0
- pyoframe-1.0.0a0/docs/overrides/partials/comments.html +46 -0
- pyoframe-1.0.0a0/docs/reference/.nav.yml +2 -0
- pyoframe-1.0.0a0/docs/reference/index.md +7 -0
- pyoframe-1.0.0a0/docs/reference/pandas.DataFrame.to_expr.md +3 -0
- pyoframe-1.0.0a0/docs/reference/polars.DataFrame.to_expr.md +3 -0
- pyoframe-1.0.0a0/docs/reference/pyoframe.Config.md +12 -0
- pyoframe-1.0.0a0/docs/stylesheets/extra.css +4 -0
- pyoframe-1.0.0a0/docs/why-pyoframe/index.md +11 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/docs/why-pyoframe/pyoframe-performance.ipynb +1 -1
- pyoframe-1.0.0a0/giscus.json +3 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/mkdocs.yml +61 -5
- pyoframe-1.0.0a0/pyproject.toml +111 -0
- pyoframe-1.0.0a0/scripts/archive/benchmark_assign_ids_constraints.py +226 -0
- pyoframe-1.0.0a0/scripts/archive/benchmark_assign_ids_constraints_2.py +158 -0
- pyoframe-1.0.0a0/scripts/archive/benchmark_assign_ids_variables.py +72 -0
- pyoframe-1.0.0a0/scripts/archive/benchmark_attr_performance.py +73 -0
- pyoframe-1.0.0a0/scripts/generate_api_reference.py +34 -0
- pyoframe-1.0.0a0/scripts/griffe_extensions.py +25 -0
- pyoframe-1.0.0a0/src/pyoframe/__init__.py +35 -0
- pyoframe-1.0.0a0/src/pyoframe/_arithmetic.py +547 -0
- pyoframe-1.0.0a0/src/pyoframe/_constants.py +416 -0
- pyoframe-1.0.0a0/src/pyoframe/_core.py +2575 -0
- pyoframe-1.0.0a0/src/pyoframe/_model.py +578 -0
- pyoframe-1.0.0a0/src/pyoframe/_model_element.py +175 -0
- pyoframe-1.0.0a0/src/pyoframe/_monkey_patch.py +80 -0
- pyoframe-0.2.0/src/pyoframe/objective.py → pyoframe-1.0.0a0/src/pyoframe/_objective.py +49 -14
- pyoframe-0.2.0/src/pyoframe/util.py → pyoframe-1.0.0a0/src/pyoframe/_utils.py +106 -126
- pyoframe-1.0.0a0/src/pyoframe/_version.py +34 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/src/pyoframe.egg-info/PKG-INFO +32 -25
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/src/pyoframe.egg-info/SOURCES.txt +70 -41
- pyoframe-1.0.0a0/src/pyoframe.egg-info/requires.txt +40 -0
- pyoframe-1.0.0a0/tests/conftest.py +41 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/cutting_stock_problem/model.py +8 -8
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/model.py +9 -13
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/model_gurobipy.py +1 -3
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_location/model.py +14 -9
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/model.py +12 -9
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/model_gurobipy.py +14 -11
- pyoframe-1.0.0a0/tests/examples/portfolio_optim/input_data/assets.csv +6 -0
- pyoframe-1.0.0a0/tests/examples/portfolio_optim/input_data/covariance.csv +26 -0
- pyoframe-1.0.0a0/tests/examples/portfolio_optim/input_data/portfolio_params.csv +3 -0
- pyoframe-1.0.0a0/tests/examples/portfolio_optim/model.py +195 -0
- pyoframe-1.0.0a0/tests/examples/portfolio_optim/results/con_min_return.csv +2 -0
- pyoframe-1.0.0a0/tests/examples/portfolio_optim/results/con_weights_sum.csv +2 -0
- pyoframe-1.0.0a0/tests/examples/portfolio_optim/results/objective.csv +2 -0
- pyoframe-1.0.0a0/tests/examples/portfolio_optim/results/problem-gurobi-machine.lp +18 -0
- pyoframe-1.0.0a0/tests/examples/portfolio_optim/results/problem-gurobi-pretty.lp +24 -0
- pyoframe-1.0.0a0/tests/examples/portfolio_optim/results/solution-gurobi-machine.sol +7 -0
- pyoframe-1.0.0a0/tests/examples/portfolio_optim/results/solution-gurobi-pretty.sol +7 -0
- pyoframe-1.0.0a0/tests/examples/portfolio_optim/results/weight.csv +6 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/model.py +10 -7
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/model.py +15 -12
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/model.py +10 -7
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/test_arithmetic.py +175 -108
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/test_examples.py +122 -69
- pyoframe-1.0.0a0/tests/test_io.py +173 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/test_model.py +40 -15
- pyoframe-1.0.0a0/tests/test_names.py +77 -0
- pyoframe-1.0.0a0/tests/test_objective.py +26 -0
- pyoframe-1.0.0a0/tests/test_solver.py +295 -0
- pyoframe-1.0.0a0/tests/util.py +81 -0
- pyoframe-0.2.0/.github/workflows/publish_doc.yml +0 -33
- pyoframe-0.2.0/.pre-commit-config.yaml +0 -9
- pyoframe-0.2.0/.vscode/settings.json +0 -7
- pyoframe-0.2.0/conftest.py +0 -38
- pyoframe-0.2.0/docs/SUMMARY.md +0 -4
- pyoframe-0.2.0/docs/contribute/index.md +0 -36
- pyoframe-0.2.0/docs/index.md +0 -53
- pyoframe-0.2.0/docs/learn/01_getting-started/01_installation.md +0 -26
- pyoframe-0.2.0/docs/learn/01_getting-started/02_build-simple-model.md +0 -196
- pyoframe-0.2.0/docs/learn/01_getting-started/04_building_blocks.md +0 -17
- pyoframe-0.2.0/docs/learn/01_getting-started/05_special_functions.md +0 -18
- pyoframe-0.2.0/docs/learn/01_getting-started/SUMMARY.md +0 -5
- pyoframe-0.2.0/docs/learn/01_getting-started/inputs/food_data.csv +0 -3
- pyoframe-0.2.0/docs/learn/02_tutorials/index.md +0 -5
- pyoframe-0.2.0/docs/learn/03_concepts/02_performance_tips.md +0 -13
- pyoframe-0.2.0/docs/learn/03_concepts/03_quadratic_expressions.md +0 -41
- pyoframe-0.2.0/docs/learn/03_concepts/SUMMARY.md +0 -4
- pyoframe-0.2.0/docs/learn/04_examples/index.md +0 -8
- pyoframe-0.2.0/docs/learn/SUMMARY.md +0 -4
- pyoframe-0.2.0/docs/learn/index.md +0 -44
- pyoframe-0.2.0/docs/overrides/home.html +0 -4
- pyoframe-0.2.0/docs/why-pyoframe/SUMMARY.md +0 -5
- pyoframe-0.2.0/docs/why-pyoframe/index.md +0 -14
- pyoframe-0.2.0/docs/why-pyoframe/why-pyoframe.md +0 -1
- pyoframe-0.2.0/pyproject.toml +0 -70
- pyoframe-0.2.0/scripts/gen_ref_pages.py +0 -35
- pyoframe-0.2.0/src/pyoframe/__init__.py +0 -28
- pyoframe-0.2.0/src/pyoframe/_arithmetic.py +0 -441
- pyoframe-0.2.0/src/pyoframe/_version.py +0 -21
- pyoframe-0.2.0/src/pyoframe/constants.py +0 -140
- pyoframe-0.2.0/src/pyoframe/core.py +0 -1794
- pyoframe-0.2.0/src/pyoframe/model.py +0 -408
- pyoframe-0.2.0/src/pyoframe/model_element.py +0 -184
- pyoframe-0.2.0/src/pyoframe/monkey_patch.py +0 -54
- pyoframe-0.2.0/src/pyoframe.egg-info/requires.txt +0 -31
- pyoframe-0.2.0/tests/conftest.py +0 -19
- pyoframe-0.2.0/tests/examples/facility_problem/results/con_max_capacity.csv +0 -6
- pyoframe-0.2.0/tests/examples/facility_problem/results/con_meet_demand.csv +0 -5
- pyoframe-0.2.0/tests/examples/pumped_storage/results/initial_storage_level.csv +0 -2
- pyoframe-0.2.0/tests/examples/pumped_storage/results/intermediate_storage_level.csv +0 -1461
- pyoframe-0.2.0/tests/examples/pumped_storage/results/pump_and_turbine_xor.csv +0 -1461
- pyoframe-0.2.0/tests/test_io.py +0 -137
- pyoframe-0.2.0/tests/test_operations.py +0 -53
- pyoframe-0.2.0/tests/test_solver.py +0 -208
- pyoframe-0.2.0/tests/util.py +0 -53
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.gitattributes +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.github/CODEOWNERS +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.github/actions/setup_optimizers_macos/action.yml +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.github/actions/setup_optimizers_windows/action.yml +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/CHANGELOG.md +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/LICENSE +0 -0
- /pyoframe-0.2.0/docs/learn/03_concepts/04_troubleshooting.md → /pyoframe-1.0.0a0/docs/learn/advanced-concepts/troubleshooting.md +0 -0
- {pyoframe-0.2.0/docs/learn/01_getting-started/inputs → pyoframe-1.0.0a0/docs/learn/get-started/basic-example}/foods.csv +0 -0
- {pyoframe-0.2.0/docs/learn/01_getting-started/inputs → pyoframe-1.0.0a0/docs/learn/get-started/basic-example}/foods_to_nutrients.csv +0 -0
- {pyoframe-0.2.0/docs/learn/01_getting-started/inputs → pyoframe-1.0.0a0/docs/learn/get-started/basic-example}/nutrients.csv +0 -0
- {pyoframe-0.2.0/docs/learn/01_getting-started/inputs → pyoframe-1.0.0a0/docs/learn/get-started/basic-example}/results.csv +0 -0
- {pyoframe-0.2.0/docs/learn/01_getting-started → pyoframe-1.0.0a0/docs/learn/get-started}/three-bus.png +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/docs/overrides/partials/actions.html +0 -0
- /pyoframe-0.2.0/docs/why-pyoframe/benchmarks.md → /pyoframe-1.0.0a0/docs/overrides/partials/integrations/analytics/custom.html +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/docs/why-pyoframe/data_py.parquet +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/docs/why-pyoframe/gen_py.parquet +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/docs/why-pyoframe/three-bus-four-gen.png +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/setup.cfg +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/src/pyoframe.egg-info/dependency_links.txt +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/src/pyoframe.egg-info/top_level.txt +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/__init__.py +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/README.md +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/__init__.py +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/cutting_stock_problem/__init__.py +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/cutting_stock_problem/input_data/orders.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/cutting_stock_problem/input_data/parameters.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/cutting_stock_problem/results/objective.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/cutting_stock_problem/results/problem-gurobi-machine.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/cutting_stock_problem/results/problem-gurobi-pretty.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/cutting_stock_problem/results/problem-highs-machine.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/cutting_stock_problem/results/problem-highs-pretty.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/README.md +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/__init__.py +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/input_data/foods.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/input_data/foods_to_nutrients.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/input_data/nutrients.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/Buy.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/Buy_ub.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/max_nutrients.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/min_nutrients.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/objective.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/problem-gurobi-machine.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/problem-gurobi-pretty.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/problem-highs-machine.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/problem-highs-pretty.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/solution-gurobi-machine.sol +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/solution-gurobi-pretty.sol +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/solution-highs-machine.sol +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/solution-highs-pretty.sol +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_location/__init__.py +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_location/results/objective.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_location/results/problem-gurobi-machine.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_location/results/problem-gurobi-pretty.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/__init__.py +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/input_data/plants.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/input_data/transport_costs.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/input_data/wharehouses.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/objective.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/open.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/problem-gurobi-machine.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/problem-gurobi-pretty.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/problem-highs-machine.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/problem-highs-pretty.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/solution-gurobi-machine.sol +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/solution-gurobi-pretty.sol +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/solution-highs-machine.sol +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/solution-highs-pretty.sol +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/transport.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/__init__.py +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/input_data/machines_availability.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/input_data/processing_times.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/input_data/products_profit.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/results/objective.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/results/problem-gurobi-machine.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/results/problem-gurobi-pretty.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/results/problem-highs-machine.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/results/problem-highs-pretty.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/results/solution-gurobi-machine.sol +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/results/solution-gurobi-pretty.sol +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/results/solution-highs-machine.sol +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/results/solution-highs-pretty.sol +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/results/solution.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/README.md +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/__init__.py +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/input_data/elspot-prices_2021_hourly_eur.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/Pump.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/Storage_level.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/Turb.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/objective.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/problem-gurobi-machine.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/problem-gurobi-pretty.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/problem-highs-machine.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/problem-highs-pretty.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/solution-gurobi-machine.sol +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/solution-gurobi-pretty.sol +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/solution-highs-machine.sol +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/solution-highs-pretty.sol +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/__init__.py +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/input_data/initial_numbers.csv +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/results/problem-gurobi-machine.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/results/problem-gurobi-pretty.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/results/problem-highs-machine.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/results/problem-highs-pretty.lp +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/results/solution-gurobi-machine.sol +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/results/solution-gurobi-pretty.sol +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/results/solution-highs-machine.sol +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/results/solution-highs-pretty.sol +0 -0
- {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/results/solution.csv +0 -0
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
name: "Install optimizers on linux"
|
|
6
6
|
|
|
7
7
|
inputs:
|
|
8
|
-
GUROBI_WLS:
|
|
8
|
+
GUROBI_WLS:
|
|
9
9
|
description: "..."
|
|
10
10
|
required: true
|
|
11
11
|
# COPT_CLIENT_INI:
|
|
@@ -17,7 +17,7 @@ inputs:
|
|
|
17
17
|
# GITHUB_TOKEN:
|
|
18
18
|
# description: "..."
|
|
19
19
|
# required: true
|
|
20
|
-
CHECK_LICENSE:
|
|
20
|
+
CHECK_LICENSE:
|
|
21
21
|
description: "..."
|
|
22
22
|
required: true
|
|
23
23
|
|
|
@@ -33,18 +33,22 @@ runs:
|
|
|
33
33
|
id: cache-installers-linux
|
|
34
34
|
uses: actions/cache@v4
|
|
35
35
|
env:
|
|
36
|
-
cache-name: cache-installers-linux
|
|
36
|
+
cache-name: cache-installers-linux-v2
|
|
37
37
|
with:
|
|
38
38
|
path: ~/installers
|
|
39
|
-
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('optimizer_version.toml') }}
|
|
39
|
+
key: ${{ runner.os }}-build-${{ env.cache-name }}-v2-${{ hashFiles('optimizer_version.toml') }}
|
|
40
40
|
restore-keys: |
|
|
41
|
-
${{ runner.os }}-build-${{ env.cache-name }}-
|
|
41
|
+
${{ runner.os }}-build-${{ env.cache-name }}-v2-
|
|
42
42
|
|
|
43
|
-
- if: ${{ steps.cache-installers-linux.outputs.cache-hit != 'true' }}
|
|
43
|
+
- if: ${{ steps.cache-installers-linux-v2.outputs.cache-hit != 'true' }}
|
|
44
44
|
shell: bash
|
|
45
45
|
name: Download Installers
|
|
46
46
|
run: |
|
|
47
47
|
curl -L -o ~/installers/gurobi.tar.gz https://packages.gurobi.com/12.0/gurobi12.0.2_linux64.tar.gz
|
|
48
|
+
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
|
|
51
|
+
# curl -L -o ~/installers/mosek.tar.bz2 https://download.mosek.com/stable/10.2.0/mosektoolslinux64x86.tar.bz2
|
|
48
52
|
|
|
49
53
|
- name: Setup Gurobi Installation
|
|
50
54
|
shell: bash
|
|
@@ -59,13 +63,13 @@ runs:
|
|
|
59
63
|
echo "PATH=${PATH}:${GUROBI_HOME}/bin" >> $GITHUB_ENV
|
|
60
64
|
echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${GUROBI_HOME}/lib" >> $GITHUB_ENV
|
|
61
65
|
echo $GUROBI_HOME
|
|
62
|
-
|
|
66
|
+
|
|
63
67
|
# setup license using secrets
|
|
64
68
|
echo "$GUROBI_WLS" > ~/gurobi.lic
|
|
65
69
|
echo "GRB_LICENSE_FILE=${HOME}/gurobi.lic" >> $GITHUB_ENV
|
|
66
70
|
- name: Test Gurobi
|
|
67
71
|
if: ${{ inputs.CHECK_LICENSE == 'true' }}
|
|
68
|
-
uses: nick-fields/retry@v3
|
|
72
|
+
uses: nick-fields/retry@v3 # wait 30 seconds (5x) if all licenses are already in use
|
|
69
73
|
with:
|
|
70
74
|
max_attempts: 5
|
|
71
75
|
retry_wait_seconds: 30
|
|
@@ -118,15 +122,16 @@ runs:
|
|
|
118
122
|
# run: |
|
|
119
123
|
# msktestlic
|
|
120
124
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
125
|
+
- name: Setup IPOPT Installation
|
|
126
|
+
shell: bash
|
|
127
|
+
run: |
|
|
128
|
+
sudo apt-get install -y libopenblas-dev liblapack3 libgfortran5
|
|
129
|
+
mkdir -p ~/ipopt
|
|
130
|
+
tar xfz ~/installers/idaes-solvers.tar.gz -C ~/ipopt
|
|
131
|
+
echo "PATH=${PATH}:${HOME}/ipopt" >> $GITHUB_ENV
|
|
132
|
+
echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${HOME}/ipopt" >> $GITHUB_ENV
|
|
133
|
+
ls ~/ipopt
|
|
134
|
+
- name: Test IPOPT
|
|
135
|
+
shell: bash
|
|
136
|
+
run: |
|
|
137
|
+
ipopt -v
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
# This workflow runs the tests.
|
|
2
|
+
# It is triggered automatically on pull requests and is also run weekly on the main branch.
|
|
3
|
+
# Tests are run in a matrix of different Python versions.
|
|
4
|
+
# This test also uploads coverage results to Codecov.
|
|
5
|
+
|
|
1
6
|
# Note: We use the insecure pull_request_target to allow running workflows from forks.
|
|
2
7
|
# However, we've added checks (see below) for safety.
|
|
3
8
|
# In short, the 'safe to test' label must exist AND the workflow must be run by someone with write access.
|
|
@@ -75,13 +80,12 @@ jobs:
|
|
|
75
80
|
with:
|
|
76
81
|
python-version: ${{ matrix.python-version }}
|
|
77
82
|
cache: "pip"
|
|
83
|
+
- name: Install dependencies
|
|
84
|
+
run: pip install -e .[dev]
|
|
78
85
|
- uses: ./.github/actions/setup_optimizers_linux
|
|
79
86
|
with:
|
|
80
87
|
GUROBI_WLS: ${{ secrets.GUROBI_WLS }}
|
|
81
88
|
CHECK_LICENSE: true
|
|
82
|
-
- name: Install dependencies
|
|
83
|
-
run: |
|
|
84
|
-
pip install --editable .[dev]
|
|
85
89
|
- name: Run tests and collect coverage
|
|
86
90
|
run: pytest --cov
|
|
87
91
|
- name: Upload coverage to Codecov
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# This workflow runs every time a new tag is released and publishes the documentation to the website.
|
|
2
|
+
name: Docs
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
release:
|
|
6
|
+
types: [released]
|
|
7
|
+
env:
|
|
8
|
+
ENABLED_GIT_REVISION_DATE: true
|
|
9
|
+
ENABLED_GIT_COMMITTERS: true
|
|
10
|
+
DOCS_PRERELEASE: false
|
|
11
|
+
permissions:
|
|
12
|
+
contents: write
|
|
13
|
+
jobs:
|
|
14
|
+
deploy:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
environment: build-docs
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
with:
|
|
20
|
+
fetch-depth: 0 # Needed for git-revision-date-localized plugin
|
|
21
|
+
fetch-tags: true
|
|
22
|
+
- name: Configure Git Credentials
|
|
23
|
+
run: |
|
|
24
|
+
git config user.name github-actions[bot]
|
|
25
|
+
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
|
|
26
|
+
- uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: 3.x
|
|
29
|
+
cache: 'pip'
|
|
30
|
+
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
|
|
31
|
+
- uses: actions/cache@v4
|
|
32
|
+
with:
|
|
33
|
+
key: mkdocs-material-${{ env.cache_id }}
|
|
34
|
+
path: .cache
|
|
35
|
+
restore-keys: |
|
|
36
|
+
mkdocs-material-
|
|
37
|
+
- run: pip install .[docs]
|
|
38
|
+
- name: Get latest tag
|
|
39
|
+
id: tags
|
|
40
|
+
run: |
|
|
41
|
+
# Get the latest tag like v1.2.3, remove the leading 'v' if present, and remove the patch version
|
|
42
|
+
latest_tag=$(git describe --tags --abbrev=0)
|
|
43
|
+
clean_tag=${latest_tag#v}
|
|
44
|
+
minor_tag=$(echo "$clean_tag" | cut -d. -f1-2)
|
|
45
|
+
|
|
46
|
+
echo "latest_tag=$latest_tag" >> $GITHUB_ENV
|
|
47
|
+
echo "minor_tag=$minor_tag" >> $GITHUB_ENV
|
|
48
|
+
# Some examples
|
|
49
|
+
# https://github.com/squidfunk/mkdocs-material/discussions/6546
|
|
50
|
+
# https://github.com/arduino/arduino-cli/blob/master/.github/workflows/deploy-cobra-mkdocs-versioned-poetry.yml
|
|
51
|
+
# https://blog.grosdouli.dev/blog/mkdocs-mike-integration#setup-github-workflows
|
|
52
|
+
- run: mike deploy --update-aliases --push --title $latest_tag $minor_tag latest
|
|
53
|
+
env:
|
|
54
|
+
MKDOCS_GIT_COMMITTERS_APIKEY : ${{ secrets.MKDOCS_GIT_COMMITTERS_APIKEY }}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# This workflow runs on every commit to main and publishes a development version of the documentation to the website.
|
|
2
|
+
name: Publish dev docs
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
env:
|
|
8
|
+
ENABLED_GIT_REVISION_DATE: true
|
|
9
|
+
ENABLED_GIT_COMMITTERS: true
|
|
10
|
+
DOCS_PRERELEASE: true
|
|
11
|
+
permissions:
|
|
12
|
+
contents: write
|
|
13
|
+
jobs:
|
|
14
|
+
deploy:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
environment: build-docs
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
with:
|
|
20
|
+
fetch-depth: 0 # Needed for git-revision-date-localized plugin
|
|
21
|
+
- name: Configure Git Credentials
|
|
22
|
+
run: |
|
|
23
|
+
git config user.name github-actions[bot]
|
|
24
|
+
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
|
|
25
|
+
- uses: actions/setup-python@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: 3.x
|
|
28
|
+
cache: "pip"
|
|
29
|
+
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
|
|
30
|
+
- uses: actions/cache@v4
|
|
31
|
+
with:
|
|
32
|
+
key: mkdocs-material-${{ env.cache_id }}
|
|
33
|
+
path: .cache
|
|
34
|
+
restore-keys: |
|
|
35
|
+
mkdocs-material-
|
|
36
|
+
- run: pip install .[docs]
|
|
37
|
+
# Some examples
|
|
38
|
+
# https://github.com/squidfunk/mkdocs-material/discussions/6546
|
|
39
|
+
# https://github.com/arduino/arduino-cli/blob/master/.github/workflows/deploy-cobra-mkdocs-versioned-poetry.yml
|
|
40
|
+
# https://blog.grosdouli.dev/blog/mkdocs-mike-integration#setup-github-workflows
|
|
41
|
+
- run: mike deploy --push dev
|
|
42
|
+
env:
|
|
43
|
+
MKDOCS_GIT_COMMITTERS_APIKEY: ${{ secrets.MKDOCS_GIT_COMMITTERS_APIKEY }}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# This workflow runs on pull requests and tests that building the docs works
|
|
2
|
+
name: Test documentation builds
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: ["*"]
|
|
6
|
+
jobs:
|
|
7
|
+
run:
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
steps:
|
|
10
|
+
- uses: actions/checkout@v4
|
|
11
|
+
- uses: actions/setup-python@v5
|
|
12
|
+
with:
|
|
13
|
+
python-version: 3.x
|
|
14
|
+
cache: "pip"
|
|
15
|
+
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
|
|
16
|
+
- uses: actions/cache@v4
|
|
17
|
+
with:
|
|
18
|
+
key: mkdocs-material-${{ env.cache_id }}
|
|
19
|
+
path: .cache
|
|
20
|
+
restore-keys: |
|
|
21
|
+
mkdocs-material-
|
|
22
|
+
- run: pip install .[docs]
|
|
23
|
+
- run: mkdocs build --strict
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
3
|
+
# Ruff version.
|
|
4
|
+
rev: v0.12.7
|
|
5
|
+
hooks:
|
|
6
|
+
# Run the linter.
|
|
7
|
+
- id: ruff-check
|
|
8
|
+
args: [ --fix ]
|
|
9
|
+
# Run the formatter.
|
|
10
|
+
- id: ruff-format
|
|
11
|
+
- repo: https://github.com/adamtheturtle/doccmd-pre-commit
|
|
12
|
+
rev: v2025.4.8
|
|
13
|
+
hooks:
|
|
14
|
+
- id: doccmd
|
|
15
|
+
args: ["--language", "python", "--no-pad-file", "--command", "ruff format", "docs/"]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
// Use IntelliSense to learn about possible attributes.
|
|
3
|
+
// Hover to view descriptions of existing attributes.
|
|
4
|
+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
5
|
+
"version": "0.2.0",
|
|
6
|
+
"configurations": [
|
|
7
|
+
{
|
|
8
|
+
"name": "Debug mkdocs",
|
|
9
|
+
"type": "debugpy",
|
|
10
|
+
"request": "launch",
|
|
11
|
+
"module": "mkdocs",
|
|
12
|
+
"args": [
|
|
13
|
+
"serve"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyoframe
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.0a0
|
|
4
4
|
Summary: Blazing fast linear program interface
|
|
5
5
|
Author-email: Bravos Power <dev@bravospower.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -20,30 +20,37 @@ Requires-Dist: numpy
|
|
|
20
20
|
Requires-Dist: pyarrow
|
|
21
21
|
Requires-Dist: pandas
|
|
22
22
|
Requires-Dist: pyoptinterface<1,>=0.4.1
|
|
23
|
-
Provides-Extra: dev
|
|
24
|
-
Requires-Dist: ruff; extra == "dev"
|
|
25
|
-
Requires-Dist: polars>=1.30.0; extra == "dev"
|
|
26
|
-
Requires-Dist: bumpver; extra == "dev"
|
|
27
|
-
Requires-Dist: pip-tools; extra == "dev"
|
|
28
|
-
Requires-Dist: pytest; extra == "dev"
|
|
29
|
-
Requires-Dist: pytest-cov; extra == "dev"
|
|
30
|
-
Requires-Dist: pre-commit; extra == "dev"
|
|
31
|
-
Requires-Dist: gurobipy; extra == "dev"
|
|
32
|
-
Requires-Dist: highsbox; extra == "dev"
|
|
33
|
-
Requires-Dist: coverage; extra == "dev"
|
|
34
|
-
Requires-Dist: ipykernel; extra == "dev"
|
|
35
|
-
Requires-Dist: pytest-markdown-docs; extra == "dev"
|
|
36
|
-
Requires-Dist: mkdocs-material==9.*; extra == "dev"
|
|
37
|
-
Requires-Dist: mkdocstrings[python]; extra == "dev"
|
|
38
|
-
Requires-Dist: mkdocs-git-revision-date-localized-plugin; extra == "dev"
|
|
39
|
-
Requires-Dist: mkdocs-git-committers-plugin-2; extra == "dev"
|
|
40
|
-
Requires-Dist: mkdocs-gen-files; extra == "dev"
|
|
41
|
-
Requires-Dist: mkdocs-section-index; extra == "dev"
|
|
42
|
-
Requires-Dist: mkdocs-literate-nav; extra == "dev"
|
|
43
|
-
Requires-Dist: mkdocs-table-reader-plugin; extra == "dev"
|
|
44
|
-
Requires-Dist: markdown-hide-code>=0.1.1; extra == "dev"
|
|
45
23
|
Provides-Extra: highs
|
|
46
24
|
Requires-Dist: highsbox; extra == "highs"
|
|
25
|
+
Provides-Extra: ipopt
|
|
26
|
+
Requires-Dist: pyoptinterface[nlp]; extra == "ipopt"
|
|
27
|
+
Requires-Dist: llvmlite<=0.44.0; extra == "ipopt"
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: ruff==0.12.11; extra == "dev"
|
|
30
|
+
Requires-Dist: polars>=1.32.3; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest==8.4.1; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest-cov==6.2.1; extra == "dev"
|
|
33
|
+
Requires-Dist: sybil[pytest]==9.2.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pre-commit==4.3.0; extra == "dev"
|
|
35
|
+
Requires-Dist: gurobipy==12.0.3; extra == "dev"
|
|
36
|
+
Requires-Dist: coverage==7.10.6; extra == "dev"
|
|
37
|
+
Requires-Dist: ipykernel==6.30.1; extra == "dev"
|
|
38
|
+
Requires-Dist: highsbox; extra == "dev"
|
|
39
|
+
Requires-Dist: pyoptinterface[nlp]; extra == "dev"
|
|
40
|
+
Requires-Dist: llvmlite<=0.44.0; extra == "dev"
|
|
41
|
+
Provides-Extra: docs
|
|
42
|
+
Requires-Dist: mkdocs-material~=9.6.18; extra == "docs"
|
|
43
|
+
Requires-Dist: mkdocstrings[python]~=0.30.0; extra == "docs"
|
|
44
|
+
Requires-Dist: mkdocs-git-revision-date-localized-plugin~=1.4.7; extra == "docs"
|
|
45
|
+
Requires-Dist: mkdocs-git-committers-plugin-2~=2.5.0; extra == "docs"
|
|
46
|
+
Requires-Dist: mkdocs-gen-files~=0.5.0; extra == "docs"
|
|
47
|
+
Requires-Dist: mkdocs-section-index~=0.3.10; extra == "docs"
|
|
48
|
+
Requires-Dist: mkdocs-awesome-nav~=3.1.2; extra == "docs"
|
|
49
|
+
Requires-Dist: doccmd==2025.4.8; extra == "docs"
|
|
50
|
+
Requires-Dist: mkdocs-table-reader-plugin~=3.1.0; extra == "docs"
|
|
51
|
+
Requires-Dist: markdown-katex==202406.1035; extra == "docs"
|
|
52
|
+
Requires-Dist: mike==2.1.3; extra == "docs"
|
|
53
|
+
Requires-Dist: ruff==0.12.11; extra == "docs"
|
|
47
54
|
Dynamic: license-file
|
|
48
55
|
|
|
49
56
|
# Pyoframe: Fast and low-memory linear programming models
|
|
@@ -56,11 +63,11 @@ Dynamic: license-file
|
|
|
56
63
|
[](https://github.com/Bravos-Power/pyoframe/issues?q=is%3Aopen+is%3Aissue+label%3Abug)
|
|
57
64
|
|
|
58
65
|
|
|
59
|
-
A library to rapidly and memory-efficiently formulate large and sparse optimization models using Pandas or Polars
|
|
66
|
+
A library to rapidly and memory-efficiently formulate large and sparse optimization models using Pandas or Polars DataFrames.
|
|
60
67
|
|
|
61
68
|
## **[Documentation](https://bravos-power.github.io/pyoframe/)**
|
|
62
69
|
|
|
63
|
-
[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/).
|
|
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).
|
|
64
71
|
|
|
65
72
|
|
|
66
73
|
## Acknowledgments
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
[](https://github.com/Bravos-Power/pyoframe/issues?q=is%3Aopen+is%3Aissue+label%3Abug)
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
A library to rapidly and memory-efficiently formulate large and sparse optimization models using Pandas or Polars
|
|
11
|
+
A library to rapidly and memory-efficiently formulate large and sparse optimization models using Pandas or Polars DataFrames.
|
|
12
12
|
|
|
13
13
|
## **[Documentation](https://bravos-power.github.io/pyoframe/)**
|
|
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/).
|
|
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).
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
## Acknowledgments
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""File related to setting up pytest."""
|
|
2
|
+
|
|
3
|
+
import doctest
|
|
4
|
+
import os
|
|
5
|
+
import warnings
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
import polars as pl
|
|
9
|
+
import pytest
|
|
10
|
+
|
|
11
|
+
import pyoframe as pf
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _setup_before_each_test(doctest_namespace):
|
|
15
|
+
doctest_namespace["pf"] = pf
|
|
16
|
+
pf.Config.reset_defaults()
|
|
17
|
+
pf.Config.enable_is_duplicated_expression_safety_check = True
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@pytest.fixture(autouse=True)
|
|
21
|
+
def _setup_fixture(doctest_namespace):
|
|
22
|
+
_setup_before_each_test(doctest_namespace)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def pytest_collection_modifyitems(items):
|
|
26
|
+
"""Exclude certain paths from contributing to the test coverage.
|
|
27
|
+
|
|
28
|
+
Specifically, the integration tests and documentation code snippets are not
|
|
29
|
+
counted towards the coverage metrics because they're not rigorous enough.
|
|
30
|
+
|
|
31
|
+
See:
|
|
32
|
+
- https://docs.pytest.org/en/stable/reference/reference.html#pytest.hookspec.pytest_collection_modifyitems
|
|
33
|
+
- https://stackoverflow.com/questions/60608511/pytest-cov-dont-count-coverage-for-the-directory-of-integration-tests
|
|
34
|
+
"""
|
|
35
|
+
root_dir = Path(__file__).parent
|
|
36
|
+
no_coverage_paths = (
|
|
37
|
+
root_dir / "docs",
|
|
38
|
+
root_dir / "tests" / "test_examples.py",
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
for item in items:
|
|
42
|
+
test_path = Path(item.fspath)
|
|
43
|
+
if any(test_path.is_relative_to(p) for p in no_coverage_paths):
|
|
44
|
+
item.add_marker(pytest.mark.no_cover)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@pytest.fixture(scope="module")
|
|
48
|
+
def markdown_setup_fixture_module():
|
|
49
|
+
cwd = os.getcwd()
|
|
50
|
+
yield
|
|
51
|
+
os.chdir(cwd)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@pytest.fixture
|
|
55
|
+
def markdown_setup_fixture():
|
|
56
|
+
pl.Config.restore_defaults()
|
|
57
|
+
pl.Config.set_tbl_hide_dataframe_shape(True)
|
|
58
|
+
yield
|
|
59
|
+
pl.Config.set_tbl_hide_dataframe_shape(False)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
SYBIL = False
|
|
63
|
+
try:
|
|
64
|
+
from sybil import Sybil
|
|
65
|
+
from sybil.evaluators.doctest import NUMBER
|
|
66
|
+
from sybil.parsers.markdown import (
|
|
67
|
+
ClearNamespaceParser,
|
|
68
|
+
PythonCodeBlockParser,
|
|
69
|
+
SkipParser,
|
|
70
|
+
)
|
|
71
|
+
from sybil.parsers.rest import DocTestParser
|
|
72
|
+
|
|
73
|
+
SYBIL = True
|
|
74
|
+
except ImportError:
|
|
75
|
+
# Sybil is not installed, so we won't collect markdown files.
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
if SYBIL:
|
|
79
|
+
pytest_collect_file = Sybil(
|
|
80
|
+
parsers=[
|
|
81
|
+
PythonCodeBlockParser(),
|
|
82
|
+
SkipParser(),
|
|
83
|
+
ClearNamespaceParser(),
|
|
84
|
+
DocTestParser(
|
|
85
|
+
optionflags=doctest.ELLIPSIS | NUMBER | doctest.NORMALIZE_WHITESPACE
|
|
86
|
+
),
|
|
87
|
+
],
|
|
88
|
+
patterns=["*.md"],
|
|
89
|
+
setup=_setup_before_each_test,
|
|
90
|
+
fixtures=["markdown_setup_fixture", "markdown_setup_fixture_module"],
|
|
91
|
+
).pytest()
|
|
92
|
+
else:
|
|
93
|
+
warnings.warn("Sybil not installed. Documentation tests will not run.")
|
|
@@ -0,0 +1,51 @@
|
|
|
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
|
+
4. Run `pytest` to make sure everything is working. The only errors you should see are those related to a solver not being installed. If not, [open an issue](https://github.com/Bravos-Power/pyoframe/issues/new)!
|
|
27
|
+
|
|
28
|
+
## Writing documentation
|
|
29
|
+
|
|
30
|
+
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). Additionally, all Python code blocks in Markdown files are tested using Sybil. To properly setup the tests refer to this [Sybil documentation](https://sybil.readthedocs.io/en/latest/markdown.html#code-blocks).
|
|
31
|
+
|
|
32
|
+
## Helpful commands
|
|
33
|
+
|
|
34
|
+
- `pytest`: Runs all the tests. If you'd like to generate coverage information just add the flag `--cov`.
|
|
35
|
+
- `mkdocs serve`: Generates the documentation locally. Navigate to [`http://127.0.0.1:8000/pyoframe/`](http://127.0.0.1:8000/pyoframe/) to check it out.
|
|
36
|
+
- `coverage html`: Generate a webpage to view the coverage information generated after having run `pytest --cov`.
|
|
37
|
+
- `python -m tests.test_examples`: Regenerate the files in the `results` folder of an example (e.g. `tests/examples/sudoku/results/**`). You should only run this if the result files need to be regenerated, for example, if model variable names have changed.
|
|
38
|
+
- `ruff check`: Ensures all the linter tests pass
|
|
39
|
+
- `ruff format`: Ensures the code is properly formatted (this is run upon commit if you've installed the pre-commit hooks)
|
|
40
|
+
- `doccmd --language=python --no-pad-file --command="ruff format" docs/`: to format the code in the documentation.
|
|
41
|
+
- `mike serve` to see a local version of the documentation with the version selector.
|
|
42
|
+
|
|
43
|
+
## Additional tips
|
|
44
|
+
|
|
45
|
+
- 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`).
|
|
46
|
+
|
|
47
|
+
## Details for repository maintainers
|
|
48
|
+
|
|
49
|
+
### Expired Gurobi License
|
|
50
|
+
|
|
51
|
+
We use a Gurobi license to run our tests. If the tests fail an give a license expired error, generate a new one and copy the contents of the `guorbi.lic` file into the `GUROBI_WLS` Github secret (Settings -> Secrets and variables -> actions).
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Diet problem
|
|
2
|
+
|
|
3
|
+
## Problem statement
|
|
4
|
+
|
|
5
|
+
Given a list of potential foods, their costs, and their availability ([`foods.csv`](https://github.com/Bravos-Power/pyoframe/blob/main/tests/examples/diet_problem/input_data/foods.csv)), and a list of the nutrients (e.g., protein, fats, etc.) contained in each food ([`foods_to_nutrients.csv`](https://github.com/Bravos-Power/pyoframe/blob/main/tests/examples/diet_problem/input_data/foods_to_nutrients.csv)), how can you satisfy your dietary requirements ([`nutrients.csv`](https://github.com/Bravos-Power/pyoframe/blob/main/tests/examples/diet_problem/input_data/nutrients.csv)) while minimizing total costs?
|
|
6
|
+
|
|
7
|
+
## Model
|
|
8
|
+
|
|
9
|
+
<!-- invisible-code-block: python
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
os.chdir(os.path.join(os.getcwd(), "tests/examples/diet_problem/input_data"))
|
|
13
|
+
-->
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
import pandas as pd
|
|
17
|
+
|
|
18
|
+
import pyoframe as pf
|
|
19
|
+
|
|
20
|
+
# Import data
|
|
21
|
+
food = pd.read_csv("foods.csv")
|
|
22
|
+
nutrients = pd.read_csv("nutrients.csv")
|
|
23
|
+
food_nutrients = pd.read_csv("foods_to_nutrients.csv")
|
|
24
|
+
|
|
25
|
+
# Construct model
|
|
26
|
+
m = pf.Model()
|
|
27
|
+
m.Buy = pf.Variable(food["food"], lb=0, ub=food[["food", "stock"]])
|
|
28
|
+
|
|
29
|
+
nutrient_intake = (m.Buy * food_nutrients).sum_by("category")
|
|
30
|
+
m.min_nutrients = (
|
|
31
|
+
nutrients[["category", "min"]] <= nutrient_intake.drop_unmatched() # (1)!
|
|
32
|
+
)
|
|
33
|
+
m.max_nutrients = nutrient_intake.drop_unmatched() <= nutrients[["category", "max"]]
|
|
34
|
+
|
|
35
|
+
total_cost = (m.Buy * food[["food", "cost"]]).sum()
|
|
36
|
+
m.minimize = total_cost
|
|
37
|
+
|
|
38
|
+
# Solve model
|
|
39
|
+
m.optimize()
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
1. `.drop_unmatched()` ensures that if `min_nutrient` is `null` for certain foods, no constraint will be created for those foods. [Learn more](../learn/concepts/special-functions.md#drop_unmatched-and-keep_unmatched)
|
|
43
|
+
|
|
44
|
+
So the solution is...
|
|
45
|
+
|
|
46
|
+
```pycon
|
|
47
|
+
>>> total_cost.evaluate()
|
|
48
|
+
12.060249999999998
|
|
49
|
+
>>> m.Buy.solution
|
|
50
|
+
┌───────────┬──────────┐
|
|
51
|
+
│ food ┆ solution │
|
|
52
|
+
│ --- ┆ --- │
|
|
53
|
+
│ str ┆ f64 │
|
|
54
|
+
╞═══════════╪══════════╡
|
|
55
|
+
│ hamburger ┆ 0.555263 │
|
|
56
|
+
│ chicken ┆ 0.0 │
|
|
57
|
+
│ hot_dog ┆ 0.0 │
|
|
58
|
+
│ fries ┆ 0.0 │
|
|
59
|
+
│ macaroni ┆ 0.0 │
|
|
60
|
+
│ pizza ┆ 0.0 │
|
|
61
|
+
│ salad ┆ 0.0 │
|
|
62
|
+
│ milk ┆ 6.8 │
|
|
63
|
+
│ ice_cream ┆ 2.909211 │
|
|
64
|
+
└───────────┴──────────┘
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Not a very balanced diet :thinking:.
|