parse-lp 2.4.3__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.
- {parse_lp-2.4.3 → parse_lp-2.6.0}/Cargo.lock +2 -2
- parse_lp-2.6.0/PKG-INFO +303 -0
- parse_lp-2.6.0/README.md +284 -0
- parse_lp-2.6.0/parse_lp/__init__.py +73 -0
- parse_lp-2.6.0/parse_lp/parse_lp.pyi +179 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/pyproject.toml +13 -5
- parse_lp-2.6.0/python/.gitignore +1 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/python/Cargo.toml +2 -2
- {parse_lp-2.4.3 → parse_lp-2.6.0}/python/MANIFEST.in +3 -2
- {parse_lp-2.4.3 → parse_lp-2.6.0}/python/Makefile +3 -3
- parse_lp-2.6.0/python/README.md +284 -0
- parse_lp-2.6.0/python/parse_lp/__init__.py +73 -0
- parse_lp-2.6.0/python/parse_lp/parse_lp.pyi +179 -0
- parse_lp-2.6.0/python/parse_lp/py.typed +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/python/python/CHANGELOG.md +14 -0
- parse_lp-2.6.0/python/src/lib.rs +485 -0
- parse_lp-2.6.0/python/tests/__init__.py +0 -0
- parse_lp-2.6.0/python/tests/fixtures/minimize.lp +16 -0
- parse_lp-2.6.0/python/tests/fixtures/simple.lp +12 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/python/tests/test_csv_writer.py +0 -5
- parse_lp-2.6.0/python/tests/test_lp_parser.py +224 -0
- parse_lp-2.6.0/python/tests/test_lp_writer.py +358 -0
- parse_lp-2.6.0/python/uv.lock +283 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/Cargo.toml +1 -1
- parse_lp-2.6.0/rust/README.md +198 -0
- parse_lp-2.6.0/rust/resources/afiro.lp +36 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/rust/CHANGELOG.md +7 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/context.rs +1 -1
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/lib.rs +1 -10
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/model.rs +2 -2
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/parsers/constraint.rs +7 -4
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/perf.rs +2 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/problem.rs +755 -13
- parse_lp-2.6.0/rust/src/writer.rs +562 -0
- parse_lp-2.4.3/PKG-INFO +0 -43
- parse_lp-2.4.3/README.md +0 -25
- parse_lp-2.4.3/parse_lp/__init__.py +0 -3
- parse_lp-2.4.3/python/README.md +0 -25
- parse_lp-2.4.3/python/parse_lp/__init__.py +0 -3
- parse_lp-2.4.3/python/src/lib.rs +0 -51
- parse_lp-2.4.3/python/uv.lock +0 -232
- parse_lp-2.4.3/rust/README.md +0 -120
- {parse_lp-2.4.3 → parse_lp-2.6.0}/Cargo.toml +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/LICENSE-APACHE +0 -0
- /parse_lp-2.4.3/python/tests/__init__.py → /parse_lp-2.6.0/parse_lp/py.typed +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/python/.cargo/config.toml +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/python/CHANGELOG.md +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/python/LICENSE-APACHE +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/python/resources/afiro.lp +0 -0
- {parse_lp-2.4.3/rust/resources → parse_lp-2.6.0/python/tests/fixtures}/afiro.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/CHANGELOG.md +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/benches/lp_parsing.rs +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/benches/parsing_micro.rs +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/1obj_1cons_all_variables_with_bounds.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/2obj_2cons_all_variable_types.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/2obj_2cons_only_binary_vars.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/3obj_2cons.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/AmericanSteelProblem.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/BeerDistributionProblem.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/ComputerPlantProblem.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/WhiskasModel2.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/afiro_ext.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/blank_lines.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/boeing1.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/boeing2.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/carbon.png +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/complex_names.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/corrupt.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/cplex.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/diet.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/empty_bounds.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/fit1d.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/fit2d.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/infile_comments.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/infile_comments2.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/invalid.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/kb2.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/limbo.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/lol.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/milo1.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/missing_signs.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/model.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/model2.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/mosek.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/mosek_bounds.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/no_end_section.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/optional_labels.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/output.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/output2_1.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/output2_2.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/output2_3.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/output2_4.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/output_cplex_2.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/pulp.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/pulp2.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/sc50a.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/scientific_notation.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/scientific_notation_2.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/semi_continuous.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/sos.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/sudoku.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/test.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/test2.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/test_copy.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/resources/wbm.lp +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/bin/main.rs +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/builder.rs +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/csv.rs +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/error.rs +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/parser.rs +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/parsers/coefficient.rs +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/parsers/mod.rs +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/parsers/number.rs +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/parsers/objective.rs +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/parsers/parser_traits.rs +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/parsers/problem_name.rs +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/parsers/sense.rs +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/parsers/sos_constraint.rs +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/parsers/variable.rs +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/snapshots/lp_parser_rs__problem__test__minified_example.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/snapshots/lp_parser_rs__problem__test__small_input.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/src/validation.rs +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__afiro.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__afiro_ext.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__american_steel_problem.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__beer_distribution_problem.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__blank_lines.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__boeing1.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__boeing2.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__complex_names.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__computer_plant_problem.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__cplex.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__diet.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__empty_bounds.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__fit1d.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__infile_comments.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__infile_comments2.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__kb2.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__limbo.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__lol.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__milo1.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__missing_signs.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__model.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__model2.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__mosek.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__mosek_bounds.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__nom_fit2d.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__obj3_2cons.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__obj_1cons_all_variables_with_bounds.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__obj_2cons_all_variable_types.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__obj_2cons_only_binary_vars.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__output.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__output2_1.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__output2_2.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__output2_3.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__output2_4.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__pulp.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__pulp2.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__sc50a.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__scientific_notation.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__scientific_notation_2.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__sos.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__sudoku.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__test.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__test2.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__wbm.snap +0 -0
- {parse_lp-2.4.3 → parse_lp-2.6.0}/rust/tests/snapshots/test_nom_from_file__whiskas_model_2.snap +0 -0
- {parse_lp-2.4.3 → 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.
|
|
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.
|
|
435
|
+
version = "2.6.0"
|
|
436
436
|
dependencies = [
|
|
437
437
|
"lp_parser_rs",
|
|
438
438
|
"pyo3",
|
parse_lp-2.6.0/PKG-INFO
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: parse_lp
|
|
3
|
+
Version: 2.6.0
|
|
4
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
5
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
6
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
7
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
9
|
+
License-File: LICENSE-APACHE
|
|
10
|
+
Summary: A LP file format parser for Python, powered by Rust
|
|
11
|
+
Keywords: linear-programming,optimization,parser,integer-programming,math
|
|
12
|
+
Author: Dan Dixey, Dan Dixey <dan@functorml.co.uk>
|
|
13
|
+
Author-email: Dan Dixey, Dan Dixey <dan@functorml.co.uk>
|
|
14
|
+
License: MIT OR Apache-2.0
|
|
15
|
+
Requires-Python: >=3.9
|
|
16
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
17
|
+
Project-URL: Source Code, https://github.com/dandxy89/lp_parser_rs
|
|
18
|
+
|
|
19
|
+
# parse_lp
|
|
20
|
+
|
|
21
|
+
[](https://badge.fury.io/py/parse-lp)
|
|
22
|
+
|
|
23
|
+
A LP file format parser, writer, and modifier for Python, powered by Rust.
|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
|
|
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
|
|
30
|
+
- **Easy Data Access**: Direct access to problem components (variables, constraints, objectives)
|
|
31
|
+
- **CSV Export**: Export parsed data to CSV files for further analysis
|
|
32
|
+
- **Problem Comparison**: Compare two LP problems to identify differences
|
|
33
|
+
- **Type Safety**: Full type hints for better IDE support and development experience
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install parse_lp
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from parse_lp import LpParser
|
|
45
|
+
|
|
46
|
+
# Parse an LP file
|
|
47
|
+
parser = LpParser("path/to/problem.lp")
|
|
48
|
+
parser.parse()
|
|
49
|
+
|
|
50
|
+
# Access problem information
|
|
51
|
+
print(f"Problem: {parser.name}")
|
|
52
|
+
print(f"Sense: {parser.sense}")
|
|
53
|
+
print(f"Variables: {parser.variable_count()}")
|
|
54
|
+
print(f"Constraints: {parser.constraint_count()}")
|
|
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
|
+
|
|
65
|
+
# Export to CSV files
|
|
66
|
+
parser.to_csv("output_directory/")
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Usage Examples
|
|
70
|
+
|
|
71
|
+
### Basic Parsing and Information
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from parse_lp import LpParser
|
|
75
|
+
|
|
76
|
+
parser = LpParser("optimization_problem.lp")
|
|
77
|
+
parser.parse()
|
|
78
|
+
|
|
79
|
+
# Get problem overview
|
|
80
|
+
print(f"Problem Name: {parser.name}")
|
|
81
|
+
print(f"Optimization Sense: {parser.sense}")
|
|
82
|
+
print(f"Variables: {parser.variable_count()}")
|
|
83
|
+
print(f"Constraints: {parser.constraint_count()}")
|
|
84
|
+
print(f"Objectives: {parser.objective_count()}")
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Accessing Problem Data
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
# Access objectives
|
|
91
|
+
for i, objective in enumerate(parser.objectives):
|
|
92
|
+
print(f"Objective {i+1}: {objective['name']}")
|
|
93
|
+
for coef in objective['coefficients']:
|
|
94
|
+
print(f" {coef['name']}: {coef['value']}")
|
|
95
|
+
|
|
96
|
+
# Access variables
|
|
97
|
+
for var_name, var_info in parser.variables.items():
|
|
98
|
+
print(f"Variable {var_name}:")
|
|
99
|
+
print(f" Type: {var_info['var_type']}")
|
|
100
|
+
if 'bounds' in var_info:
|
|
101
|
+
bounds = var_info['bounds']
|
|
102
|
+
if 'lower' in bounds:
|
|
103
|
+
print(f" Lower bound: {bounds['lower']}")
|
|
104
|
+
if 'upper' in bounds:
|
|
105
|
+
print(f" Upper bound: {bounds['upper']}")
|
|
106
|
+
|
|
107
|
+
# Access constraints
|
|
108
|
+
for constraint in parser.constraints:
|
|
109
|
+
print(f"Constraint {constraint['name']}:")
|
|
110
|
+
print(f" Type: {constraint['type']}")
|
|
111
|
+
if constraint['type'] == 'standard':
|
|
112
|
+
print(f" Sense: {constraint['sense']}")
|
|
113
|
+
print(f" RHS: {constraint['rhs']}")
|
|
114
|
+
print(f" Coefficients: {len(constraint['coefficients'])}")
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### CSV Export
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
import os
|
|
121
|
+
|
|
122
|
+
# Create output directory
|
|
123
|
+
os.makedirs("output", exist_ok=True)
|
|
124
|
+
|
|
125
|
+
# Export to CSV files
|
|
126
|
+
parser.to_csv("output/")
|
|
127
|
+
|
|
128
|
+
# Files created:
|
|
129
|
+
# - output/variables.csv
|
|
130
|
+
# - output/constraints.csv
|
|
131
|
+
# - output/objectives.csv
|
|
132
|
+
```
|
|
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
|
+
|
|
170
|
+
### Problem Comparison
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
# Parse two different versions of a problem
|
|
174
|
+
parser1 = LpParser("problem_v1.lp")
|
|
175
|
+
parser1.parse()
|
|
176
|
+
|
|
177
|
+
parser2 = LpParser("problem_v2.lp")
|
|
178
|
+
parser2.parse()
|
|
179
|
+
|
|
180
|
+
# Compare the problems
|
|
181
|
+
diff = parser1.compare(parser2)
|
|
182
|
+
|
|
183
|
+
print("Comparison Results:")
|
|
184
|
+
print(f"Name changed: {diff['name_changed']}")
|
|
185
|
+
print(f"Sense changed: {diff['sense_changed']}")
|
|
186
|
+
print(f"Variable count difference: {diff['variable_count_diff']}")
|
|
187
|
+
print(f"Added variables: {diff['added_variables']}")
|
|
188
|
+
print(f"Removed variables: {diff['removed_variables']}")
|
|
189
|
+
print(f"Modified variables: {diff['modified_variables']}")
|
|
190
|
+
print(f"Added constraints: {diff['added_constraints']}")
|
|
191
|
+
print(f"Removed constraints: {diff['removed_constraints']}")
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Objectives Structure
|
|
195
|
+
|
|
196
|
+
```python
|
|
197
|
+
[
|
|
198
|
+
{
|
|
199
|
+
"name": "objective_name",
|
|
200
|
+
"coefficients": [
|
|
201
|
+
{"name": "variable_name", "value": 1.5},
|
|
202
|
+
{"name": "another_var", "value": -2.0}
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
]
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Variables Structure
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
{
|
|
212
|
+
"variable_name": {
|
|
213
|
+
"name": "variable_name",
|
|
214
|
+
"var_type": "Continuous", # or "Binary", "Integer", etc.
|
|
215
|
+
"bounds": { # Optional
|
|
216
|
+
"lower": 0.0, # Optional
|
|
217
|
+
"upper": 100.0 # Optional
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Constraints Structure
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
[
|
|
227
|
+
{
|
|
228
|
+
"name": "constraint_name",
|
|
229
|
+
"type": "standard", # or "sos"
|
|
230
|
+
"sense": "LessOrEqual", # "Equal", "GreaterOrEqual"
|
|
231
|
+
"rhs": 10.0,
|
|
232
|
+
"coefficients": [
|
|
233
|
+
{"name": "variable_name", "value": 2.0}
|
|
234
|
+
]
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"name": "sos_constraint",
|
|
238
|
+
"type": "sos",
|
|
239
|
+
"sos_type": "SOS1", # or "SOS2"
|
|
240
|
+
"variables": ["var1", "var2", "var3"]
|
|
241
|
+
}
|
|
242
|
+
]
|
|
243
|
+
```
|
|
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
|
+
|
|
286
|
+
## Supported LP Format Features
|
|
287
|
+
|
|
288
|
+
- Multiple objective functions
|
|
289
|
+
- Standard constraints (≤, =, ≥)
|
|
290
|
+
- Variable bounds
|
|
291
|
+
- Variable types (continuous, binary, integer)
|
|
292
|
+
- SOS (Special Ordered Sets) constraints
|
|
293
|
+
- Problem names and comments
|
|
294
|
+
- Scientific notation in coefficients
|
|
295
|
+
|
|
296
|
+
## License
|
|
297
|
+
|
|
298
|
+
Licensed under either of Apache License, Version 2.0 or MIT license at your option.
|
|
299
|
+
|
|
300
|
+
## Contributing
|
|
301
|
+
|
|
302
|
+
Issues and pull requests are welcome at: <https://github.com/dandxy89/lp_parser_rs>
|
|
303
|
+
|
parse_lp-2.6.0/README.md
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
# parse_lp
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/py/parse-lp)
|
|
4
|
+
|
|
5
|
+
A LP file format parser, writer, and modifier for Python, powered by Rust.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
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
|
|
12
|
+
- **Easy Data Access**: Direct access to problem components (variables, constraints, objectives)
|
|
13
|
+
- **CSV Export**: Export parsed data to CSV files for further analysis
|
|
14
|
+
- **Problem Comparison**: Compare two LP problems to identify differences
|
|
15
|
+
- **Type Safety**: Full type hints for better IDE support and development experience
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install parse_lp
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
from parse_lp import LpParser
|
|
27
|
+
|
|
28
|
+
# Parse an LP file
|
|
29
|
+
parser = LpParser("path/to/problem.lp")
|
|
30
|
+
parser.parse()
|
|
31
|
+
|
|
32
|
+
# Access problem information
|
|
33
|
+
print(f"Problem: {parser.name}")
|
|
34
|
+
print(f"Sense: {parser.sense}")
|
|
35
|
+
print(f"Variables: {parser.variable_count()}")
|
|
36
|
+
print(f"Constraints: {parser.constraint_count()}")
|
|
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
|
+
|
|
47
|
+
# Export to CSV files
|
|
48
|
+
parser.to_csv("output_directory/")
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Usage Examples
|
|
52
|
+
|
|
53
|
+
### Basic Parsing and Information
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from parse_lp import LpParser
|
|
57
|
+
|
|
58
|
+
parser = LpParser("optimization_problem.lp")
|
|
59
|
+
parser.parse()
|
|
60
|
+
|
|
61
|
+
# Get problem overview
|
|
62
|
+
print(f"Problem Name: {parser.name}")
|
|
63
|
+
print(f"Optimization Sense: {parser.sense}")
|
|
64
|
+
print(f"Variables: {parser.variable_count()}")
|
|
65
|
+
print(f"Constraints: {parser.constraint_count()}")
|
|
66
|
+
print(f"Objectives: {parser.objective_count()}")
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Accessing Problem Data
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
# Access objectives
|
|
73
|
+
for i, objective in enumerate(parser.objectives):
|
|
74
|
+
print(f"Objective {i+1}: {objective['name']}")
|
|
75
|
+
for coef in objective['coefficients']:
|
|
76
|
+
print(f" {coef['name']}: {coef['value']}")
|
|
77
|
+
|
|
78
|
+
# Access variables
|
|
79
|
+
for var_name, var_info in parser.variables.items():
|
|
80
|
+
print(f"Variable {var_name}:")
|
|
81
|
+
print(f" Type: {var_info['var_type']}")
|
|
82
|
+
if 'bounds' in var_info:
|
|
83
|
+
bounds = var_info['bounds']
|
|
84
|
+
if 'lower' in bounds:
|
|
85
|
+
print(f" Lower bound: {bounds['lower']}")
|
|
86
|
+
if 'upper' in bounds:
|
|
87
|
+
print(f" Upper bound: {bounds['upper']}")
|
|
88
|
+
|
|
89
|
+
# Access constraints
|
|
90
|
+
for constraint in parser.constraints:
|
|
91
|
+
print(f"Constraint {constraint['name']}:")
|
|
92
|
+
print(f" Type: {constraint['type']}")
|
|
93
|
+
if constraint['type'] == 'standard':
|
|
94
|
+
print(f" Sense: {constraint['sense']}")
|
|
95
|
+
print(f" RHS: {constraint['rhs']}")
|
|
96
|
+
print(f" Coefficients: {len(constraint['coefficients'])}")
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### CSV Export
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
import os
|
|
103
|
+
|
|
104
|
+
# Create output directory
|
|
105
|
+
os.makedirs("output", exist_ok=True)
|
|
106
|
+
|
|
107
|
+
# Export to CSV files
|
|
108
|
+
parser.to_csv("output/")
|
|
109
|
+
|
|
110
|
+
# Files created:
|
|
111
|
+
# - output/variables.csv
|
|
112
|
+
# - output/constraints.csv
|
|
113
|
+
# - output/objectives.csv
|
|
114
|
+
```
|
|
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
|
+
|
|
152
|
+
### Problem Comparison
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
# Parse two different versions of a problem
|
|
156
|
+
parser1 = LpParser("problem_v1.lp")
|
|
157
|
+
parser1.parse()
|
|
158
|
+
|
|
159
|
+
parser2 = LpParser("problem_v2.lp")
|
|
160
|
+
parser2.parse()
|
|
161
|
+
|
|
162
|
+
# Compare the problems
|
|
163
|
+
diff = parser1.compare(parser2)
|
|
164
|
+
|
|
165
|
+
print("Comparison Results:")
|
|
166
|
+
print(f"Name changed: {diff['name_changed']}")
|
|
167
|
+
print(f"Sense changed: {diff['sense_changed']}")
|
|
168
|
+
print(f"Variable count difference: {diff['variable_count_diff']}")
|
|
169
|
+
print(f"Added variables: {diff['added_variables']}")
|
|
170
|
+
print(f"Removed variables: {diff['removed_variables']}")
|
|
171
|
+
print(f"Modified variables: {diff['modified_variables']}")
|
|
172
|
+
print(f"Added constraints: {diff['added_constraints']}")
|
|
173
|
+
print(f"Removed constraints: {diff['removed_constraints']}")
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Objectives Structure
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
[
|
|
180
|
+
{
|
|
181
|
+
"name": "objective_name",
|
|
182
|
+
"coefficients": [
|
|
183
|
+
{"name": "variable_name", "value": 1.5},
|
|
184
|
+
{"name": "another_var", "value": -2.0}
|
|
185
|
+
]
|
|
186
|
+
}
|
|
187
|
+
]
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Variables Structure
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
{
|
|
194
|
+
"variable_name": {
|
|
195
|
+
"name": "variable_name",
|
|
196
|
+
"var_type": "Continuous", # or "Binary", "Integer", etc.
|
|
197
|
+
"bounds": { # Optional
|
|
198
|
+
"lower": 0.0, # Optional
|
|
199
|
+
"upper": 100.0 # Optional
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Constraints Structure
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
[
|
|
209
|
+
{
|
|
210
|
+
"name": "constraint_name",
|
|
211
|
+
"type": "standard", # or "sos"
|
|
212
|
+
"sense": "LessOrEqual", # "Equal", "GreaterOrEqual"
|
|
213
|
+
"rhs": 10.0,
|
|
214
|
+
"coefficients": [
|
|
215
|
+
{"name": "variable_name", "value": 2.0}
|
|
216
|
+
]
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"name": "sos_constraint",
|
|
220
|
+
"type": "sos",
|
|
221
|
+
"sos_type": "SOS1", # or "SOS2"
|
|
222
|
+
"variables": ["var1", "var2", "var3"]
|
|
223
|
+
}
|
|
224
|
+
]
|
|
225
|
+
```
|
|
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
|
+
|
|
268
|
+
## Supported LP Format Features
|
|
269
|
+
|
|
270
|
+
- Multiple objective functions
|
|
271
|
+
- Standard constraints (≤, =, ≥)
|
|
272
|
+
- Variable bounds
|
|
273
|
+
- Variable types (continuous, binary, integer)
|
|
274
|
+
- SOS (Special Ordered Sets) constraints
|
|
275
|
+
- Problem names and comments
|
|
276
|
+
- Scientific notation in coefficients
|
|
277
|
+
|
|
278
|
+
## License
|
|
279
|
+
|
|
280
|
+
Licensed under either of Apache License, Version 2.0 or MIT license at your option.
|
|
281
|
+
|
|
282
|
+
## Contributing
|
|
283
|
+
|
|
284
|
+
Issues and pull requests are welcome at: <https://github.com/dandxy89/lp_parser_rs>
|
|
@@ -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"]
|