Skip to main content

A LP file format parser for Python, powered by Rust

Project description

parse_lp

PyPI version

A LP file format parser, writer, and modifier for Python, powered by Rust.

Features

  • Complete LP Support: Handles all standard LP file format features
  • Problem Modification: Programmatically modify objectives, constraints, and variables
  • LP File Writing: Generate LP files from modified problems with round-trip compatibility
  • Problem Analysis: Comprehensive statistics, structure analysis, and issue detection with configurable thresholds
  • Easy Data Access: Direct access to problem components (variables, constraints, objectives)
  • CSV Export: Export parsed data to CSV files for further analysis
  • Problem Comparison: Compare two LP problems to identify differences
  • Type Safety: Full type hints for better IDE support and development experience

Installation

pip install parse_lp

Quick Start

from parse_lp import LpParser

# Parse an LP file
parser = LpParser("path/to/problem.lp")
parser.parse()

# Access problem information
print(f"Problem: {parser.name}")
print(f"Sense: {parser.sense}")
print(f"Variables: {parser.variable_count()}")
print(f"Constraints: {parser.constraint_count()}")

# Modify the problem
parser.update_objective_coefficient("OBJ", "x1", 5.0)
parser.rename_variable("x2", "production")
parser.update_constraint_rhs("C1", 100.0)

# Write back to LP format
modified_lp = parser.to_lp_string()
parser.save_to_file("modified_problem.lp")

# Analyze problem structure and detect issues
analysis = parser.analyze()
print(f"Matrix density: {analysis['summary']['density']:.4f}")
print(f"Issues found: {len(analysis['issues'])}")

# Export to CSV files
parser.to_csv("output_directory/")

Usage Examples

Basic Parsing and Information

from parse_lp import LpParser

parser = LpParser("optimization_problem.lp")
parser.parse()

# Get problem overview
print(f"Problem Name: {parser.name}")
print(f"Optimization Sense: {parser.sense}")
print(f"Variables: {parser.variable_count()}")
print(f"Constraints: {parser.constraint_count()}")
print(f"Objectives: {parser.objective_count()}")

Accessing Problem Data

# Access objectives
for i, objective in enumerate(parser.objectives):
    print(f"Objective {i+1}: {objective['name']}")
    for coef in objective['coefficients']:
        print(f"  {coef['name']}: {coef['value']}")

# Access variables
for var_name, var_info in parser.variables.items():
    print(f"Variable {var_name}:")
    print(f"  Type: {var_info['var_type']}")
    if 'bounds' in var_info:
        bounds = var_info['bounds']
        if 'lower' in bounds:
            print(f"  Lower bound: {bounds['lower']}")
        if 'upper' in bounds:
            print(f"  Upper bound: {bounds['upper']}")

# Access constraints
for constraint in parser.constraints:
    print(f"Constraint {constraint['name']}:")
    print(f"  Type: {constraint['type']}")
    if constraint['type'] == 'standard':
        print(f"  Operator: {constraint['operator']}")
        print(f"  RHS: {constraint['rhs']}")
        print(f"  Coefficients: {len(constraint['coefficients'])}")

CSV Export

import os

# Create output directory
os.makedirs("output", exist_ok=True)

# Export to CSV files
parser.to_csv("output/")

# Files created:
# - output/variables.csv
# - output/constraints.csv
# - output/objectives.csv

Problem Analysis

Analyze problem structure, detect potential issues, and get comprehensive statistics.

from parse_lp import LpParser

parser = LpParser("problem.lp")
parser.parse()

# Get complete analysis
analysis = parser.analyze()

# Summary statistics
summary = analysis['summary']
print(f"Problem: {summary['name']}")
print(f"Sense: {summary['sense']}")
print(f"Variables: {summary['variable_count']}")
print(f"Constraints: {summary['constraint_count']}")
print(f"Nonzeros: {summary['total_nonzeros']}")
print(f"Matrix density: {summary['density']:.4f}")

# Sparsity metrics
sparsity = analysis['sparsity']
print(f"Variables per constraint: {sparsity['min_vars_per_constraint']} - {sparsity['max_vars_per_constraint']}")

# Variable type distribution
var_types = analysis['variables']['type_distribution']
print(f"Variable types: {var_types}")

# Coefficient ranges
coeffs = analysis['coefficients']
print(f"Constraint coefficients: {coeffs['constraint_coeff_range']}")
print(f"Objective coefficients: {coeffs['objective_coeff_range']}")
print(f"Coefficient ratio: {coeffs['coefficient_ratio']:.2f}")

# Check for issues (warnings and errors)
for issue in analysis['issues']:
    print(f"[{issue['severity']}] {issue['category']}: {issue['message']}")

Analysis with custom thresholds:

# Customize thresholds for issue detection
analysis = parser.analyze_with_config(
    large_coeff_threshold=1e8,      # Flag coefficients above this
    small_coeff_threshold=1e-10,    # Flag coefficients below this
    ratio_threshold=1e5             # Flag if max/min ratio exceeds this
)

Get issues only:

# Get just the detected issues without full analysis
issues = parser.get_issues()

for issue in issues:
    print(f"[{issue['severity']}] {issue['category']}: {issue['message']}")
    if issue['details']:
        print(f"  Details: {issue['details']}")

Issue types detected:

  • Invalid variable bounds (lower > upper)
  • Numerical scaling warnings (large coefficients, high ratios)
  • Empty constraints (no variables)
  • Unused variables (not in any constraint or objective)
  • Fixed variables (lower bound = upper bound)
  • Singleton constraints (only one variable)

Problem Modification

from parse_lp import LpParser

# Parse an existing LP file
parser = LpParser("optimization_problem.lp")
parser.parse()

# Modify objectives
parser.update_objective_coefficient("profit", "x1", 5.0)
parser.rename_objective("profit", "total_profit")

# Modify constraints
parser.update_constraint_coefficient("capacity", "x1", 2.0)
parser.update_constraint_rhs("capacity", 200.0)
parser.rename_constraint("capacity", "production_limit")

# Modify variables
parser.rename_variable("x1", "production_a")
parser.update_variable_type("production_a", "integer")

# Set problem properties
parser.set_problem_name("Modified Optimization Problem")
parser.set_sense("minimize")

# Write back to LP format
modified_lp_content = parser.to_lp_string()
parser.save_to_file("modified_problem.lp")

# Verify round-trip compatibility
new_parser = LpParser("modified_problem.lp")
new_parser.parse()
print(f"Successfully modified and re-parsed: {new_parser.name}")

Problem Comparison

# Parse two different versions of a problem
parser1 = LpParser("problem_v1.lp")
parser1.parse()

parser2 = LpParser("problem_v2.lp")
parser2.parse()

# Compare the problems
diff = parser1.compare(parser2)

print("Comparison Results:")
print(f"Name changed: {diff['name_changed']}")
print(f"Sense changed: {diff['sense_changed']}")
print(f"Variable count difference: {diff['variable_count_diff']}")
print(f"Added variables: {diff['added_variables']}")
print(f"Removed variables: {diff['removed_variables']}")
print(f"Modified variables: {diff['modified_variables']}")
print(f"Added constraints: {diff['added_constraints']}")
print(f"Removed constraints: {diff['removed_constraints']}")

Objectives Structure

[
    {
        "name": "objective_name",
        "coefficients": [
            {"name": "variable_name", "value": 1.5},
            {"name": "another_var", "value": -2.0}
        ]
    }
]

Variables Structure

{
    "variable_name": {
        "name": "variable_name",
        "var_type": "Continuous",  # or "Binary", "Integer", etc.
        "bounds": {  # Optional
            "lower": 0.0,  # Optional
            "upper": 100.0  # Optional
        }
    }
}

Constraints Structure

[
    {
        "name": "constraint_name",
        "type": "standard",  # or "sos"
        "sense": "LessOrEqual",  # "Equal", "GreaterOrEqual"
        "rhs": 10.0,
        "coefficients": [
            {"name": "variable_name", "value": 2.0}
        ]
    },
    {
        "name": "sos_constraint",
        "type": "sos",
        "sos_type": "S1",  # or "S2"
        "weights": [
            {"name": "var1", "value": 1.0},
            {"name": "var2", "value": 2.0}
        ]
    }
]

Modification Methods

Objective Methods

  • update_objective_coefficient(obj_name, var_name, coefficient) - Update or add coefficient
  • rename_objective(old_name, new_name) - Rename an objective
  • remove_objective(obj_name) - Remove an objective

Constraint Methods

  • update_constraint_coefficient(const_name, var_name, coefficient) - Update or add coefficient
  • update_constraint_rhs(const_name, new_rhs) - Update right-hand side value
  • rename_constraint(old_name, new_name) - Rename a constraint
  • remove_constraint(const_name) - Remove a constraint

Variable Methods

  • rename_variable(old_name, new_name) - Rename variable across problem
  • update_variable_type(var_name, var_type) - Change variable type
  • remove_variable(var_name) - Remove variable from problem

Problem Methods

  • set_problem_name(name) - Set problem name
  • set_sense(sense) - Set optimization sense ("maximize" or "minimize")

Writing Methods

  • to_lp_string() - Generate LP format string
  • to_lp_string_with_options(**options) - Generate with custom formatting
  • save_to_file(filepath) - Save to LP file

Analysis Methods

  • analyze() - Get complete problem analysis including statistics and issues
  • analyze_with_config(large_coeff_threshold, small_coeff_threshold, ratio_threshold) - Analysis with custom thresholds
  • get_issues() - Get only detected issues/warnings without full analysis

Variable Types

Supported variable types for update_variable_type():

  • "binary" - Binary variables (0 or 1)
  • "integer" - General integer variables
  • "general" - Continuous variables (default)
  • "free" - Free variables (no bounds)
  • "semicontinuous" - Semi-continuous variables

Supported LP Format Features

  • Multiple objective functions
  • Standard constraints (≤, =, ≥)
  • Variable bounds
  • Variable types (continuous, binary, integer)
  • SOS (Special Ordered Sets) constraints
  • Problem names and comments
  • Scientific notation in coefficients

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.

Contributing

Issues and pull requests are welcome at: https://github.com/dandxy89/lp_parser_rs

make build
make install
make unit-test

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

parse_lp-3.2.0.tar.gz (1.3 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

parse_lp-3.2.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (479.0 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

parse_lp-3.2.0-cp39-abi3-win_amd64.whl (346.3 kB view details)

Uploaded CPython 3.9+Windows x86-64

parse_lp-3.2.0-cp39-abi3-win32.whl (325.2 kB view details)

Uploaded CPython 3.9+Windows x86

parse_lp-3.2.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (495.2 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

parse_lp-3.2.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl (521.6 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ s390x

parse_lp-3.2.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (618.1 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ppc64le

parse_lp-3.2.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (489.9 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARMv7l

parse_lp-3.2.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (483.6 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

parse_lp-3.2.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl (533.5 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.5+ i686

parse_lp-3.2.0-cp39-abi3-macosx_11_0_arm64.whl (444.4 kB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

parse_lp-3.2.0-cp39-abi3-macosx_10_12_x86_64.whl (456.0 kB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file parse_lp-3.2.0.tar.gz.

File metadata

  • Download URL: parse_lp-3.2.0.tar.gz
  • Upload date:
  • Size: 1.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: maturin/1.11.5

File hashes

Hashes for parse_lp-3.2.0.tar.gz
Algorithm Hash digest
SHA256 a54ec1cbd276e4672ed237a1a63ad6037d7d32883dbd4ba9b19c60fc1b25bc40
MD5 1b793274217a0a489f0c9bd2bb9a6381
BLAKE2b-256 600816f5ee08517a87d5dd663174cc71c4a04be6e8ca9f210d72ee8ab0990968

See more details on using hashes here.

File details

Details for the file parse_lp-3.2.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for parse_lp-3.2.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 068587a7d46ed1a6f11d5549294bd5da13f87372ffa4b8a3a383adcd7c3f7cbd
MD5 7f915d6db9e05d34322c44fd8822762d
BLAKE2b-256 304e53f1959d715b6f27b7db38fc212bfa31de9a49dddf6971bf5c47211d6ba5

See more details on using hashes here.

File details

Details for the file parse_lp-3.2.0-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: parse_lp-3.2.0-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 346.3 kB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: maturin/1.11.5

File hashes

Hashes for parse_lp-3.2.0-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 a17ce8a0091197e22ba01fa57d6fdd00780670736e5d97fcff2d4d6172294363
MD5 1ce24da80abfef52d42c4200c00dea1a
BLAKE2b-256 ca33643bd50d351970e83e42425b09e42d2419d7f2aad8a51bb978a057454fbe

See more details on using hashes here.

File details

Details for the file parse_lp-3.2.0-cp39-abi3-win32.whl.

File metadata

  • Download URL: parse_lp-3.2.0-cp39-abi3-win32.whl
  • Upload date:
  • Size: 325.2 kB
  • Tags: CPython 3.9+, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: maturin/1.11.5

File hashes

Hashes for parse_lp-3.2.0-cp39-abi3-win32.whl
Algorithm Hash digest
SHA256 29d48657963e9082107acb7b8c0276ecab56810e77bc929c4d426162eb9050d9
MD5 96c22329313cc9c2a5d059e5f350a059
BLAKE2b-256 478dc426cc3b36517c4c5d337f7ced3a4fb68a0b4e83aaf3f53d9a0867f9abb5

See more details on using hashes here.

File details

Details for the file parse_lp-3.2.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for parse_lp-3.2.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 de0a2d75aa498fcae1f9424c28dfdf2bd3c965a2fd250169731e852d67a42bf4
MD5 c9676c9eec664d27a90c488a714252bd
BLAKE2b-256 4c646030a18ce1f13cad0af1d0cf6aa6fef47a602ed3659a65c4898b812965be

See more details on using hashes here.

File details

Details for the file parse_lp-3.2.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl.

File metadata

File hashes

Hashes for parse_lp-3.2.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl
Algorithm Hash digest
SHA256 5518908ed4085b399a6a1ab575cac1e3146e0424d44c2d7f61309f7ca186c5d0
MD5 c612c08829e4b797b00aa0e2fdac15ff
BLAKE2b-256 27bb06beb473368bc2ef7822107f62f66966ca4f69ccda4cfd43fcc29988b04a

See more details on using hashes here.

File details

Details for the file parse_lp-3.2.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl.

File metadata

File hashes

Hashes for parse_lp-3.2.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
Algorithm Hash digest
SHA256 55a9c4875982b2b3efba1029b25a4cc728960191317b6df905a450a40222c850
MD5 82e894e163ef87e01ae9f4f033283c34
BLAKE2b-256 8242c7400fb8e57583168198708de71dd9a685bba605458d4a4265d703c9e6bc

See more details on using hashes here.

File details

Details for the file parse_lp-3.2.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for parse_lp-3.2.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 26ec54b1add6c9ed680b22ae9318b5a4ca50991471ff803f43202c2e3588572d
MD5 f57eff60f1b783d8e8e5644172e9f1e7
BLAKE2b-256 4d98b498c512406f189e8e782800a69b99cbca5dac261a2c35ba331436de7679

See more details on using hashes here.

File details

Details for the file parse_lp-3.2.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for parse_lp-3.2.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 b1a237d33b5c066bb625a6d017beb50f225c8bf1dfacca1e37b6a9fcf4b9846e
MD5 dcffe0d0159a5a0bcbd13302f04ebb5e
BLAKE2b-256 3ad6745f4c1ef9e47c9e86c99a6b5eadc97dda7eef4b3059062b37d103b863f7

See more details on using hashes here.

File details

Details for the file parse_lp-3.2.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl.

File metadata

File hashes

Hashes for parse_lp-3.2.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl
Algorithm Hash digest
SHA256 24f4c88020273a1837878c5577b58b375273ec72a53d57731eb131f8584cd865
MD5 750a4370192612f17ec90de27af1d590
BLAKE2b-256 89ae8f377bf6f724edd54ee4dca7f179b751c84a9e0fd98cd2f5dbe73a73b842

See more details on using hashes here.

File details

Details for the file parse_lp-3.2.0-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for parse_lp-3.2.0-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6d1728431203b3f0810dc52d03af2581a08153aaadad66ae73237dd45d87ea68
MD5 d68c0347d79e9af842205c930c44c917
BLAKE2b-256 f2417231ed77cc2a5c9ef92903506b372d501f65f5cf66bc2c92d622781421eb

See more details on using hashes here.

File details

Details for the file parse_lp-3.2.0-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for parse_lp-3.2.0-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 d3831b86be422b50ed1b963a3969b855bc019344313ced3768a2bd1f846c5ec0
MD5 83ea9227c741e9fa2ebfc621d9527777
BLAKE2b-256 c7924ed5faa7d894830e93d17dc80a7f1256cc5d5351d6c07c707f72fd96bf60

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page