CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pulp

PuLP is a linear and mixed integer programming modeler that provides an intuitive Python interface for creating, manipulating, and solving mathematical optimization problems.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

file-io.mddocs/

File I/O and Data Formats

Functions and classes for reading and writing optimization problems in standard formats (MPS, LP) and handling structured problem data. These capabilities enable interoperability with various optimization solvers and external systems.

Capabilities

Problem File Export

Functions for writing PuLP problems to standard optimization file formats that can be read by various solvers and optimization software.

def writeLP(prob, filename):
    """
    Write optimization problem to LP (Linear Program) format file.
    
    Parameters:
    - prob (LpProblem): Problem to export
    - filename (str): Output file path with .lp extension
    
    Note: LP format is human-readable and widely supported by solvers.
    Automatically handles line length constraints for CPLEX compatibility.
    
    Examples:
    writeLP(prob, "mymodel.lp")
    writeLP(prob, "/path/to/problem.lp")
    """

def writeMPS(prob, filename):
    """
    Write optimization problem to MPS (Mathematical Programming System) format file.
    
    Parameters:
    - prob (LpProblem): Problem to export
    - filename (str): Output file path with .mps extension
    
    Note: MPS format is the industry standard for optimization problems.
    Provides precise numerical representation and broad solver compatibility.
    
    Examples:
    writeMPS(prob, "mymodel.mps")
    writeMPS(prob, "/path/to/problem.mps")
    """

Usage examples:

# Create and solve a problem
prob = LpProblem("Export_Example", LpMinimize)
x = LpVariable("x", 0, 10)
y = LpVariable("y", 0, 5)
prob += 2*x + 3*y
prob += x + y <= 8
prob += 2*x - y >= 1

# Export to different formats
writeLP(prob, "example.lp")    # Human-readable LP format
writeMPS(prob, "example.mps")  # Standard MPS format

# Export with paths
import os
output_dir = "optimization_models"
os.makedirs(output_dir, exist_ok=True)

writeLP(prob, os.path.join(output_dir, f"{prob.name}.lp"))
writeMPS(prob, os.path.join(output_dir, f"{prob.name}.mps"))

# Export for different solvers
writeLP(prob, "for_glpk.lp")     # GLPK can read LP format
writeMPS(prob, "for_cplex.mps")  # CPLEX prefers MPS format
writeMPS(prob, "for_gurobi.mps") # Gurobi supports both, MPS more precise

Problem File Import

Functions for reading optimization problems from standard file formats into PuLP problem objects.

def readMPS(path, sense, dropConsNames=False):
    """
    Read optimization problem from MPS format file.
    
    Parameters:
    - path (str): Path to MPS file to read
    - sense: Optimization sense (LpMinimize or LpMaximize)
    - dropConsNames (bool): Whether to ignore constraint names from file
    
    Returns:
    LpProblem: Problem object created from MPS file data
    
    Note: Enables importing problems created by other optimization software
    or previously exported PuLP problems.
    
    Examples:
    prob = readMPS("external_model.mps", LpMinimize)
    prob = readMPS("backup.mps", LpMaximize, dropConsNames=True)
    """

Usage examples:

# Import problems from external sources
external_prob = readMPS("industry_model.mps", LpMinimize)
print(f"Imported problem: {external_prob.name}")
print(f"Variables: {len(external_prob.variables())}")
print(f"Constraints: {len(external_prob.constraints)}")

# Solve imported problem
status = external_prob.solve()
if status == LpStatusOptimal:
    print("External model solved successfully")
    for var in external_prob.variables():
        if value(var) is not None:
            print(f"{var.name} = {value(var)}")

# Import and modify problems
base_prob = readMPS("base_model.mps", LpMinimize)

# Add additional constraints to imported problem
additional_vars = [var for var in base_prob.variables() if 'production' in var.name]
if additional_vars:
    base_prob += lpSum(additional_vars) >= 100  # Minimum production constraint

# Re-export modified problem
writeMPS(base_prob, "modified_model.mps")

MPS Data Structure Classes

Classes for representing and manipulating MPS format components, providing detailed control over problem structure and data.

class MPS:
    """
    Complete MPS format representation containing all problem components.
    Provides structured access to problem data for advanced manipulation.
    """
    def __init__(self): ...
    
    @property
    def variables(self): ...    # Access to variable definitions
    @property
    def constraints(self): ...  # Access to constraint definitions  
    @property
    def objective(self): ...    # Access to objective function
    @property
    def parameters(self): ...   # Access to problem parameters

class MPSParameters:
    """
    Problem parameters section of MPS format.
    Contains solver settings and problem configuration data.
    """
    def __init__(self): ...

class MPSObjective:
    """
    Objective function data in MPS format.
    Represents the cost/profit coefficients and optimization sense.
    """
    def __init__(self): ...
    
    @property
    def coefficients(self): ... # Variable coefficients in objective
    @property
    def sense(self): ...        # Minimization or maximization
    @property
    def name(self): ...         # Objective function name

class MPSVariable:
    """
    Variable data in MPS format.
    Contains variable definitions, bounds, and type information.
    """
    def __init__(self): ...
    
    @property
    def name(self): ...         # Variable name
    @property
    def bounds(self): ...       # Lower and upper bounds
    @property
    def variable_type(self): ... # Continuous, integer, or binary

class MPSConstraint:
    """
    Constraint data in MPS format.
    Represents constraint coefficients, bounds, and relationship types.
    """
    def __init__(self): ...
    
    @property
    def name(self): ...         # Constraint name
    @property
    def coefficients(self): ... # Variable coefficients
    @property
    def sense(self): ...        # <=, =, or >= relationship
    @property
    def rhs(self): ...          # Right-hand side value

class MPSCoefficient:
    """
    Individual coefficient data in MPS format.
    Represents variable-constraint coefficient pairs.
    """
    def __init__(self): ...
    
    @property
    def variable(self): ...     # Associated variable
    @property
    def constraint(self): ...   # Associated constraint  
    @property
    def value(self): ...        # Coefficient value

Usage examples:

# Advanced MPS file manipulation
def analyze_mps_structure(mps_file_path):
    """Analyze the structure of an MPS file."""
    prob = readMPS(mps_file_path, LpMinimize)
    
    print(f"Problem Analysis: {prob.name}")
    print(f"Variables: {len(prob.variables())}")
    print(f"Constraints: {len(prob.constraints)}")
    
    # Analyze variable types
    var_types = {}
    for var in prob.variables():
        var_type = var.cat
        var_types[var_type] = var_types.get(var_type, 0) + 1
    
    print("Variable types:")
    for vtype, count in var_types.items():
        print(f"  {vtype}: {count}")
    
    # Analyze constraint senses
    constraint_senses = {}
    for constraint in prob.constraints.values():
        sense = constraint.sense
        sense_str = LpConstraintSenses.get(sense, str(sense))
        constraint_senses[sense_str] = constraint_senses.get(sense_str, 0) + 1
    
    print("Constraint types:")
    for sense, count in constraint_senses.items():
        print(f"  {sense}: {count}")

# Create MPS data programmatically
def create_structured_mps_problem():
    """Create a problem with detailed MPS structure."""
    prob = LpProblem("Structured_MPS_Example", LpMinimize)
    
    # Create variables with detailed naming
    production_vars = LpVariable.dicts("production", 
                                     ["plant1", "plant2", "plant3"], 
                                     0, 1000, LpContinuous)
    
    binary_decisions = LpVariable.dicts("use_plant",
                                      ["plant1", "plant2", "plant3"],
                                      cat=LpBinary)
    
    # Structured constraints with meaningful names
    prob += (lpSum(production_vars), "total_production_limit", 2500)
    
    for plant in production_vars:
        # Production can only occur if plant is used
        prob += (production_vars[plant] <= 1000 * binary_decisions[plant], 
                f"production_logic_{plant}")
    
    # Objective with cost structure
    plant_costs = {"plant1": 10, "plant2": 12, "plant3": 8}
    fixed_costs = {"plant1": 1000, "plant2": 1200, "plant3": 800}
    
    total_cost = (lpSum([plant_costs[p] * production_vars[p] for p in production_vars]) +
                  lpSum([fixed_costs[p] * binary_decisions[p] for p in binary_decisions]))
    
    prob += total_cost
    
    return prob

# Export with detailed structure
structured_prob = create_structured_mps_problem()
writeMPS(structured_prob, "structured_example.mps")
writeLP(structured_prob, "structured_example.lp")

Sparse Matrix Support

Support for sparse matrix operations essential for large-scale optimization problems with sparse constraint matrices.

class Matrix:
    """
    Generic sparse matrix class using dictionary-based storage.
    Efficient representation for optimization problems with sparse coefficient matrices.
    """
    def __init__(self): ...
    
    def __getitem__(self, key): ...     # Access matrix elements
    def __setitem__(self, key, value): ... # Set matrix elements
    def keys(self): ...                 # Get all defined indices
    def values(self): ...               # Get all defined values
    def items(self): ...                # Get (index, value) pairs

Usage examples:

# Sparse constraint matrix for large problems
def create_sparse_transportation_problem(supply_points, demand_points, connections):
    """
    Create transportation problem with sparse connection matrix.
    Only creates variables for valid supply-demand connections.
    """
    prob = LpProblem("Sparse_Transportation", LpMinimize)
    
    # Sparse matrix to track which connections exist
    connection_matrix = Matrix()
    transport_vars = {}
    
    for supply, demand, cost in connections:
        # Only create variables for valid connections
        var_name = f"transport_{supply}_{demand}"
        transport_vars[(supply, demand)] = LpVariable(var_name, 0)
        connection_matrix[supply, demand] = cost
    
    # Supply constraints (only for connected supply points)
    supply_constraints = {}
    for supply in supply_points:
        connected_demands = [d for s, d in transport_vars.keys() if s == supply]
        if connected_demands:
            supply_constraints[supply] = lpSum([
                transport_vars[(supply, demand)] for demand in connected_demands
            ])
            prob += supply_constraints[supply] <= supply_points[supply]
    
    # Demand constraints (only for connected demand points)  
    demand_constraints = {}
    for demand in demand_points:
        connected_supplies = [s for s, d in transport_vars.keys() if d == demand]
        if connected_supplies:
            demand_constraints[demand] = lpSum([
                transport_vars[(supply, demand)] for supply in connected_supplies
            ])
            prob += demand_constraints[demand] >= demand_points[demand]
    
    # Sparse objective function
    transport_cost = lpSum([
        connection_matrix[supply, demand] * transport_vars[(supply, demand)]
        for supply, demand in transport_vars.keys()
    ])
    prob += transport_cost
    
    return prob, transport_vars, connection_matrix

# Example usage with sparse data
supply_capacities = {"S1": 100, "S2": 150, "S3": 120}
demand_requirements = {"D1": 80, "D2": 90, "D3": 70, "D4": 85}

# Only some supply-demand pairs are connected (sparse network)
valid_connections = [
    ("S1", "D1", 10), ("S1", "D3", 15),
    ("S2", "D1", 12), ("S2", "D2", 8), ("S2", "D4", 20),
    ("S3", "D2", 14), ("S3", "D3", 11), ("S3", "D4", 16)
]

sparse_prob, variables, costs = create_sparse_transportation_problem(
    supply_capacities, demand_requirements, valid_connections
)

# Export sparse problem
writeMPS(sparse_prob, "sparse_transportation.mps")
print(f"Created sparse problem with {len(variables)} variables")
print(f"Density: {len(variables)}/{len(supply_capacities)*len(demand_requirements)} = {len(variables)/(len(supply_capacities)*len(demand_requirements)):.2%}")

File Format Utilities

Additional utilities for handling different file formats and ensuring compatibility across solvers.

# Batch export to multiple formats
def export_problem_suite(problem, base_name):
    """Export problem to all supported formats."""
    formats = {
        '.lp': writeLP,
        '.mps': writeMPS
    }
    
    exported_files = []
    for extension, write_func in formats.items():
        filename = f"{base_name}{extension}"
        try:
            write_func(problem, filename)
            exported_files.append(filename)
            print(f"Exported: {filename}")
        except Exception as e:
            print(f"Failed to export {filename}: {e}")
    
    return exported_files

# Problem format conversion
def convert_problem_format(input_file, output_file, target_sense=LpMinimize):
    """Convert between problem file formats."""
    # Determine input format from extension
    if input_file.lower().endswith('.mps'):
        prob = readMPS(input_file, target_sense)
    else:
        raise ValueError(f"Unsupported input format: {input_file}")
    
    # Determine output format and write
    if output_file.lower().endswith('.lp'):
        writeLP(prob, output_file)
    elif output_file.lower().endswith('.mps'):
        writeMPS(prob, output_file)
    else:
        raise ValueError(f"Unsupported output format: {output_file}")
    
    print(f"Converted {input_file} to {output_file}")

# Example usage
prob = LpProblem("Multi_Export_Example", LpMinimize)
x = LpVariable("x", 0, 10)
prob += 2*x
prob += x >= 5

# Export to all formats
exported = export_problem_suite(prob, "multi_format_example")

# Convert existing MPS to LP
# convert_problem_format("existing_model.mps", "converted_model.lp")

Install with Tessl CLI

npx tessl i tessl/pypi-pulp

docs

constants-enums.md

core-modeling.md

file-io.md

index.md

mathematical-operations.md

solver-interfaces.md

utility-functions.md

tile.json