parse-lp 2.5.0__tar.gz → 2.6.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. {parse_lp-2.5.0 → parse_lp-2.6.0}/Cargo.lock +2 -2
  2. {parse_lp-2.5.0 → parse_lp-2.6.0}/PKG-INFO +92 -2
  3. {parse_lp-2.5.0 → parse_lp-2.6.0}/README.md +91 -1
  4. parse_lp-2.6.0/parse_lp/__init__.py +73 -0
  5. {parse_lp-2.5.0 → parse_lp-2.6.0}/pyproject.toml +1 -0
  6. parse_lp-2.6.0/python/.gitignore +1 -0
  7. {parse_lp-2.5.0 → parse_lp-2.6.0}/python/Cargo.toml +1 -1
  8. {parse_lp-2.5.0 → parse_lp-2.6.0}/python/Makefile +3 -3
  9. {parse_lp-2.5.0 → parse_lp-2.6.0}/python/README.md +91 -1
  10. parse_lp-2.6.0/python/parse_lp/__init__.py +73 -0
  11. {parse_lp-2.5.0 → parse_lp-2.6.0}/python/python/CHANGELOG.md +7 -0
  12. parse_lp-2.6.0/python/src/lib.rs +485 -0
  13. {parse_lp-2.5.0 → parse_lp-2.6.0}/python/tests/test_lp_parser.py +33 -28
  14. parse_lp-2.6.0/python/tests/test_lp_writer.py +358 -0
  15. {parse_lp-2.5.0 → parse_lp-2.6.0}/python/uv.lock +30 -0
  16. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/Cargo.toml +1 -1
  17. parse_lp-2.6.0/rust/README.md +198 -0
  18. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/rust/CHANGELOG.md +7 -0
  19. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/context.rs +1 -1
  20. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/lib.rs +1 -10
  21. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/model.rs +2 -2
  22. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/parsers/constraint.rs +7 -4
  23. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/perf.rs +2 -0
  24. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/problem.rs +755 -13
  25. parse_lp-2.6.0/rust/src/writer.rs +562 -0
  26. parse_lp-2.5.0/parse_lp/__init__.py +0 -39
  27. parse_lp-2.5.0/python/parse_lp/__init__.py +0 -39
  28. parse_lp-2.5.0/python/src/lib.rs +0 -256
  29. parse_lp-2.5.0/rust/README.md +0 -120
  30. {parse_lp-2.5.0 → parse_lp-2.6.0}/Cargo.toml +0 -0
  31. {parse_lp-2.5.0 → parse_lp-2.6.0}/LICENSE-APACHE +0 -0
  32. {parse_lp-2.5.0 → parse_lp-2.6.0}/parse_lp/parse_lp.pyi +0 -0
  33. {parse_lp-2.5.0 → parse_lp-2.6.0}/parse_lp/py.typed +0 -0
  34. {parse_lp-2.5.0 → parse_lp-2.6.0}/python/.cargo/config.toml +0 -0
  35. {parse_lp-2.5.0 → parse_lp-2.6.0}/python/CHANGELOG.md +0 -0
  36. {parse_lp-2.5.0 → parse_lp-2.6.0}/python/LICENSE-APACHE +0 -0
  37. {parse_lp-2.5.0 → parse_lp-2.6.0}/python/MANIFEST.in +0 -0
  38. {parse_lp-2.5.0 → parse_lp-2.6.0}/python/parse_lp/parse_lp.pyi +0 -0
  39. {parse_lp-2.5.0 → parse_lp-2.6.0}/python/parse_lp/py.typed +0 -0
  40. {parse_lp-2.5.0 → parse_lp-2.6.0}/python/resources/afiro.lp +0 -0
  41. {parse_lp-2.5.0 → parse_lp-2.6.0}/python/tests/__init__.py +0 -0
  42. {parse_lp-2.5.0 → parse_lp-2.6.0}/python/tests/fixtures/afiro.lp +0 -0
  43. {parse_lp-2.5.0 → parse_lp-2.6.0}/python/tests/fixtures/minimize.lp +0 -0
  44. {parse_lp-2.5.0 → parse_lp-2.6.0}/python/tests/fixtures/simple.lp +0 -0
  45. {parse_lp-2.5.0 → parse_lp-2.6.0}/python/tests/test_csv_writer.py +0 -0
  46. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/CHANGELOG.md +0 -0
  47. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/benches/lp_parsing.rs +0 -0
  48. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/benches/parsing_micro.rs +0 -0
  49. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/1obj_1cons_all_variables_with_bounds.lp +0 -0
  50. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/2obj_2cons_all_variable_types.lp +0 -0
  51. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/2obj_2cons_only_binary_vars.lp +0 -0
  52. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/3obj_2cons.lp +0 -0
  53. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/AmericanSteelProblem.lp +0 -0
  54. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/BeerDistributionProblem.lp +0 -0
  55. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/ComputerPlantProblem.lp +0 -0
  56. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/WhiskasModel2.lp +0 -0
  57. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/afiro.lp +0 -0
  58. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/afiro_ext.lp +0 -0
  59. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/blank_lines.lp +0 -0
  60. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/boeing1.lp +0 -0
  61. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/boeing2.lp +0 -0
  62. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/carbon.png +0 -0
  63. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/complex_names.lp +0 -0
  64. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/corrupt.lp +0 -0
  65. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/cplex.lp +0 -0
  66. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/diet.lp +0 -0
  67. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/empty_bounds.lp +0 -0
  68. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/fit1d.lp +0 -0
  69. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/fit2d.lp +0 -0
  70. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/infile_comments.lp +0 -0
  71. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/infile_comments2.lp +0 -0
  72. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/invalid.lp +0 -0
  73. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/kb2.lp +0 -0
  74. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/limbo.lp +0 -0
  75. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/lol.lp +0 -0
  76. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/milo1.lp +0 -0
  77. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/missing_signs.lp +0 -0
  78. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/model.lp +0 -0
  79. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/model2.lp +0 -0
  80. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/mosek.lp +0 -0
  81. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/mosek_bounds.lp +0 -0
  82. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/no_end_section.lp +0 -0
  83. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/optional_labels.lp +0 -0
  84. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/output.lp +0 -0
  85. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/output2_1.lp +0 -0
  86. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/output2_2.lp +0 -0
  87. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/output2_3.lp +0 -0
  88. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/output2_4.lp +0 -0
  89. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/output_cplex_2.lp +0 -0
  90. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/pulp.lp +0 -0
  91. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/pulp2.lp +0 -0
  92. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/sc50a.lp +0 -0
  93. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/scientific_notation.lp +0 -0
  94. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/scientific_notation_2.lp +0 -0
  95. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/semi_continuous.lp +0 -0
  96. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/sos.lp +0 -0
  97. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/sudoku.lp +0 -0
  98. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/test.lp +0 -0
  99. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/test2.lp +0 -0
  100. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/test_copy.lp +0 -0
  101. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/resources/wbm.lp +0 -0
  102. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/bin/main.rs +0 -0
  103. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/builder.rs +0 -0
  104. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/csv.rs +0 -0
  105. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/error.rs +0 -0
  106. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/parser.rs +0 -0
  107. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/parsers/coefficient.rs +0 -0
  108. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/parsers/mod.rs +0 -0
  109. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/parsers/number.rs +0 -0
  110. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/parsers/objective.rs +0 -0
  111. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/parsers/parser_traits.rs +0 -0
  112. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/parsers/problem_name.rs +0 -0
  113. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/parsers/sense.rs +0 -0
  114. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/parsers/sos_constraint.rs +0 -0
  115. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/parsers/variable.rs +0 -0
  116. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/snapshots/lp_parser_rs__problem__test__minified_example.snap +0 -0
  117. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/snapshots/lp_parser_rs__problem__test__small_input.snap +0 -0
  118. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/src/validation.rs +0 -0
  119. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__afiro.snap +0 -0
  120. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__afiro_ext.snap +0 -0
  121. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__american_steel_problem.snap +0 -0
  122. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__beer_distribution_problem.snap +0 -0
  123. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__blank_lines.snap +0 -0
  124. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__boeing1.snap +0 -0
  125. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__boeing2.snap +0 -0
  126. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__complex_names.snap +0 -0
  127. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__computer_plant_problem.snap +0 -0
  128. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__cplex.snap +0 -0
  129. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__diet.snap +0 -0
  130. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__empty_bounds.snap +0 -0
  131. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__fit1d.snap +0 -0
  132. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__infile_comments.snap +0 -0
  133. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__infile_comments2.snap +0 -0
  134. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__kb2.snap +0 -0
  135. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__limbo.snap +0 -0
  136. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__lol.snap +0 -0
  137. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__milo1.snap +0 -0
  138. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__missing_signs.snap +0 -0
  139. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__model.snap +0 -0
  140. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__model2.snap +0 -0
  141. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__mosek.snap +0 -0
  142. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__mosek_bounds.snap +0 -0
  143. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__nom_fit2d.snap +0 -0
  144. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__obj3_2cons.snap +0 -0
  145. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__obj_1cons_all_variables_with_bounds.snap +0 -0
  146. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__obj_2cons_all_variable_types.snap +0 -0
  147. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__obj_2cons_only_binary_vars.snap +0 -0
  148. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__output.snap +0 -0
  149. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__output2_1.snap +0 -0
  150. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__output2_2.snap +0 -0
  151. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__output2_3.snap +0 -0
  152. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__output2_4.snap +0 -0
  153. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__pulp.snap +0 -0
  154. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__pulp2.snap +0 -0
  155. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__sc50a.snap +0 -0
  156. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__scientific_notation.snap +0 -0
  157. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__scientific_notation_2.snap +0 -0
  158. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__sos.snap +0 -0
  159. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__sudoku.snap +0 -0
  160. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__test.snap +0 -0
  161. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__test2.snap +0 -0
  162. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__wbm.snap +0 -0
  163. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__whiskas_model_2.snap +0 -0
  164. {parse_lp-2.5.0 → parse_lp-2.6.0}/rust/tests/test_nom_from_file.rs +0 -0
@@ -310,7 +310,7 @@ checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
310
310
 
311
311
  [[package]]
312
312
  name = "lp_parser_rs"
313
- version = "2.4.3"
313
+ version = "2.5.0"
314
314
  dependencies = [
315
315
  "csv",
316
316
  "diff-struct",
@@ -432,7 +432,7 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
432
432
 
433
433
  [[package]]
434
434
  name = "parse_lp"
435
- version = "2.5.0"
435
+ version = "2.6.0"
436
436
  dependencies = [
437
437
  "lp_parser_rs",
438
438
  "pyo3",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: parse_lp
3
- Version: 2.5.0
3
+ Version: 2.6.0
4
4
  Classifier: License :: OSI Approved :: Apache Software License
5
5
  Classifier: Programming Language :: Python :: 3.9
6
6
  Classifier: Programming Language :: Python :: 3.10
@@ -18,11 +18,15 @@ Project-URL: Source Code, https://github.com/dandxy89/lp_parser_rs
18
18
 
19
19
  # parse_lp
20
20
 
21
- A LP file format parser for Python, powered by Rust.
21
+ [![PyPI version](https://badge.fury.io/py/parse-lp.svg)](https://badge.fury.io/py/parse-lp)
22
+
23
+ A LP file format parser, writer, and modifier for Python, powered by Rust.
22
24
 
23
25
  ## Features
24
26
 
25
27
  - **Complete LP Support**: Handles all standard LP file format features
28
+ - **Problem Modification**: Programmatically modify objectives, constraints, and variables
29
+ - **LP File Writing**: Generate LP files from modified problems with round-trip compatibility
26
30
  - **Easy Data Access**: Direct access to problem components (variables, constraints, objectives)
27
31
  - **CSV Export**: Export parsed data to CSV files for further analysis
28
32
  - **Problem Comparison**: Compare two LP problems to identify differences
@@ -49,6 +53,15 @@ print(f"Sense: {parser.sense}")
49
53
  print(f"Variables: {parser.variable_count()}")
50
54
  print(f"Constraints: {parser.constraint_count()}")
51
55
 
56
+ # Modify the problem
57
+ parser.update_objective_coefficient("OBJ", "x1", 5.0)
58
+ parser.rename_variable("x2", "production")
59
+ parser.update_constraint_rhs("C1", 100.0)
60
+
61
+ # Write back to LP format
62
+ modified_lp = parser.to_lp_string()
63
+ parser.save_to_file("modified_problem.lp")
64
+
52
65
  # Export to CSV files
53
66
  parser.to_csv("output_directory/")
54
67
  ```
@@ -118,6 +131,42 @@ parser.to_csv("output/")
118
131
  # - output/objectives.csv
119
132
  ```
120
133
 
134
+ ### Problem Modification
135
+
136
+ ```python
137
+ from parse_lp import LpParser
138
+
139
+ # Parse an existing LP file
140
+ parser = LpParser("optimization_problem.lp")
141
+ parser.parse()
142
+
143
+ # Modify objectives
144
+ parser.update_objective_coefficient("profit", "x1", 5.0)
145
+ parser.rename_objective("profit", "total_profit")
146
+
147
+ # Modify constraints
148
+ parser.update_constraint_coefficient("capacity", "x1", 2.0)
149
+ parser.update_constraint_rhs("capacity", 200.0)
150
+ parser.rename_constraint("capacity", "production_limit")
151
+
152
+ # Modify variables
153
+ parser.rename_variable("x1", "production_a")
154
+ parser.update_variable_type("production_a", "integer")
155
+
156
+ # Set problem properties
157
+ parser.set_problem_name("Modified Optimization Problem")
158
+ parser.set_sense("minimize")
159
+
160
+ # Write back to LP format
161
+ modified_lp_content = parser.to_lp_string()
162
+ parser.save_to_file("modified_problem.lp")
163
+
164
+ # Verify round-trip compatibility
165
+ new_parser = LpParser("modified_problem.lp")
166
+ new_parser.parse()
167
+ print(f"Successfully modified and re-parsed: {new_parser.name}")
168
+ ```
169
+
121
170
  ### Problem Comparison
122
171
 
123
172
  ```python
@@ -193,6 +242,47 @@ print(f"Removed constraints: {diff['removed_constraints']}")
193
242
  ]
194
243
  ```
195
244
 
245
+ ## Modification Methods
246
+
247
+ ### Objective Methods
248
+
249
+ - `update_objective_coefficient(obj_name, var_name, coefficient)` - Update or add coefficient
250
+ - `rename_objective(old_name, new_name)` - Rename an objective
251
+ - `remove_objective(obj_name)` - Remove an objective
252
+
253
+ ### Constraint Methods
254
+
255
+ - `update_constraint_coefficient(const_name, var_name, coefficient)` - Update or add coefficient
256
+ - `update_constraint_rhs(const_name, new_rhs)` - Update right-hand side value
257
+ - `rename_constraint(old_name, new_name)` - Rename a constraint
258
+ - `remove_constraint(const_name)` - Remove a constraint
259
+
260
+ ### Variable Methods
261
+
262
+ - `rename_variable(old_name, new_name)` - Rename variable across problem
263
+ - `update_variable_type(var_name, var_type)` - Change variable type
264
+ - `remove_variable(var_name)` - Remove variable from problem
265
+
266
+ ### Problem Methods
267
+
268
+ - `set_problem_name(name)` - Set problem name
269
+ - `set_sense(sense)` - Set optimization sense ("maximize" or "minimize")
270
+
271
+ ### Writing Methods
272
+
273
+ - `to_lp_string()` - Generate LP format string
274
+ - `to_lp_string_with_options(**options)` - Generate with custom formatting
275
+ - `save_to_file(filepath)` - Save to LP file
276
+
277
+ ### Variable Types
278
+
279
+ Supported variable types for `update_variable_type()`:
280
+ - `"binary"` - Binary variables (0 or 1)
281
+ - `"integer"` - General integer variables
282
+ - `"general"` - Continuous variables (default)
283
+ - `"free"` - Free variables (no bounds)
284
+ - `"semicontinuous"` - Semi-continuous variables
285
+
196
286
  ## Supported LP Format Features
197
287
 
198
288
  - Multiple objective functions
@@ -1,10 +1,14 @@
1
1
  # parse_lp
2
2
 
3
- A LP file format parser for Python, powered by Rust.
3
+ [![PyPI version](https://badge.fury.io/py/parse-lp.svg)](https://badge.fury.io/py/parse-lp)
4
+
5
+ A LP file format parser, writer, and modifier for Python, powered by Rust.
4
6
 
5
7
  ## Features
6
8
 
7
9
  - **Complete LP Support**: Handles all standard LP file format features
10
+ - **Problem Modification**: Programmatically modify objectives, constraints, and variables
11
+ - **LP File Writing**: Generate LP files from modified problems with round-trip compatibility
8
12
  - **Easy Data Access**: Direct access to problem components (variables, constraints, objectives)
9
13
  - **CSV Export**: Export parsed data to CSV files for further analysis
10
14
  - **Problem Comparison**: Compare two LP problems to identify differences
@@ -31,6 +35,15 @@ print(f"Sense: {parser.sense}")
31
35
  print(f"Variables: {parser.variable_count()}")
32
36
  print(f"Constraints: {parser.constraint_count()}")
33
37
 
38
+ # Modify the problem
39
+ parser.update_objective_coefficient("OBJ", "x1", 5.0)
40
+ parser.rename_variable("x2", "production")
41
+ parser.update_constraint_rhs("C1", 100.0)
42
+
43
+ # Write back to LP format
44
+ modified_lp = parser.to_lp_string()
45
+ parser.save_to_file("modified_problem.lp")
46
+
34
47
  # Export to CSV files
35
48
  parser.to_csv("output_directory/")
36
49
  ```
@@ -100,6 +113,42 @@ parser.to_csv("output/")
100
113
  # - output/objectives.csv
101
114
  ```
102
115
 
116
+ ### Problem Modification
117
+
118
+ ```python
119
+ from parse_lp import LpParser
120
+
121
+ # Parse an existing LP file
122
+ parser = LpParser("optimization_problem.lp")
123
+ parser.parse()
124
+
125
+ # Modify objectives
126
+ parser.update_objective_coefficient("profit", "x1", 5.0)
127
+ parser.rename_objective("profit", "total_profit")
128
+
129
+ # Modify constraints
130
+ parser.update_constraint_coefficient("capacity", "x1", 2.0)
131
+ parser.update_constraint_rhs("capacity", 200.0)
132
+ parser.rename_constraint("capacity", "production_limit")
133
+
134
+ # Modify variables
135
+ parser.rename_variable("x1", "production_a")
136
+ parser.update_variable_type("production_a", "integer")
137
+
138
+ # Set problem properties
139
+ parser.set_problem_name("Modified Optimization Problem")
140
+ parser.set_sense("minimize")
141
+
142
+ # Write back to LP format
143
+ modified_lp_content = parser.to_lp_string()
144
+ parser.save_to_file("modified_problem.lp")
145
+
146
+ # Verify round-trip compatibility
147
+ new_parser = LpParser("modified_problem.lp")
148
+ new_parser.parse()
149
+ print(f"Successfully modified and re-parsed: {new_parser.name}")
150
+ ```
151
+
103
152
  ### Problem Comparison
104
153
 
105
154
  ```python
@@ -175,6 +224,47 @@ print(f"Removed constraints: {diff['removed_constraints']}")
175
224
  ]
176
225
  ```
177
226
 
227
+ ## Modification Methods
228
+
229
+ ### Objective Methods
230
+
231
+ - `update_objective_coefficient(obj_name, var_name, coefficient)` - Update or add coefficient
232
+ - `rename_objective(old_name, new_name)` - Rename an objective
233
+ - `remove_objective(obj_name)` - Remove an objective
234
+
235
+ ### Constraint Methods
236
+
237
+ - `update_constraint_coefficient(const_name, var_name, coefficient)` - Update or add coefficient
238
+ - `update_constraint_rhs(const_name, new_rhs)` - Update right-hand side value
239
+ - `rename_constraint(old_name, new_name)` - Rename a constraint
240
+ - `remove_constraint(const_name)` - Remove a constraint
241
+
242
+ ### Variable Methods
243
+
244
+ - `rename_variable(old_name, new_name)` - Rename variable across problem
245
+ - `update_variable_type(var_name, var_type)` - Change variable type
246
+ - `remove_variable(var_name)` - Remove variable from problem
247
+
248
+ ### Problem Methods
249
+
250
+ - `set_problem_name(name)` - Set problem name
251
+ - `set_sense(sense)` - Set optimization sense ("maximize" or "minimize")
252
+
253
+ ### Writing Methods
254
+
255
+ - `to_lp_string()` - Generate LP format string
256
+ - `to_lp_string_with_options(**options)` - Generate with custom formatting
257
+ - `save_to_file(filepath)` - Save to LP file
258
+
259
+ ### Variable Types
260
+
261
+ Supported variable types for `update_variable_type()`:
262
+ - `"binary"` - Binary variables (0 or 1)
263
+ - `"integer"` - General integer variables
264
+ - `"general"` - Continuous variables (default)
265
+ - `"free"` - Free variables (no bounds)
266
+ - `"semicontinuous"` - Semi-continuous variables
267
+
178
268
  ## Supported LP Format Features
179
269
 
180
270
  - Multiple objective functions
@@ -0,0 +1,73 @@
1
+ """parse_lp - A fast LP file format parser, writer, and modifier for Python, powered by Rust.
2
+
3
+ This package provides a high-performance parser for Linear Programming (LP) files,
4
+ leveraging Rust for speed and Python for ease of use. It supports parsing, modifying,
5
+ and writing LP files with full round-trip compatibility.
6
+
7
+ Key Features:
8
+ - Fast parsing of LP files of various formats
9
+ - Programmatic modification of LP problems (objectives, constraints, variables)
10
+ - Write LP problems back to standard LP format
11
+ - Export parsed data to CSV files
12
+ - Access to problem components (variables, constraints, objectives)
13
+ - Compare two LP problems to find differences
14
+ - Type hints for better IDE support
15
+
16
+ Example Usage:
17
+ >>> from parse_lp import LpParser
18
+ >>>
19
+ >>> # Parse an LP file
20
+ >>> parser = LpParser("optimization_problem.lp")
21
+ >>> parser.parse()
22
+ >>>
23
+ >>> # Access problem information
24
+ >>> print(f"Problem name: {parser.name}")
25
+ >>> print(f"Variables: {parser.variable_count()}")
26
+ >>> print(f"Constraints: {parser.constraint_count()}")
27
+ >>>
28
+ >>> # Modify the problem
29
+ >>> parser.update_objective_coefficient("profit", "x1", 5.0)
30
+ >>> parser.rename_variable("x2", "production")
31
+ >>> parser.update_constraint_rhs("capacity", 100.0)
32
+ >>> parser.update_variable_type("x1", "integer")
33
+ >>>
34
+ >>> # Write back to LP format
35
+ >>> modified_lp = parser.to_lp_string()
36
+ >>> parser.save_to_file("modified_problem.lp")
37
+ >>>
38
+ >>> # Export to CSV files
39
+ >>> parser.to_csv("output/")
40
+ >>>
41
+ >>> # Compare two problems
42
+ >>> parser2 = LpParser("modified_problem.lp")
43
+ >>> parser2.parse()
44
+ >>> diff = parser.compare(parser2)
45
+ >>> print(f"Added variables: {diff['added_variables']}")
46
+
47
+ Modification Methods:
48
+ Objective modifications:
49
+ - update_objective_coefficient(obj_name, var_name, coefficient)
50
+ - rename_objective(old_name, new_name)
51
+ - remove_objective(obj_name)
52
+
53
+ Constraint modifications:
54
+ - update_constraint_coefficient(const_name, var_name, coefficient)
55
+ - update_constraint_rhs(const_name, new_rhs)
56
+ - rename_constraint(old_name, new_name)
57
+ - remove_constraint(const_name)
58
+
59
+ Variable modifications:
60
+ - rename_variable(old_name, new_name)
61
+ - update_variable_type(var_name, var_type) # binary, integer, general, free, semicontinuous
62
+ - remove_variable(var_name)
63
+
64
+ Problem modifications:
65
+ - set_problem_name(name)
66
+ - set_sense(sense) # maximize, minimize
67
+
68
+ """
69
+
70
+ from .parse_lp import LpParser
71
+
72
+ __version__ = "2.5.0"
73
+ __all__ = ["LpParser"]
@@ -29,6 +29,7 @@ manifest-path = "python/Cargo.toml"
29
29
 
30
30
  [dependency-groups]
31
31
  dev = [
32
+ "basedpyright>=1.31.0",
32
33
  "mypy>=1.17.0",
33
34
  "pip>=25.1.1",
34
35
  "pytest>=8.4.1",
@@ -0,0 +1 @@
1
+ .env
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "parse_lp"
3
- version = "2.5.0"
3
+ version = "2.6.0"
4
4
  edition = "2021"
5
5
  authors = ["Dan Dixey", "Dan Dixey <dan@functorml.co.uk>"]
6
6
  rust-version = "1.70.0"
@@ -44,13 +44,13 @@ check-python: ## Run check on Python
44
44
  uv run --no-sync ruff format --check --diff .
45
45
  $(info Check Python linting)
46
46
  uv run --no-sync ruff check .
47
- # $(info Check Python mypy)
48
- # uv run --no-sync mypy
47
+ $(info Check Python mypy)
48
+ uv run --no-sync mypy
49
49
 
50
50
  .PHONY: unit-test
51
51
  unit-test: install ## Run unit test
52
52
  $(info --- Run Python unit-test ---)
53
- uv run --no-sync pytest --doctest-modules
53
+ uv run --no-sync pytest --doctest-modules
54
54
 
55
55
  .PHONY: clean
56
56
  clean: ## Run clean
@@ -1,10 +1,14 @@
1
1
  # parse_lp
2
2
 
3
- A LP file format parser for Python, powered by Rust.
3
+ [![PyPI version](https://badge.fury.io/py/parse-lp.svg)](https://badge.fury.io/py/parse-lp)
4
+
5
+ A LP file format parser, writer, and modifier for Python, powered by Rust.
4
6
 
5
7
  ## Features
6
8
 
7
9
  - **Complete LP Support**: Handles all standard LP file format features
10
+ - **Problem Modification**: Programmatically modify objectives, constraints, and variables
11
+ - **LP File Writing**: Generate LP files from modified problems with round-trip compatibility
8
12
  - **Easy Data Access**: Direct access to problem components (variables, constraints, objectives)
9
13
  - **CSV Export**: Export parsed data to CSV files for further analysis
10
14
  - **Problem Comparison**: Compare two LP problems to identify differences
@@ -31,6 +35,15 @@ print(f"Sense: {parser.sense}")
31
35
  print(f"Variables: {parser.variable_count()}")
32
36
  print(f"Constraints: {parser.constraint_count()}")
33
37
 
38
+ # Modify the problem
39
+ parser.update_objective_coefficient("OBJ", "x1", 5.0)
40
+ parser.rename_variable("x2", "production")
41
+ parser.update_constraint_rhs("C1", 100.0)
42
+
43
+ # Write back to LP format
44
+ modified_lp = parser.to_lp_string()
45
+ parser.save_to_file("modified_problem.lp")
46
+
34
47
  # Export to CSV files
35
48
  parser.to_csv("output_directory/")
36
49
  ```
@@ -100,6 +113,42 @@ parser.to_csv("output/")
100
113
  # - output/objectives.csv
101
114
  ```
102
115
 
116
+ ### Problem Modification
117
+
118
+ ```python
119
+ from parse_lp import LpParser
120
+
121
+ # Parse an existing LP file
122
+ parser = LpParser("optimization_problem.lp")
123
+ parser.parse()
124
+
125
+ # Modify objectives
126
+ parser.update_objective_coefficient("profit", "x1", 5.0)
127
+ parser.rename_objective("profit", "total_profit")
128
+
129
+ # Modify constraints
130
+ parser.update_constraint_coefficient("capacity", "x1", 2.0)
131
+ parser.update_constraint_rhs("capacity", 200.0)
132
+ parser.rename_constraint("capacity", "production_limit")
133
+
134
+ # Modify variables
135
+ parser.rename_variable("x1", "production_a")
136
+ parser.update_variable_type("production_a", "integer")
137
+
138
+ # Set problem properties
139
+ parser.set_problem_name("Modified Optimization Problem")
140
+ parser.set_sense("minimize")
141
+
142
+ # Write back to LP format
143
+ modified_lp_content = parser.to_lp_string()
144
+ parser.save_to_file("modified_problem.lp")
145
+
146
+ # Verify round-trip compatibility
147
+ new_parser = LpParser("modified_problem.lp")
148
+ new_parser.parse()
149
+ print(f"Successfully modified and re-parsed: {new_parser.name}")
150
+ ```
151
+
103
152
  ### Problem Comparison
104
153
 
105
154
  ```python
@@ -175,6 +224,47 @@ print(f"Removed constraints: {diff['removed_constraints']}")
175
224
  ]
176
225
  ```
177
226
 
227
+ ## Modification Methods
228
+
229
+ ### Objective Methods
230
+
231
+ - `update_objective_coefficient(obj_name, var_name, coefficient)` - Update or add coefficient
232
+ - `rename_objective(old_name, new_name)` - Rename an objective
233
+ - `remove_objective(obj_name)` - Remove an objective
234
+
235
+ ### Constraint Methods
236
+
237
+ - `update_constraint_coefficient(const_name, var_name, coefficient)` - Update or add coefficient
238
+ - `update_constraint_rhs(const_name, new_rhs)` - Update right-hand side value
239
+ - `rename_constraint(old_name, new_name)` - Rename a constraint
240
+ - `remove_constraint(const_name)` - Remove a constraint
241
+
242
+ ### Variable Methods
243
+
244
+ - `rename_variable(old_name, new_name)` - Rename variable across problem
245
+ - `update_variable_type(var_name, var_type)` - Change variable type
246
+ - `remove_variable(var_name)` - Remove variable from problem
247
+
248
+ ### Problem Methods
249
+
250
+ - `set_problem_name(name)` - Set problem name
251
+ - `set_sense(sense)` - Set optimization sense ("maximize" or "minimize")
252
+
253
+ ### Writing Methods
254
+
255
+ - `to_lp_string()` - Generate LP format string
256
+ - `to_lp_string_with_options(**options)` - Generate with custom formatting
257
+ - `save_to_file(filepath)` - Save to LP file
258
+
259
+ ### Variable Types
260
+
261
+ Supported variable types for `update_variable_type()`:
262
+ - `"binary"` - Binary variables (0 or 1)
263
+ - `"integer"` - General integer variables
264
+ - `"general"` - Continuous variables (default)
265
+ - `"free"` - Free variables (no bounds)
266
+ - `"semicontinuous"` - Semi-continuous variables
267
+
178
268
  ## Supported LP Format Features
179
269
 
180
270
  - Multiple objective functions
@@ -0,0 +1,73 @@
1
+ """parse_lp - A fast LP file format parser, writer, and modifier for Python, powered by Rust.
2
+
3
+ This package provides a high-performance parser for Linear Programming (LP) files,
4
+ leveraging Rust for speed and Python for ease of use. It supports parsing, modifying,
5
+ and writing LP files with full round-trip compatibility.
6
+
7
+ Key Features:
8
+ - Fast parsing of LP files of various formats
9
+ - Programmatic modification of LP problems (objectives, constraints, variables)
10
+ - Write LP problems back to standard LP format
11
+ - Export parsed data to CSV files
12
+ - Access to problem components (variables, constraints, objectives)
13
+ - Compare two LP problems to find differences
14
+ - Type hints for better IDE support
15
+
16
+ Example Usage:
17
+ >>> from parse_lp import LpParser
18
+ >>>
19
+ >>> # Parse an LP file
20
+ >>> parser = LpParser("optimization_problem.lp")
21
+ >>> parser.parse()
22
+ >>>
23
+ >>> # Access problem information
24
+ >>> print(f"Problem name: {parser.name}")
25
+ >>> print(f"Variables: {parser.variable_count()}")
26
+ >>> print(f"Constraints: {parser.constraint_count()}")
27
+ >>>
28
+ >>> # Modify the problem
29
+ >>> parser.update_objective_coefficient("profit", "x1", 5.0)
30
+ >>> parser.rename_variable("x2", "production")
31
+ >>> parser.update_constraint_rhs("capacity", 100.0)
32
+ >>> parser.update_variable_type("x1", "integer")
33
+ >>>
34
+ >>> # Write back to LP format
35
+ >>> modified_lp = parser.to_lp_string()
36
+ >>> parser.save_to_file("modified_problem.lp")
37
+ >>>
38
+ >>> # Export to CSV files
39
+ >>> parser.to_csv("output/")
40
+ >>>
41
+ >>> # Compare two problems
42
+ >>> parser2 = LpParser("modified_problem.lp")
43
+ >>> parser2.parse()
44
+ >>> diff = parser.compare(parser2)
45
+ >>> print(f"Added variables: {diff['added_variables']}")
46
+
47
+ Modification Methods:
48
+ Objective modifications:
49
+ - update_objective_coefficient(obj_name, var_name, coefficient)
50
+ - rename_objective(old_name, new_name)
51
+ - remove_objective(obj_name)
52
+
53
+ Constraint modifications:
54
+ - update_constraint_coefficient(const_name, var_name, coefficient)
55
+ - update_constraint_rhs(const_name, new_rhs)
56
+ - rename_constraint(old_name, new_name)
57
+ - remove_constraint(const_name)
58
+
59
+ Variable modifications:
60
+ - rename_variable(old_name, new_name)
61
+ - update_variable_type(var_name, var_type) # binary, integer, general, free, semicontinuous
62
+ - remove_variable(var_name)
63
+
64
+ Problem modifications:
65
+ - set_problem_name(name)
66
+ - set_sense(sense) # maximize, minimize
67
+
68
+ """
69
+
70
+ from .parse_lp import LpParser
71
+
72
+ __version__ = "2.5.0"
73
+ __all__ = ["LpParser"]
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.6.0](https://github.com/dandxy89/lp_parser_rs/compare/parse_lp-v2.5.0...parse_lp-v2.6.0) (2025-07-27)
4
+
5
+
6
+ ### Features
7
+
8
+ * Adding the functionality to modify and write to a .lp file ([46c69a9](https://github.com/dandxy89/lp_parser_rs/commit/46c69a997263ab3fbb6bb1ccfd4d6b4dee71bc6a))
9
+
3
10
  ## [2.5.0](https://github.com/dandxy89/lp_parser_rs/compare/parse_lp-v2.4.3...parse_lp-v2.5.0) (2025-07-24)
4
11
 
5
12