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.
Files changed (257) hide show
  1. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.github/actions/setup_optimizers_linux/action.yml +25 -20
  2. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.github/workflows/ci.yml +7 -3
  3. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.github/workflows/format.yml +1 -0
  4. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.github/workflows/lines_changed_counter.yml +2 -0
  5. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.github/workflows/lint.yml +1 -0
  6. pyoframe-1.0.0a0/.github/workflows/publish_doc.yml +54 -0
  7. pyoframe-1.0.0a0/.github/workflows/publish_doc_dev.yml +43 -0
  8. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.github/workflows/publish_to_pypi.yml +1 -0
  9. pyoframe-1.0.0a0/.github/workflows/test_doc.yml +23 -0
  10. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.gitignore +1 -1
  11. pyoframe-1.0.0a0/.pre-commit-config.yaml +15 -0
  12. pyoframe-1.0.0a0/.vscode/launch.json +17 -0
  13. pyoframe-1.0.0a0/.vscode/settings.json +14 -0
  14. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/PKG-INFO +32 -25
  15. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/README.md +2 -2
  16. pyoframe-1.0.0a0/conftest.py +93 -0
  17. pyoframe-1.0.0a0/docs/.nav.yml +13 -0
  18. pyoframe-1.0.0a0/docs/contribute/index.md +51 -0
  19. pyoframe-1.0.0a0/docs/examples/.nav.yml +6 -0
  20. pyoframe-1.0.0a0/docs/examples/diet.md +68 -0
  21. pyoframe-1.0.0a0/docs/examples/facility_location.md +73 -0
  22. pyoframe-1.0.0a0/docs/examples/index.md +8 -0
  23. pyoframe-1.0.0a0/docs/examples/portfolio_optimization.md +66 -0
  24. pyoframe-1.0.0a0/docs/examples/production.md +60 -0
  25. pyoframe-1.0.0a0/docs/index.md +78 -0
  26. pyoframe-1.0.0a0/docs/javascripts/feedback.js +26 -0
  27. pyoframe-1.0.0a0/docs/learn/advanced-concepts/.nav.yml +6 -0
  28. pyoframe-0.2.0/docs/learn/03_concepts/01_pyoframe-datastructure.md → pyoframe-1.0.0a0/docs/learn/advanced-concepts/datastructure.md +2 -2
  29. pyoframe-1.0.0a0/docs/learn/advanced-concepts/internals.md +19 -0
  30. pyoframe-1.0.0a0/docs/learn/advanced-concepts/performance.md +36 -0
  31. pyoframe-1.0.0a0/docs/learn/advanced-concepts/quadratics.md +33 -0
  32. pyoframe-1.0.0a0/docs/learn/concepts/.nav.yml +4 -0
  33. pyoframe-1.0.0a0/docs/learn/concepts/building-blocks.md +17 -0
  34. 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
  35. pyoframe-1.0.0a0/docs/learn/concepts/special-functions.md +227 -0
  36. pyoframe-1.0.0a0/docs/learn/get-started/.nav.yml +4 -0
  37. pyoframe-1.0.0a0/docs/learn/get-started/basic-example/example-with-dimensions.md +187 -0
  38. pyoframe-1.0.0a0/docs/learn/get-started/basic-example/example.md +61 -0
  39. pyoframe-1.0.0a0/docs/learn/get-started/basic-example/food_data.csv +3 -0
  40. pyoframe-1.0.0a0/docs/learn/get-started/installation.md +68 -0
  41. {pyoframe-0.2.0/docs/learn/01_getting-started → pyoframe-1.0.0a0/docs/learn/get-started}/power_grid_example.ipynb +3 -3
  42. pyoframe-1.0.0a0/docs/learn/migrate/v1.0.md +105 -0
  43. pyoframe-1.0.0a0/docs/overrides/main.html +12 -0
  44. pyoframe-1.0.0a0/docs/overrides/partials/comments.html +46 -0
  45. pyoframe-1.0.0a0/docs/reference/.nav.yml +2 -0
  46. pyoframe-1.0.0a0/docs/reference/index.md +7 -0
  47. pyoframe-1.0.0a0/docs/reference/pandas.DataFrame.to_expr.md +3 -0
  48. pyoframe-1.0.0a0/docs/reference/polars.DataFrame.to_expr.md +3 -0
  49. pyoframe-1.0.0a0/docs/reference/pyoframe.Config.md +12 -0
  50. pyoframe-1.0.0a0/docs/stylesheets/extra.css +4 -0
  51. pyoframe-1.0.0a0/docs/why-pyoframe/index.md +11 -0
  52. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/docs/why-pyoframe/pyoframe-performance.ipynb +1 -1
  53. pyoframe-1.0.0a0/giscus.json +3 -0
  54. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/mkdocs.yml +61 -5
  55. pyoframe-1.0.0a0/pyproject.toml +111 -0
  56. pyoframe-1.0.0a0/scripts/archive/benchmark_assign_ids_constraints.py +226 -0
  57. pyoframe-1.0.0a0/scripts/archive/benchmark_assign_ids_constraints_2.py +158 -0
  58. pyoframe-1.0.0a0/scripts/archive/benchmark_assign_ids_variables.py +72 -0
  59. pyoframe-1.0.0a0/scripts/archive/benchmark_attr_performance.py +73 -0
  60. pyoframe-1.0.0a0/scripts/generate_api_reference.py +34 -0
  61. pyoframe-1.0.0a0/scripts/griffe_extensions.py +25 -0
  62. pyoframe-1.0.0a0/src/pyoframe/__init__.py +35 -0
  63. pyoframe-1.0.0a0/src/pyoframe/_arithmetic.py +547 -0
  64. pyoframe-1.0.0a0/src/pyoframe/_constants.py +416 -0
  65. pyoframe-1.0.0a0/src/pyoframe/_core.py +2575 -0
  66. pyoframe-1.0.0a0/src/pyoframe/_model.py +578 -0
  67. pyoframe-1.0.0a0/src/pyoframe/_model_element.py +175 -0
  68. pyoframe-1.0.0a0/src/pyoframe/_monkey_patch.py +80 -0
  69. pyoframe-0.2.0/src/pyoframe/objective.py → pyoframe-1.0.0a0/src/pyoframe/_objective.py +49 -14
  70. pyoframe-0.2.0/src/pyoframe/util.py → pyoframe-1.0.0a0/src/pyoframe/_utils.py +106 -126
  71. pyoframe-1.0.0a0/src/pyoframe/_version.py +34 -0
  72. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/src/pyoframe.egg-info/PKG-INFO +32 -25
  73. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/src/pyoframe.egg-info/SOURCES.txt +70 -41
  74. pyoframe-1.0.0a0/src/pyoframe.egg-info/requires.txt +40 -0
  75. pyoframe-1.0.0a0/tests/conftest.py +41 -0
  76. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/cutting_stock_problem/model.py +8 -8
  77. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/model.py +9 -13
  78. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/model_gurobipy.py +1 -3
  79. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_location/model.py +14 -9
  80. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/model.py +12 -9
  81. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/model_gurobipy.py +14 -11
  82. pyoframe-1.0.0a0/tests/examples/portfolio_optim/input_data/assets.csv +6 -0
  83. pyoframe-1.0.0a0/tests/examples/portfolio_optim/input_data/covariance.csv +26 -0
  84. pyoframe-1.0.0a0/tests/examples/portfolio_optim/input_data/portfolio_params.csv +3 -0
  85. pyoframe-1.0.0a0/tests/examples/portfolio_optim/model.py +195 -0
  86. pyoframe-1.0.0a0/tests/examples/portfolio_optim/results/con_min_return.csv +2 -0
  87. pyoframe-1.0.0a0/tests/examples/portfolio_optim/results/con_weights_sum.csv +2 -0
  88. pyoframe-1.0.0a0/tests/examples/portfolio_optim/results/objective.csv +2 -0
  89. pyoframe-1.0.0a0/tests/examples/portfolio_optim/results/problem-gurobi-machine.lp +18 -0
  90. pyoframe-1.0.0a0/tests/examples/portfolio_optim/results/problem-gurobi-pretty.lp +24 -0
  91. pyoframe-1.0.0a0/tests/examples/portfolio_optim/results/solution-gurobi-machine.sol +7 -0
  92. pyoframe-1.0.0a0/tests/examples/portfolio_optim/results/solution-gurobi-pretty.sol +7 -0
  93. pyoframe-1.0.0a0/tests/examples/portfolio_optim/results/weight.csv +6 -0
  94. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/model.py +10 -7
  95. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/model.py +15 -12
  96. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/model.py +10 -7
  97. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/test_arithmetic.py +175 -108
  98. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/test_examples.py +122 -69
  99. pyoframe-1.0.0a0/tests/test_io.py +173 -0
  100. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/test_model.py +40 -15
  101. pyoframe-1.0.0a0/tests/test_names.py +77 -0
  102. pyoframe-1.0.0a0/tests/test_objective.py +26 -0
  103. pyoframe-1.0.0a0/tests/test_solver.py +295 -0
  104. pyoframe-1.0.0a0/tests/util.py +81 -0
  105. pyoframe-0.2.0/.github/workflows/publish_doc.yml +0 -33
  106. pyoframe-0.2.0/.pre-commit-config.yaml +0 -9
  107. pyoframe-0.2.0/.vscode/settings.json +0 -7
  108. pyoframe-0.2.0/conftest.py +0 -38
  109. pyoframe-0.2.0/docs/SUMMARY.md +0 -4
  110. pyoframe-0.2.0/docs/contribute/index.md +0 -36
  111. pyoframe-0.2.0/docs/index.md +0 -53
  112. pyoframe-0.2.0/docs/learn/01_getting-started/01_installation.md +0 -26
  113. pyoframe-0.2.0/docs/learn/01_getting-started/02_build-simple-model.md +0 -196
  114. pyoframe-0.2.0/docs/learn/01_getting-started/04_building_blocks.md +0 -17
  115. pyoframe-0.2.0/docs/learn/01_getting-started/05_special_functions.md +0 -18
  116. pyoframe-0.2.0/docs/learn/01_getting-started/SUMMARY.md +0 -5
  117. pyoframe-0.2.0/docs/learn/01_getting-started/inputs/food_data.csv +0 -3
  118. pyoframe-0.2.0/docs/learn/02_tutorials/index.md +0 -5
  119. pyoframe-0.2.0/docs/learn/03_concepts/02_performance_tips.md +0 -13
  120. pyoframe-0.2.0/docs/learn/03_concepts/03_quadratic_expressions.md +0 -41
  121. pyoframe-0.2.0/docs/learn/03_concepts/SUMMARY.md +0 -4
  122. pyoframe-0.2.0/docs/learn/04_examples/index.md +0 -8
  123. pyoframe-0.2.0/docs/learn/SUMMARY.md +0 -4
  124. pyoframe-0.2.0/docs/learn/index.md +0 -44
  125. pyoframe-0.2.0/docs/overrides/home.html +0 -4
  126. pyoframe-0.2.0/docs/why-pyoframe/SUMMARY.md +0 -5
  127. pyoframe-0.2.0/docs/why-pyoframe/index.md +0 -14
  128. pyoframe-0.2.0/docs/why-pyoframe/why-pyoframe.md +0 -1
  129. pyoframe-0.2.0/pyproject.toml +0 -70
  130. pyoframe-0.2.0/scripts/gen_ref_pages.py +0 -35
  131. pyoframe-0.2.0/src/pyoframe/__init__.py +0 -28
  132. pyoframe-0.2.0/src/pyoframe/_arithmetic.py +0 -441
  133. pyoframe-0.2.0/src/pyoframe/_version.py +0 -21
  134. pyoframe-0.2.0/src/pyoframe/constants.py +0 -140
  135. pyoframe-0.2.0/src/pyoframe/core.py +0 -1794
  136. pyoframe-0.2.0/src/pyoframe/model.py +0 -408
  137. pyoframe-0.2.0/src/pyoframe/model_element.py +0 -184
  138. pyoframe-0.2.0/src/pyoframe/monkey_patch.py +0 -54
  139. pyoframe-0.2.0/src/pyoframe.egg-info/requires.txt +0 -31
  140. pyoframe-0.2.0/tests/conftest.py +0 -19
  141. pyoframe-0.2.0/tests/examples/facility_problem/results/con_max_capacity.csv +0 -6
  142. pyoframe-0.2.0/tests/examples/facility_problem/results/con_meet_demand.csv +0 -5
  143. pyoframe-0.2.0/tests/examples/pumped_storage/results/initial_storage_level.csv +0 -2
  144. pyoframe-0.2.0/tests/examples/pumped_storage/results/intermediate_storage_level.csv +0 -1461
  145. pyoframe-0.2.0/tests/examples/pumped_storage/results/pump_and_turbine_xor.csv +0 -1461
  146. pyoframe-0.2.0/tests/test_io.py +0 -137
  147. pyoframe-0.2.0/tests/test_operations.py +0 -53
  148. pyoframe-0.2.0/tests/test_solver.py +0 -208
  149. pyoframe-0.2.0/tests/util.py +0 -53
  150. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.gitattributes +0 -0
  151. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.github/CODEOWNERS +0 -0
  152. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.github/actions/setup_optimizers_macos/action.yml +0 -0
  153. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/.github/actions/setup_optimizers_windows/action.yml +0 -0
  154. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/CHANGELOG.md +0 -0
  155. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/LICENSE +0 -0
  156. /pyoframe-0.2.0/docs/learn/03_concepts/04_troubleshooting.md → /pyoframe-1.0.0a0/docs/learn/advanced-concepts/troubleshooting.md +0 -0
  157. {pyoframe-0.2.0/docs/learn/01_getting-started/inputs → pyoframe-1.0.0a0/docs/learn/get-started/basic-example}/foods.csv +0 -0
  158. {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
  159. {pyoframe-0.2.0/docs/learn/01_getting-started/inputs → pyoframe-1.0.0a0/docs/learn/get-started/basic-example}/nutrients.csv +0 -0
  160. {pyoframe-0.2.0/docs/learn/01_getting-started/inputs → pyoframe-1.0.0a0/docs/learn/get-started/basic-example}/results.csv +0 -0
  161. {pyoframe-0.2.0/docs/learn/01_getting-started → pyoframe-1.0.0a0/docs/learn/get-started}/three-bus.png +0 -0
  162. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/docs/overrides/partials/actions.html +0 -0
  163. /pyoframe-0.2.0/docs/why-pyoframe/benchmarks.md → /pyoframe-1.0.0a0/docs/overrides/partials/integrations/analytics/custom.html +0 -0
  164. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/docs/why-pyoframe/data_py.parquet +0 -0
  165. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/docs/why-pyoframe/gen_py.parquet +0 -0
  166. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/docs/why-pyoframe/three-bus-four-gen.png +0 -0
  167. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/setup.cfg +0 -0
  168. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/src/pyoframe.egg-info/dependency_links.txt +0 -0
  169. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/src/pyoframe.egg-info/top_level.txt +0 -0
  170. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/__init__.py +0 -0
  171. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/README.md +0 -0
  172. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/__init__.py +0 -0
  173. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/cutting_stock_problem/__init__.py +0 -0
  174. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/cutting_stock_problem/input_data/orders.csv +0 -0
  175. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/cutting_stock_problem/input_data/parameters.csv +0 -0
  176. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/cutting_stock_problem/results/objective.csv +0 -0
  177. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/cutting_stock_problem/results/problem-gurobi-machine.lp +0 -0
  178. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/cutting_stock_problem/results/problem-gurobi-pretty.lp +0 -0
  179. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/cutting_stock_problem/results/problem-highs-machine.lp +0 -0
  180. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/cutting_stock_problem/results/problem-highs-pretty.lp +0 -0
  181. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/README.md +0 -0
  182. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/__init__.py +0 -0
  183. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/input_data/foods.csv +0 -0
  184. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/input_data/foods_to_nutrients.csv +0 -0
  185. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/input_data/nutrients.csv +0 -0
  186. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/Buy.csv +0 -0
  187. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/Buy_ub.csv +0 -0
  188. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/max_nutrients.csv +0 -0
  189. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/min_nutrients.csv +0 -0
  190. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/objective.csv +0 -0
  191. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/problem-gurobi-machine.lp +0 -0
  192. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/problem-gurobi-pretty.lp +0 -0
  193. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/problem-highs-machine.lp +0 -0
  194. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/problem-highs-pretty.lp +0 -0
  195. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/solution-gurobi-machine.sol +0 -0
  196. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/solution-gurobi-pretty.sol +0 -0
  197. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/solution-highs-machine.sol +0 -0
  198. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/diet_problem/results/solution-highs-pretty.sol +0 -0
  199. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_location/__init__.py +0 -0
  200. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_location/results/objective.csv +0 -0
  201. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_location/results/problem-gurobi-machine.lp +0 -0
  202. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_location/results/problem-gurobi-pretty.lp +0 -0
  203. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/__init__.py +0 -0
  204. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/input_data/plants.csv +0 -0
  205. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/input_data/transport_costs.csv +0 -0
  206. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/input_data/wharehouses.csv +0 -0
  207. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/objective.csv +0 -0
  208. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/open.csv +0 -0
  209. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/problem-gurobi-machine.lp +0 -0
  210. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/problem-gurobi-pretty.lp +0 -0
  211. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/problem-highs-machine.lp +0 -0
  212. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/problem-highs-pretty.lp +0 -0
  213. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/solution-gurobi-machine.sol +0 -0
  214. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/solution-gurobi-pretty.sol +0 -0
  215. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/solution-highs-machine.sol +0 -0
  216. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/solution-highs-pretty.sol +0 -0
  217. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/facility_problem/results/transport.csv +0 -0
  218. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/__init__.py +0 -0
  219. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/input_data/machines_availability.csv +0 -0
  220. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/input_data/processing_times.csv +0 -0
  221. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/input_data/products_profit.csv +0 -0
  222. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/results/objective.csv +0 -0
  223. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/results/problem-gurobi-machine.lp +0 -0
  224. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/results/problem-gurobi-pretty.lp +0 -0
  225. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/results/problem-highs-machine.lp +0 -0
  226. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/results/problem-highs-pretty.lp +0 -0
  227. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/results/solution-gurobi-machine.sol +0 -0
  228. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/results/solution-gurobi-pretty.sol +0 -0
  229. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/results/solution-highs-machine.sol +0 -0
  230. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/results/solution-highs-pretty.sol +0 -0
  231. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/production_planning/results/solution.csv +0 -0
  232. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/README.md +0 -0
  233. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/__init__.py +0 -0
  234. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/input_data/elspot-prices_2021_hourly_eur.csv +0 -0
  235. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/Pump.csv +0 -0
  236. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/Storage_level.csv +0 -0
  237. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/Turb.csv +0 -0
  238. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/objective.csv +0 -0
  239. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/problem-gurobi-machine.lp +0 -0
  240. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/problem-gurobi-pretty.lp +0 -0
  241. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/problem-highs-machine.lp +0 -0
  242. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/problem-highs-pretty.lp +0 -0
  243. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/solution-gurobi-machine.sol +0 -0
  244. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/solution-gurobi-pretty.sol +0 -0
  245. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/solution-highs-machine.sol +0 -0
  246. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/pumped_storage/results/solution-highs-pretty.sol +0 -0
  247. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/__init__.py +0 -0
  248. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/input_data/initial_numbers.csv +0 -0
  249. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/results/problem-gurobi-machine.lp +0 -0
  250. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/results/problem-gurobi-pretty.lp +0 -0
  251. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/results/problem-highs-machine.lp +0 -0
  252. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/results/problem-highs-pretty.lp +0 -0
  253. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/results/solution-gurobi-machine.sol +0 -0
  254. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/results/solution-gurobi-pretty.sol +0 -0
  255. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/results/solution-highs-machine.sol +0 -0
  256. {pyoframe-0.2.0 → pyoframe-1.0.0a0}/tests/examples/sudoku/results/solution-highs-pretty.sol +0 -0
  257. {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 # wait 30 seconds (5x) if all licenses are already in use
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
- # - name: Setup IPOPT Installation
122
- # shell: bash
123
- # run: |
124
- # mkdir -p ~/ipopt
125
- # tar xfz ~/installers/idaes-solvers.tar.gz -C ~/ipopt
126
- # echo "PATH=${PATH}:${HOME}/ipopt" >> $GITHUB_ENV
127
- # echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${HOME}/ipopt" >> $GITHUB_ENV
128
- # ls ~/ipopt
129
- # - name: Test IPOPT
130
- # shell: bash
131
- # run: |
132
- # ipopt -v
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
@@ -1,3 +1,4 @@
1
+ # This workflow ensures that `ruff check` passes on pull requests.
1
2
  name: Check formatting with Ruff
2
3
 
3
4
  on: [pull_request]
@@ -1,3 +1,5 @@
1
+ # This workflow adds a comment to pull requests with the number of lines added, deleted, and changed.
2
+
1
3
  # MIT License
2
4
  # Copyright (c) 2021 Viacheslav Poturaev
3
5
  name: Comment on PR with lines changed
@@ -1,3 +1,4 @@
1
+ # This workflow ensures that `ruff format` passes on pull requests.
1
2
  name: Check linting with Ruff
2
3
  on: [pull_request]
3
4
 
@@ -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 }}
@@ -1,3 +1,4 @@
1
+ # This workflow runs when a new release is published and uploads the package to PyPI.
1
2
  name: PyPi Publishing
2
3
 
3
4
  on:
@@ -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
@@ -7,10 +7,10 @@ build
7
7
  tmp
8
8
  .coverage
9
9
  .cache
10
- docs/reference
11
10
  dist
12
11
  *.log
13
12
  site
14
13
  .idea
15
14
  src/pyoframe/_version.py
16
15
  htmlcov/
16
+ .snakemake
@@ -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
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "python.testing.unittestEnabled": false,
3
+ "python.testing.pytestEnabled": true,
4
+ "cSpell.words": [
5
+ "dataframes",
6
+ "Gurobi",
7
+ "highs",
8
+ "ipopt",
9
+ "Pyoframe"
10
+ ],
11
+ "python.testing.pytestArgs": [
12
+ "."
13
+ ]
14
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyoframe
3
- Version: 0.2.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
  [![Open Bugs](https://img.shields.io/github/issues-search/Bravos-Power/pyoframe?query=label%3Abug%20is%3Aopen&label=Open%20Bugs)](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 dataframes.
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
  [![Open Bugs](https://img.shields.io/github/issues-search/Bravos-Power/pyoframe?query=label%3Abug%20is%3Aopen&label=Open%20Bugs)](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 dataframes.
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,13 @@
1
+ sort:
2
+ by: filename
3
+ nav:
4
+ - Home: index.md
5
+ - Learn:
6
+ - learn/get-started
7
+ - learn/concepts
8
+ - learn/advanced-concepts
9
+ - learn/migrate
10
+ - examples
11
+ - reference
12
+ - why-pyoframe/index.md
13
+ - contribute
@@ -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,6 @@
1
+ nav:
2
+ - index.md
3
+ - diet.md
4
+ - production.md
5
+ - facility_location.md
6
+ - portfolio_optimization.md
@@ -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:.