### Setup Development Environment Source: https://github.com/open-energy-transition/linopy/blob/master/CLAUDE.md Create a virtual environment, activate it, and install linopy with development and solver dependencies using uv. ```bash python -m venv venv source venv/bin/activate pip install uv uv pip install -e .[dev,solvers] ``` -------------------------------- ### Example: Piecewise Linear Approximation (SOS2) Setup Source: https://github.com/open-energy-transition/linopy/blob/master/doc/sos-constraints.md Initializes a Linopy model for approximating a function f(x) = x² over [0, 3] using SOS Type 2 constraints with defined breakpoints. ```python import numpy as np # Approximate f(x) = x² over [0, 3] with breakpoints breakpoints = pd.Index([0, 1, 2, 3], name="breakpoints") x_vals = xr.DataArray(breakpoints.to_series()) y_vals = x_vals**2 # Create model m = linopy.Model() ``` -------------------------------- ### Load Benchmark Model Example Source: https://github.com/open-energy-transition/linopy/blob/master/doc/release_notes.md A new 'examples' module is available, providing example models. This snippet shows how to load the benchmark model. ```python m = linopy.examples.benchmark_model() ``` -------------------------------- ### Install cuPDLPx solver for GPU acceleration Source: https://github.com/open-energy-transition/linopy/blob/master/doc/prerequisites.md Install the cuPDLPx solver for GPU-accelerated optimization. This requires compatible NVIDIA hardware and CUDA installation. ```bash pip install cupdlpx ``` -------------------------------- ### Install and Use Pre-commit Hooks Source: https://github.com/open-energy-transition/linopy/blob/master/doc/contributing.md Install pre-commit for code linting and formatting. Run `pre-commit install` to activate it on commits or `pre-commit run --all` to manually check all files. ```bash pip install pre-commit ``` ```bash pre-commit install ``` ```bash pre-commit run --all ``` -------------------------------- ### Install Linopy with solver support Source: https://github.com/open-energy-transition/linopy/blob/master/doc/prerequisites.md Install Linopy along with common solver wrappers. This command installs the necessary packages to interface with various optimization solvers. ```bash pip install linopy[solvers] ``` -------------------------------- ### Install cuPDLPx Solver Source: https://github.com/open-energy-transition/linopy/blob/master/doc/gpu-acceleration.md Install the cuPDLPx solver using pip after ensuring the CUDA Toolkit is installed. This solver is experimental and optimized for GPUs. ```bash # Install CUDA Toolkit first (if not already installed) # Follow instructions at: https://developer.nvidia.com/cuda-downloads # Install cuPDLPx pip install cupdlpx>=0.1.2 ``` -------------------------------- ### Set up Linopy Development Environment Source: https://github.com/open-energy-transition/linopy/blob/master/README.md Installs linopy in editable mode and sets up development dependencies. Ensure you have a virtual environment activated. ```sh python -m venv venv source venv/bin/activate pip install uv uv pip install -e .[dev,solvers] pytest ``` -------------------------------- ### Quick Start: Adding a Piecewise Linear Constraint Source: https://github.com/open-energy-transition/linopy/blob/master/doc/piecewise-linear-constraints.md This example demonstrates the basic usage of `piecewise()` and `add_piecewise_constraints()` to model a piecewise linear relationship between two variables. Ensure `linopy` is imported and a `Model` is initialized. ```python import linopy m = linopy.Model() x = m.add_variables(name="x", lower=0, upper=100) y = m.add_variables(name="y") # y equals a piecewise linear function of x x_pts = linopy.breakpoints([0, 30, 60, 100]) y_pts = linopy.breakpoints([0, 36, 84, 170]) m.add_piecewise_constraints(linopy.piecewise(x, x_pts, y_pts) == y) ``` -------------------------------- ### Example 1: Facility Location (SOS1) Source: https://github.com/open-energy-transition/linopy/blob/master/doc/sos-constraints.md An example demonstrating how to use SOS Type 1 constraints to model a facility location problem where at most one facility can be built. ```APIDOC ## Example 1: Facility Location (SOS1) ```python import linopy import pandas as pd import xarray as xr # Problem data locations = pd.Index([0, 1, 2, 3], name="locations") costs = xr.DataArray([100, 150, 120, 80], coords=[locations]) benefits = xr.DataArray([200, 300, 250, 180], coords=[locations]) # Create model m = linopy.Model() # Decision variables: build facility at location i build = m.add_variables(coords=[locations], name="build", lower=0, upper=1) # SOS1 constraint: at most one facility can be built m.add_sos_constraints(build, sos_type=1, sos_dim="locations") # Objective: maximize net benefit net_benefit = benefits - costs m.add_objective(-((net_benefit * build).sum())) # Solve m.solve(solver_name="gurobi") if m.status == "ok": solution = build.solution.to_pandas() selected_location = solution[solution > 0.5].index[0] print(f"Build facility at location {selected_location}") ``` ``` -------------------------------- ### Install Development Dependencies Source: https://github.com/open-energy-transition/linopy/blob/master/doc/contributing.md Install linopy with development and solver dependencies using pip. ```bash pip install -e .[dev,solvers] ``` -------------------------------- ### Install Linopy using pip Source: https://github.com/open-energy-transition/linopy/blob/master/doc/prerequisites.md Use this command to install the Linopy library via pip. Ensure Python 3.9 or later is installed. ```bash pip install linopy ``` -------------------------------- ### Check Installed Solvers and Configure Display Options in Linopy Source: https://context7.com/open-energy-transition/linopy/llms.txt Use `linopy.available_solvers` to see which solvers are installed. Configure display settings globally using `linopy.options` or temporarily with a context manager. Options can also be set for explicit print calls. ```python import linopy # Check which solvers are installed print(linopy.available_solvers) # e.g. ['highs', 'glpk'] or ['gurobi', 'highs', 'cplex'] # Change display settings globally linopy.options["display_max_rows"] = 50 linopy.options["display_max_terms"] = 10 # Or temporarily via context manager with linopy.options as opts: opts.set_value(display_max_rows=5) print(x) # abbreviated printout # original settings restored here # Use options when printing large objects explicitly x.print(display_max_rows=100) ``` -------------------------------- ### Install HiGHS solver Source: https://github.com/open-energy-transition/linopy/blob/master/doc/prerequisites.md Install the HiGHS solver, a recommended free and open-source option for linear programming. This is a direct installation of the highspy package. ```bash pip install highspy ``` -------------------------------- ### Example: Facility Location (SOS1) Source: https://github.com/open-energy-transition/linopy/blob/master/doc/sos-constraints.md Illustrates how to use SOS Type 1 constraints to model a facility location problem where at most one facility can be built. Solves for maximum net benefit. ```python import linopy import pandas as pd import xarray as xr # Problem data locations = pd.Index([0, 1, 2, 3], name="locations") costs = xr.DataArray([100, 150, 120, 80], coords=[locations]) benefits = xr.DataArray([200, 300, 250, 180], coords=[locations]) # Create model m = linopy.Model() # Decision variables: build facility at location i build = m.add_variables(coords=[locations], name="build", lower=0, upper=1) # SOS1 constraint: at most one facility can be built m.add_sos_constraints(build, sos_type=1, sos_dim="locations") # Objective: maximize net benefit net_benefit = benefits - costs m.add_objective(-((net_benefit * build).sum())) # Solve m.solve(solver_name="gurobi") if m.status == "ok": solution = build.solution.to_pandas() selected_location = solution[solution > 0.5].index[0] print(f"Build facility at location {selected_location}") ``` -------------------------------- ### Create and Activate Conda Environment Source: https://github.com/open-energy-transition/linopy/blob/master/benchmark/README.md Installs the necessary packages for the benchmark using a conda environment file. Use 'environment.fixed.yaml' for fixed package versions. ```bash conda env create -f environment.yaml conda activate linopy-benchmark ``` -------------------------------- ### Initialize Linopy Model Source: https://github.com/open-energy-transition/linopy/blob/master/examples/transport-tutorial.ipynb Imports necessary libraries and creates a linopy Model object. This is the starting point for defining optimization problems in linopy. ```python # Import of linopy and related modules import xarray as xr import linopy # Creation of a Model m = linopy.Model() ``` ```python from pyomo.environ import * model = ConcreteModel() ``` -------------------------------- ### Install Linopy using conda Source: https://github.com/open-energy-transition/linopy/blob/master/doc/prerequisites.md Use this command to install the Linopy library via conda from the conda-forge channel. Ensure Python 3.9 or later is installed. ```bash conda install -c conda-forge linopy ``` -------------------------------- ### Verify GPU Solver Installation Source: https://github.com/open-energy-transition/linopy/blob/master/doc/gpu-acceleration.md Check if GPU-accelerated solvers are available and detected by Linopy. This involves importing necessary modules and using helper functions to list available solvers. ```python import linopy from linopy.solver_capabilities import ( SolverFeature, get_available_solvers_with_feature, ) # Check available solvers print("All available solvers:", linopy.available_solvers) # Check GPU-accelerated solvers gpu_solvers = get_available_solvers_with_feature( SolverFeature.GPU_ACCELERATION, linopy.available_solvers ) print("GPU solvers:", gpu_solvers) ``` -------------------------------- ### Nblink Configuration for Notebook Examples Source: https://github.com/open-energy-transition/linopy/blob/master/doc/contributing.md Configure an nblink file to link Jupyter notebooks into the documentation. Adjust the 'path' to correctly point to your notebook file. ```json { "path" : "../../examples/foo.ipynb" } ``` -------------------------------- ### Create Optimization Model in Linopy Source: https://github.com/open-energy-transition/linopy/blob/master/doc/syntax.md Initializes an optimization model with variables, constraints, and an objective function using the linopy library in Python. Requires linopy and numpy to be installed. ```python from linopy import Model from numpy import arange def create_model(N): m = Model() x = m.add_variables(coords=[arange(N), arange(N)]) y = m.add_variables(coords=[arange(N), arange(N)]) m.add_constraints(x - y >= arange(N)) m.add_constraints(x + y >= 0) m.add_objective((2 * x).sum() + y.sum()) return m ``` -------------------------------- ### Create Optimization Model in Pyomo Source: https://github.com/open-energy-transition/linopy/blob/master/doc/syntax.md Constructs a concrete optimization model in Pyomo, defining sets, variables, constraints, and the objective function. Pyomo and numpy must be installed. ```python from numpy import arange from pyomo.environ import ConcreteModel, Constraint, Objective, Set, Var def create_model(N): m = ConcreteModel() m.N = Set(initialize=arange(N)) m.x = Var(m.N, m.N, bounds=(None, None)) m.y = Var(m.N, m.N, bounds=(None, None)) def bound1(m, i, j): return m.x[(i, j)] - m.y[(i, j)] >= i def bound2(m, i, j): return m.x[(i, j)] + m.y[(i, j)] >= 0 def objective(m): return sum(2 * m.x[(i, j)] + m.y[(i, j)] for i in m.N for j in m.N) m.con1 = Constraint(m.N, m.N, rule=bound1) m.con2 = Constraint(m.N, m.N, rule=bound2) m.obj = Objective(rule=objective) return m ``` -------------------------------- ### Run GPU-Enabled Pytest Tests Source: https://github.com/open-energy-transition/linopy/blob/master/CLAUDE.md Execute tests that require GPU hardware. Ensure cuPDLPx is installed and GPU hardware is available. ```bash pytest --run-gpu ``` -------------------------------- ### Example 2: Piecewise Linear Approximation (SOS2) Source: https://github.com/open-energy-transition/linopy/blob/master/doc/sos-constraints.md Illustrates the use of SOS Type 2 constraints for approximating a piecewise linear function, specifically f(x) = x². ```APIDOC ## Example 2: Piecewise Linear Approximation (SOS2) ```python import numpy as np # Approximate f(x) = x² over [0, 3] with breakpoints breakpoints = pd.Index([0, 1, 2, 3], name="breakpoints") x_vals = xr.DataArray(breakpoints.to_series()) y_vals = x_vals**2 # Create model m = linopy.Model() ``` ``` -------------------------------- ### Create Optimization Model in JuMP Source: https://github.com/open-energy-transition/linopy/blob/master/doc/syntax.md Defines an optimization model with variables, constraints, and an objective function using the JuMP package in Julia. Ensure JuMP is installed and imported. ```julia using JuMP function create_model(N) m = Model() @variable(m, x[1:N, 1:N]) @variable(m, y[1:N, 1:N]) @constraint(m, x - y .>= 0:(N-1)) @constraint(m, x + y .>= 0) @objective(m, Min, 2 * sum(x) + sum(y)) return m end ``` -------------------------------- ### Get Dual Values of Constraints Source: https://github.com/open-energy-transition/linopy/blob/master/doc/release_notes.md The matrices accessor of the Model class now has a 'dual' function to retrieve dual values of constraints after optimization. ```python model.matrices.dual() ``` -------------------------------- ### Create Named Dimensional Variable Source: https://github.com/open-energy-transition/linopy/blob/master/examples/creating-variables.ipynb Best practice example: Creates a named variable 'supply' with dimensions 'time' and 'station' using xarray DataArrays for bounds. ```python lower = xr.DataArray([1, 2, 3], dims=["time"]) upper = xr.DataArray([10, 11, 12, 13], dims=["station"]) m.add_variables(lower, upper, name="supply") ``` -------------------------------- ### Create an Infeasible Model Source: https://github.com/open-energy-transition/linopy/blob/master/examples/infeasible-model.ipynb Define a Linopy model with constraints that are intentionally contradictory to create an infeasible problem. This setup is useful for testing infeasibility detection. ```python import pandas as pd import linopy m = linopy.Model() time = pd.RangeIndex(10, name="time") x = m.add_variables(lower=0, coords=[time], name="x") y = m.add_variables(lower=0, coords=[time], name="y") m.add_constraints(x <= 5) m.add_constraints(y <= 5) m.add_constraints(x + y >= 12) ``` -------------------------------- ### Construct and Inspect an Empty Linopy Model Source: https://context7.com/open-energy-transition/linopy/llms.txt Demonstrates how to initialize a Linopy Model with options for dimension name enforcement and automatic masking. Shows how to inspect the initial state of an empty model. ```python import linopy import pandas as pd import numpy as np # --- basic model construction --- m = linopy.Model( force_dim_names=True, # raise if unnamed dimensions appear auto_mask=True, # skip variables/constraints where bounds/RHS are NaN ) time = pd.RangeIndex(5, name="t") gen = pd.Index(["solar", "wind"], name="gen") # inspect an empty model print(m) # Linopy LP model # =============== # Variables: (none) # Constraints: (none) # Status: initialized # model type is computed from variable types and objective # "LP", "MILP", "QP", "MIQP", etc. print(m.type) # "LP" print(m.nvars) # 0 print(m.ncons) # 0 ``` -------------------------------- ### Configure OETC Settings from Environment Variables Source: https://github.com/open-energy-transition/linopy/blob/master/examples/solve-on-oetc.ipynb Create OetcSettings by reading from environment variables, with optional keyword overrides. This is recommended for CI/CD and production. ```python # Create settings from environment variables # All required env vars must be set: OETC_EMAIL, OETC_PASSWORD, # OETC_NAME, OETC_AUTH_URL, OETC_ORCHESTRATOR_URL settings = OetcSettings.from_env() # Or override specific values via keyword arguments settings = OetcSettings.from_env( cpu_cores=8, disk_space_gb=50, ) ``` -------------------------------- ### Run All Pre-commit Hooks Source: https://github.com/open-energy-transition/linopy/blob/master/CLAUDE.md Execute all configured pre-commit hooks across the entire repository. ```bash pre-commit run --all-files ``` -------------------------------- ### Initialize a Linopy Model Source: https://github.com/open-energy-transition/linopy/blob/master/examples/creating-constraints.ipynb Create a new instance of a linopy Model. This is the first step before adding variables or constraints. ```python from linopy import Model m = Model() ``` -------------------------------- ### Initialize Model and Variables Source: https://github.com/open-energy-transition/linopy/blob/master/examples/creating-expressions.ipynb Sets up a Linopy model and adds two variables, 'x' and 'y', with specified dimensions and lower bounds. Requires pandas and xarray for coordinate definitions. ```python import pandas as pd import xarray as xr import linopy time = pd.Index(range(10), name="time") port = pd.Index(list("abcd"), name="port") m = linopy.Model() x = m.add_variables(lower=0, coords=[time], name="x") y = m.add_variables(lower=0, coords=[time, port], name="y") m ``` -------------------------------- ### Varying variable lower bounds Source: https://github.com/open-energy-transition/linopy/blob/master/examples/manipulating-models.ipynb Modifies the lower bound of a variable 'x' to a scalar value. This demonstrates how to adjust variable limits after initial model setup. ```python x.lower = 1 ``` -------------------------------- ### Display Solution for Disjunctive Piecewise Model Source: https://github.com/open-energy-transition/linopy/blob/master/examples/piecewise-linear-constraints.ipynb View the solution for power, cost, and backup variables from the model with disjunctive piecewise constraints. ```python m3.solution[["power", "cost", "backup"]].to_pandas() ``` -------------------------------- ### Solve Model and Get Objective Value Source: https://github.com/open-energy-transition/linopy/blob/master/README.md Solves the defined optimization problem and retrieves the optimal value of the objective function. The output shows the numerical result. ```python m.solve() m.objective.value ``` ```text 17.166 ``` -------------------------------- ### Initialize Linopy Model Source: https://github.com/open-energy-transition/linopy/blob/master/examples/create-a-model-with-coordinates.ipynb Initializes a new Linopy model. This is the first step before adding variables, constraints, or objectives. ```python import linopy m = linopy.Model() ``` -------------------------------- ### Explicit Method Selection for Piecewise Constraints Source: https://github.com/open-energy-transition/linopy/blob/master/doc/piecewise-linear-constraints.md Demonstrates how to explicitly specify the method for handling piecewise linear constraints. Options include 'sos2', 'incremental', 'lp', and 'auto'. ```python pw = linopy.piecewise(x, x_pts, y_pts) # Explicit SOS2 m.add_piecewise_constraints(pw == y, method="sos2") # Explicit incremental (requires monotonic x_pts) m.add_piecewise_constraints(pw == y, method="incremental") # Explicit LP (requires inequality + correct convexity + increasing x_pts) m.add_piecewise_constraints(pw >= y, method="lp") # Auto-select best method (default) m.add_piecewise_constraints(pw == y, method="auto") ``` -------------------------------- ### Initialize Model and Add Variables Source: https://github.com/open-energy-transition/linopy/blob/master/README.md Initializes a linopy Model and adds continuous variables with lower bounds and coordinates. The output shows the structure of the added variables. ```python import pandas as pd import linopy m = linopy.Model() days = pd.Index(["Mon", "Tue", "Wed", "Thu", "Fri"], name="day") apples = m.add_variables(lower=0, name="apples", coords=[days]) bananas = m.add_variables(lower=0, name="bananas", coords=[days]) apples ``` ```text Variable (day: 5) ----------------- [Mon]: apples[Mon] ∈ [0, inf] [Tue]: apples[Tue] ∈ [0, inf] [Wed]: apples[Wed] ∈ [0, inf] [Thu]: apples[Thu] ∈ [0, inf] [Fri]: apples[Fri] ∈ [0, inf] ``` -------------------------------- ### Display Solution for LP Piecewise Model Source: https://github.com/open-energy-transition/linopy/blob/master/examples/piecewise-linear-constraints.ipynb Show the solution for power and fuel variables from the model using the LP formulation for concave piecewise constraints. ```python m4.solution[["power", "fuel"]].to_pandas() ``` -------------------------------- ### Define Breakpoints for LP Formulation Source: https://github.com/open-energy-transition/linopy/blob/master/examples/piecewise-linear-constraints.ipynb Define strictly increasing x-breakpoints and corresponding y-breakpoints for a concave piecewise function. This setup allows Linopy to use a pure LP formulation. ```python x_pts4 = linopy.breakpoints([0, 40, 80, 120]) # Concave curve: decreasing marginal fuel per MW y_pts4 = linopy.breakpoints([0, 50, 90, 120]) ``` -------------------------------- ### Define Objective Function Source: https://github.com/open-energy-transition/linopy/blob/master/examples/piecewise-linear-constraints.ipynb Set up the objective function to minimize total costs, including fuel, startup, and backup power costs. ```python m6.add_objective((fuel + startup_cost * commit + 5 * backup).sum()) ``` -------------------------------- ### Get Solver-Specific Variable Attributes with Gurobi Source: https://github.com/open-energy-transition/linopy/blob/master/doc/release_notes.md The Variables class has a 'get_solver_attribute' function to parse solver-specific attributes. Currently, it only supports Gurobi models for attributes like 'SAObjUp' or 'RC'. ```python variables.get_solver_attribute("SAObjUp") ``` -------------------------------- ### Run Snakemake Benchmark Source: https://github.com/open-energy-transition/linopy/blob/master/benchmark/README.md Executes the Snakemake workflow to run the benchmarks. Adjust the number of cores as needed. ```bash snakemake --cores 4 ``` -------------------------------- ### Creating Segments from a List of Sequences Source: https://github.com/open-energy-transition/linopy/blob/master/doc/piecewise-linear-constraints.md Generates a DataArray with '_segment' and '_breakpoint' dimensions for defining disconnected segments. Accepts a list of tuples, where each tuple defines the start and end of a segment. ```python # Two disconnected segments: [0,10] and [50,100] x_seg = linopy.segments([(0, 10), (50, 100)]) y_seg = linopy.segments([(0, 15), (60, 130)]) ``` -------------------------------- ### Variable Arithmetic and Selection in Linopy Source: https://context7.com/open-energy-transition/linopy/llms.txt Demonstrates building expressions and constraints using arithmetic operators and selecting subsets of variables. Also shows how to fix, unfix, relax, and unrelax variables. ```python import linopy, pandas as pd, numpy as np m = linopy.Model() time = pd.RangeIndex(24, name="hour") gen = pd.Index(["solar","wind"], name="gen") p = m.add_variables(lower=0, coords=[time, gen], name="p") q = m.add_variables(lower=0, coords=[time, gen], name="q") # arithmetic → LinearExpression expr = 2 * p + q - 5 print(type(expr)) # linopy.expressions.LinearExpression # quadratic term quad = p ** 2 # QuadraticExpression dot = p @ p # equivalent dot product # anonymous constraint (not yet assigned to model) anon = p + q <= 200 # selection p_solar = p.sel(gen="solar") # Variable (hour: 24) p_hour0 = p.isel(hour=0) # Variable (gen: 2) scalar = p.at[0, "solar"] # ScalarVariable # summation over a dimension p_total = p.sum("gen") # LinearExpression (hour: 24) # groupby sum (aggregate by a mapping array) weights = xr.DataArray([1, 2], dims="gen", coords={"gen": gen}) grouped = p.groupby(weights).sum() # fix a variable to its solution after solving m.add_constraints(p <= 100, name="cap") m.objective = p.sum() m.solve() p.fix() # fixes p to current solution values p.fix(value=50.0) # fixes to explicit value p.unfix() # removes the equality constraint # relax integrality (useful for LP relaxation heuristics) b = m.add_variables(binary=True, coords=[time], name="on") b.relax() # converts to continuous [0, 1] b.unrelax() # restores binary type ``` -------------------------------- ### Build and solve a simple Linopy model Source: https://github.com/open-energy-transition/linopy/blob/master/examples/manipulating-models.ipynb Defines variables, constraints, and an objective, then solves the model using the 'highs' solver. This sets up the base model for subsequent modifications. ```python m = linopy.Model() time = pd.Index(range(10), name="time") x = m.add_variables( lower=0, coords=[time], name="x", ) y = m.add_variables(lower=0, coords=[time], name="y") factor = pd.Series(time, index=time) con1 = m.add_constraints(3 * x + 7 * y >= 10 * factor, name="con1") con2 = m.add_constraints(5 * x + 2 * y >= 3 * factor, name="con2") m.add_objective(x + 2 * y) m.solve(solver_name="highs") m.solve(solver_name="highs") sol = m.solution.to_dataframe() sol.plot(grid=True, ylabel="Optimal Value") ``` -------------------------------- ### Display Solution as Pandas DataFrame Source: https://github.com/open-energy-transition/linopy/blob/master/README.md Converts the optimization solution to a pandas DataFrame for easy viewing and analysis. The output table shows the optimal quantities of apples and bananas for each day. ```python m.solution.to_pandas() ``` ```text apples bananas day Mon 2.667 0 Tue 0 4 Wed 0 9 Thu 0 4 Fri 0 4 ``` -------------------------------- ### Create Model and Variables Source: https://github.com/open-energy-transition/linopy/blob/master/examples/migrating-from-pyomo.ipynb Initialize a linopy model and add variables with specified coordinates. The `.at[]` method is the recommended way to access scalar variables. ```python import pandas as pd import linopy m = linopy.Model() coords = pd.RangeIndex(10), ["a", "b"] x = m.add_variables(0, 100, coords, name="x") x ``` -------------------------------- ### Create an Optimization Model in Linopy Source: https://github.com/open-energy-transition/linopy/blob/master/examples/solve-on-remote.ipynb Define and build an optimization model locally using linopy. This involves adding variables, constraints, and an objective function. ```python from numpy import arange from xarray import DataArray from linopy import Model N = 10 m = Model() coords = [arange(N), arange(N)] x = m.add_variables(coords=coords, name="x") y = m.add_variables(coords=coords, name="y") m.add_constraints(x - y >= DataArray(arange(N))) m.add_constraints(x + y >= 0) m.add_objective((2 * x + y).sum()) m ``` -------------------------------- ### Format Code with Ruff Source: https://github.com/open-energy-transition/linopy/blob/master/CLAUDE.md Apply code formatting rules to the entire project using Ruff's formatter. ```bash ruff format . ``` -------------------------------- ### Import Linopy Testing Utilities Source: https://github.com/open-energy-transition/linopy/blob/master/examples/testing-framework.ipynb Import necessary functions for testing Linopy objects. These include assertions for variables, linear expressions, and constraints. ```python import pandas as pd import linopy from linopy.testing import assert_conequal, assert_linequal, assert_varequal ``` -------------------------------- ### Import necessary libraries Source: https://github.com/open-energy-transition/linopy/blob/master/examples/manipulating-models.ipynb Imports pandas, xarray, and linopy for model building and manipulation. ```python import pandas as pd import xarray as xr import linopy ``` -------------------------------- ### Check Available Solvers in Linopy Source: https://github.com/open-energy-transition/linopy/blob/master/examples/transport-tutorial.ipynb Print the list of available solvers that can be used with linopy. This helps in choosing an appropriate solver for the optimization task. ```python print(linopy.available_solvers) ``` -------------------------------- ### Model Initialization Source: https://github.com/open-energy-transition/linopy/blob/master/examples/coordinate-alignment.ipynb Initializes a Linopy model and adds a 'gen' variable with specified coordinates. ```python m3 = linopy.Model() hours = pd.RangeIndex(24, name="hour") techs = pd.Index(["solar", "wind", "gas"], name="tech") gen = m3.add_variables(lower=0, coords=[hours, techs], name="gen") ``` -------------------------------- ### Selecting a Subset of Variables using .loc Source: https://github.com/open-energy-transition/linopy/blob/master/examples/creating-expressions.ipynb Selects the first 5 time steps of variable 'x' using .loc. ```python x.loc[:5] ``` -------------------------------- ### Initialize SSH Connection with RemoteHandler Source: https://github.com/open-energy-transition/linopy/blob/master/examples/solve-on-remote.ipynb Set up an SSH connection to a remote server using linopy's RemoteHandler. This handler relies on the paramiko package and can automatically detect SSH keys if stored in default locations. ```python from linopy import RemoteHandler host = "your.host.de" username = "username" handler = RemoteHandler(host, username=username) ``` -------------------------------- ### Activate Experimental LP File Writing with Polars Source: https://github.com/open-energy-transition/linopy/blob/master/doc/release_notes.md Activate the new memory-efficient LP file writing method using the Polars package by setting the io_api argument in the solve function. ```python solve(..., io_api="lp-polars") ``` -------------------------------- ### Define Demand and Backup Constraints Source: https://github.com/open-energy-transition/linopy/blob/master/examples/piecewise-linear-constraints.ipynb Model demand constraints and introduce a backup variable to meet demand when the primary source is insufficient or committed. ```python demand6 = xr.DataArray([15, 70, 50], coords=[time]) backup = m6.add_variables(name="backup", lower=0, coords=[time]) m6.add_constraints(power + backup >= demand6, name="demand") ``` -------------------------------- ### Configure OETC Settings Manually Source: https://github.com/open-energy-transition/linopy/blob/master/examples/solve-on-oetc.ipynb Manually construct OetcCredentials and OetcSettings objects for OETC cloud solving. Ensure credentials are not hardcoded in production environments. ```python # Configure your OETC credentials # IMPORTANT: Never hardcode credentials in production code! # Use environment variables or secure credential management import os from linopy.remote.oetc import ( ComputeProvider, OetcCredentials, OetcHandler, OetcSettings, ) credentials = OetcCredentials( email=os.getenv("OETC_EMAIL", "your-email@example.com"), password=os.getenv("OETC_PASSWORD", "your-password"), ) # Configure OETC settings settings = OetcSettings( credentials=credentials, name="linopy-example-job", authentication_server_url="https://auth.oetcloud.com", # Replace with actual URL orchestrator_server_url="https://orchestrator.oetcloud.com", # Replace with actual URL compute_provider=ComputeProvider.GCP, cpu_cores=4, # Number of CPU cores to allocate disk_space_gb=20, # Disk space in GB delete_worker_on_error=False, # Keep worker for debugging if job fails ) print("OETC settings configured successfully") print(f"Solver: {settings.solver}") print(f"CPU cores: {settings.cpu_cores}") print(f"Disk space: {settings.disk_space_gb} GB") ``` -------------------------------- ### Create a Simple Variable Source: https://github.com/open-energy-transition/linopy/blob/master/examples/creating-variables.ipynb Creates a basic variable named 'x' with default infinite bounds. This variable can be used in expressions. ```python x = m.add_variables(name="x") x ``` -------------------------------- ### Applying .loc to an Existing Expression Source: https://github.com/open-energy-transition/linopy/blob/master/examples/creating-expressions.ipynb Selects the first 5 time steps of a pre-existing expression 'expr' (x + y) using .loc. ```python expr = x + y expr.loc[:5] ``` -------------------------------- ### Adding SOS Constraints Source: https://github.com/open-energy-transition/linopy/blob/master/doc/sos-constraints.md Demonstrates the basic usage of adding SOS Type 1 and SOS Type 2 constraints to variables in a Linopy model. ```APIDOC ## Adding SOS Constraints To add SOS constraints to variables in linopy: ```python import linopy import pandas as pd import xarray as xr # Create model m = linopy.Model() # Create variables with numeric coordinates coords = pd.Index([0, 1, 2], name="options") x = m.add_variables(coords=[coords], name="x", lower=0, upper=1) # Add SOS1 constraint m.add_sos_constraints(x, sos_type=1, sos_dim="options") # For SOS2 constraint breakpoints = pd.Index([0.0, 1.0, 2.0], name="breakpoints") lambdas = m.add_variables(coords=[breakpoints], name="lambdas", lower=0, upper=1) m.add_sos_constraints(lambdas, sos_type=2, sos_dim="breakpoints") ``` ``` -------------------------------- ### Select Subset of Constraint with .loc Source: https://github.com/open-energy-transition/linopy/blob/master/doc/release_notes.md The Constraint class now has a .loc method for selecting subsets by labels. ```python constraint.loc[["label1", "label2"]] ``` -------------------------------- ### Create an Optimization Model Source: https://github.com/open-energy-transition/linopy/blob/master/examples/solve-on-oetc.ipynb Define an optimization problem with decision variables and constraints using linopy. This model can then be solved on the OETC platform. ```python from numpy import arange from xarray import DataArray from linopy import Model # Create a medium-sized optimization problem N = 50 m = Model() # Define decision variables with coordinates coords = [arange(N), arange(N)] x = m.add_variables(coords=coords, name="x", lower=0) y = m.add_variables(coords=coords, name="y", lower=0) # Add constraints m.add_constraints(x - y >= DataArray(arange(N)), name="constraint1") m.add_constraints(x + y >= DataArray(arange(N) * 0.5), name="constraint2") m.add_constraints(x <= DataArray(arange(N) + 10), name="upper_bounds") # Set objective function m.add_objective((2 * x + y).sum()) print( f"Model created with {len(m.variables)} variable groups and {len(m.constraints)} constraint groups" ) m ``` -------------------------------- ### Display Solution DataFrame Source: https://github.com/open-energy-transition/linopy/blob/master/examples/piecewise-linear-constraints.ipynb Extract and display the 'commit', 'power', 'fuel', and 'backup' variables from the solved model as a pandas DataFrame. ```python m6.solution[["commit", "power", "fuel", "backup"]].to_pandas() ``` -------------------------------- ### Run GPU-Accelerated Tests Source: https://github.com/open-energy-transition/linopy/blob/master/doc/contributing.md Execute tests that require GPU hardware. Use `--run-gpu` to include GPU tests or `-m gpu --run-gpu` to run only GPU tests. ```bash pytest --run-gpu ``` ```bash pytest -m gpu --run-gpu ``` -------------------------------- ### LinearExpression Operations Source: https://context7.com/open-energy-transition/linopy/llms.txt Demonstrates various operations on LinearExpression objects, including summation, rolling sums, cumulative sums, and conversion to constraints. It also shows how to merge expressions and handle coordinate joins. ```APIDOC ## LinearExpression Operations ### Description Holds a labeled N-D array of linear combinations of variables. Supports the same xarray-style operations as `Variable`. Use `.sum()`, `.groupby()`, `.rolling()`, `.cumsum()`, `.diff()`, `.where()`, `.fillna()` freely. Compare with `<=`, `>=`, `==` to produce anonymous constraints. ### Methods - `.sum()`: Calculates the sum of all terms in the expression. - `.rolling(dim, window).sum()`: Computes a rolling sum along a specified dimension. - `.cumsum(dim)`: Computes the cumulative sum along a specified dimension. - `.to_constraint(op, value)`: Converts the expression into a constraint. - `.add(other_expr, join)`: Merges another expression with the current one, with options for coordinate joining. ### Example ```python import linopy, pandas as pd m = linopy.Model() time = pd.RangeIndex(5, name="t") x = m.add_variables(lower=0, coords=[time], name="x") y = m.add_variables(lower=0, coords=[time], name="y") # build expression expr = 3 * x + 2 * y - x.shift(t=1).fillna(0) # sum all terms total = expr.sum() # scalar LinearExpression # rolling sum (convolution-style constraint) rolling_sum = x.rolling(t=3).sum() # LinearExpression (t: 5) # cumulative sum cum = x.cumsum("t") # convert to Constraint directly con = expr.to_constraint(">=", 10) m.add_constraints(con, name="lb_con") # merge multiple expressions (concatenate terms) from linopy import merge merged = merge([3 * x, 2 * y]) # LinearExpression with 2 terms # explicit coordinate-join mode expr2 = x.add(y, join="outer") # fills missing coords with 0 # solution value (after solve) m.objective = x.sum() m.solve() print(expr.solution) # xr.DataArray of evaluated expression values ``` ``` -------------------------------- ### Run Linopy Tests Source: https://github.com/open-energy-transition/linopy/blob/master/doc/contributing.md Execute the test suite using pytest. Options include running all tests, tests with coverage, specific files, or specific functions. ```bash pytest ``` ```bash pytest --cov=./ --cov-report=xml linopy --doctest-modules test ``` ```bash pytest test/test_model.py ``` ```bash pytest test/test_model.py::test_model_creation ``` -------------------------------- ### Compute and Format Infeasibilities Source: https://context7.com/open-energy-transition/linopy/llms.txt Compute the Irreducible Infeasible Subsystem (IIS) when a solve returns an infeasible status (Gurobi or Xpress only). Returns constraint labels or a formatted string for diagnosis. ```python import linopy, pandas as pd m = linopy.Model() x = m.add_variables(lower=5, upper=10, name="x", coords=[pd.RangeIndex(1)]) m.add_constraints(x >= 20, name="lower_infeasible") # infeasible: x in [5,10] but >= 20 m.add_constraints(x <= 1, name="upper_infeasible") m.objective = x.sum() status, cond = m.solve(solver_name="gurobi") print(status, cond) # "warning" "infeasible" if cond == "infeasible": labels = m.compute_infeasibilities() print("Infeasible constraint labels:", labels) report = m.format_infeasibilities(display_max_terms=10) print(report) ``` -------------------------------- ### Model Gas Turbine with SOS2 PWL Constraint Source: https://github.com/open-energy-transition/linopy/blob/master/examples/piecewise-linear-constraints.ipynb Builds a linopy model for a gas turbine using the SOS2 formulation for its piecewise linear heat rate. This formulation is suitable for convex heat rates. ```python m1 = linopy.Model() power = m1.add_variables(name="power", lower=0, upper=100, coords=[time]) fuel = m1.add_variables(name="fuel", lower=0, coords=[time]) # piecewise(...) can be written on either side of the comparison # breakpoints are auto-broadcast to match the time dimension m1.add_piecewise_constraints( linopy.piecewise(power, x_pts1, y_pts1) == fuel, name="pwl", method="sos2", ) demand1 = xr.DataArray([50, 80, 30], coords=[time]) m1.add_constraints(power >= demand1, name="demand") m1.add_objective(fuel.sum()) ``` -------------------------------- ### Combining Different Selections with .loc Source: https://github.com/open-energy-transition/linopy/blob/master/examples/creating-expressions.ipynb Combines a subset of 'x' (first 4 time steps) with a subset of 'y' (time steps 5 onwards) using .loc. ```python x.loc[:4] + y.loc[5:] ``` -------------------------------- ### Model.to_file / Model.to_netcdf / linopy.read_netcdf Source: https://context7.com/open-energy-transition/linopy/llms.txt Provides methods for exporting the optimization model to standard file formats (LP, MPS) and for serializing the entire model state (including solutions) to NetCDF for persistence and later retrieval. ```APIDOC ## Model.to_file / Model.to_netcdf / linopy.read_netcdf ### Description Exports the model to an LP or MPS file (for inspection or external solvers), or serializes the entire model (variables, constraints, objective, solution) to NetCDF for storage and re-use. ### Methods - `Model.to_file(fn, io_api, slice_size, progress)`: Exports the model to an LP or MPS file. - `Model.to_netcdf(path)`: Serializes the entire model to a NetCDF file. - `linopy.read_netcdf(path)`: Reads a model from a NetCDF file. ### Parameters - `fn` (str): The filename for the exported LP or MPS file. - `io_api` (str): The API to use for writing the file ('lp' or 'mps'). - `slice_size` (int, optional): Size of slices for processing large models. - `progress` (bool, optional): Whether to display progress. - `path` (str): The path to the NetCDF file for reading or writing. ### Example ```python import linopy, pandas as pd m = linopy.Model() t = pd.RangeIndex(100, name="t") x = m.add_variables(lower=0, coords=[t], name="x") m.objective = x.sum() m.add_constraints(x <= 50, name="cap") # Write LP file (uses Polars for performance) m.to_file("/tmp/my_problem.lp", io_api="lp") m.to_file("/tmp/my_problem.mps", io_api="mps") # Persist to NetCDF (preserves coordinates, solution, duals) m.to_netcdf("/tmp/my_model.nc") # Read model from NetCDF # read_model = linopy.read_netcdf("/tmp/my_model.nc") ``` ``` -------------------------------- ### Add Piecewise Constraints with Auto-Broadcasting Source: https://github.com/open-energy-transition/linopy/blob/master/doc/piecewise-linear-constraints.md Demonstrates adding piecewise linear constraints where breakpoints are automatically broadcast to match the dimensions of the variables involved. This is useful when variables have extra dimensions like 'time'. ```python import pandas as pd import linopy m = linopy.Model() time = pd.Index([1, 2, 3], name="time") x = m.add_variables(name="x", lower=0, upper=100, coords=[time]) y = m.add_variables(name="y", coords=[time]) # 1D breakpoints auto-expand to match x's time dimension x_pts = linopy.breakpoints([0, 50, 100]) y_pts = linopy.breakpoints([0, 70, 150]) m.add_piecewise_constraints(linopy.piecewise(x, x_pts, y_pts) == y) ``` -------------------------------- ### Model Coal Plant with Incremental PWL Constraint Source: https://github.com/open-energy-transition/linopy/blob/master/examples/piecewise-linear-constraints.ipynb Builds a linopy model for a coal plant using the incremental formulation for its piecewise linear heat rate. This method is suitable for strictly monotonic heat rates. ```python m2 = linopy.Model() power = m2.add_variables(name="power", lower=0, upper=150, coords=[time]) fuel = m2.add_variables(name="fuel", lower=0, coords=[time]) # breakpoints are auto-broadcast to match the time dimension m2.add_piecewise_constraints( linopy.piecewise(power, x_pts2, y_pts2) == fuel, name="pwl", method="incremental", ) demand2 = xr.DataArray([80, 120, 50], coords=[time]) m2.add_constraints(power >= demand2, name="demand") m2.add_objective(fuel.sum()) ``` -------------------------------- ### Import necessary libraries Source: https://github.com/open-energy-transition/linopy/blob/master/examples/coordinate-alignment.ipynb Imports the required libraries for linopy, xarray, pandas, and numpy. ```python import numpy as np import pandas as pd import xarray as xr import linopy ``` -------------------------------- ### Postprocess and Display Solution in Pyomo Source: https://github.com/open-energy-transition/linopy/blob/master/examples/transport-tutorial.ipynb A Pyomo function to display the full solution for a variable. This includes using a SolverFactory and writing results to standard output. ```python def pyomo_postprocess(options=None, instance=None, results=None): model.x.display() from pyomo.opt import SolverFactory opt = SolverFactory("glpk") results = opt.solve(model) # Sends results to stdout results.write() print("\nDisplaying Solution\n" + '-'*60) pyomo_postprocess(None, model, results) ``` -------------------------------- ### Define Constraints in Pyomo Source: https://github.com/open-energy-transition/linopy/blob/master/examples/transport-tutorial.ipynb Equivalent Pyomo definitions for supply and demand constraints using rule functions. ```python def supply_rule(model, i): return sum(model.x[i,j] for j in model.j) <= model.a[i] model.supply = Constraint(model.i, rule=supply_rule, doc='Observe supply limit at plant i') def demand_rule(model, j): return sum(model.x[i,j] for i in model.i) >= model.b[j] model.demand = Constraint(model.j, rule=demand_rule, doc='Satisfy demand at market j') ``` -------------------------------- ### Plot Results for LP Piecewise Model Source: https://github.com/open-energy-transition/linopy/blob/master/examples/piecewise-linear-constraints.ipynb Visualize the results of the LP piecewise formulation, including the piecewise function and demand. ```python plot_pwl_results(m4, x_pts4, y_pts4, demand4, color="C4") ``` -------------------------------- ### Define Parameters in Pyomo Source: https://github.com/open-energy-transition/linopy/blob/master/examples/transport-tutorial.ipynb Equivalent Pyomo model definition for capacity, demand, distance, and freight parameters. ```python model.a = Param(model.i, initialize={'seattle':350,'san-diego':600}, doc='Capacity of plant i in cases') model.b = Param(model.j, initialize={'new-york':325,'chicago':300,'topeka':275}, doc='Demand at market j in cases') dtab = { ('seattle', 'new-york') : 2.5, ('seattle', 'chicago') : 1.7, ('seattle', 'topeka') : 1.8, ('san-diego','new-york') : 2.5, ('san-diego','chicago') : 1.8, ('san-diego','topeka') : 1.4, } model.d = Param(model.i, model.j, initialize=dtab, doc='Distance in thousands of miles') model.f = Param(initialize=90, doc='Freight in dollars per case per thousand miles') ``` -------------------------------- ### Reformulate SOS Constraints for Solvers Without Native Support Source: https://github.com/open-energy-transition/linopy/blob/master/doc/sos-constraints.md Automatically reformulate SOS constraints into binary and linear constraints using the Big-M method when solving with a solver that does not natively support them, such as HiGHS. ```python # Automatic reformulation during solve m.solve(solver_name="highs", reformulate_sos=True) # Or reformulate manually m.reformulate_sos_constraints() m.solve(solver_name="highs") ``` -------------------------------- ### Solar Availability Constraint Source: https://github.com/open-energy-transition/linopy/blob/master/examples/coordinate-alignment.ipynb Constrains solar generation based on a 24-hour availability profile. Standard alignment works as the profile covers all hours. ```python solar_avail = np.zeros(24) solar_avail[6:19] = 100 * np.sin(np.linspace(0, np.pi, 13)) solar_availability = xr.DataArray(solar_avail, dims=["hour"], coords={"hour": hours}) solar_gen = gen.sel(tech="solar") m3.add_constraints(solar_gen <= solar_availability, name="solar_avail") ``` -------------------------------- ### Add Optimization Variables to a Linopy Model Source: https://context7.com/open-energy-transition/linopy/llms.txt Shows how to add continuous, binary, and integer optimization variables to a Linopy model. Demonstrates setting bounds, coordinates, names, and masks, and accessing variable properties. ```python import linopy, pandas as pd, numpy as np m = linopy.Model() time = pd.RangeIndex(8760, name="hour") gen = pd.Index(["solar", "wind", "gas"], name="gen") # Continuous variable with per-generator capacity upper bounds cap = pd.Series({"solar": 500.0, "wind": 300.0, "gas": 200.0}, name="gen") prod = m.add_variables(lower=0, upper=cap, coords=[time, gen], name="production") # Variable (hour: 8760, gen: 3) # → production[h, g] ∈ [0, cap[g]] # Binary variable (unit commitment) commit = m.add_variables(coords=[time, gen], name="commit", binary=True) # Integer variable with a mask (only gas hours matter) gas_mask = (gen == "gas") startup = m.add_variables(lower=0, coords=[time, gen], name="startup", integer=True, mask=gas_mask) # Access variable properties print(prod.shape) # (8760, 3) print(prod.dims) # ('hour', 'gen') print(prod.lower) # xr.DataArray of lower bounds print(prod.upper) # xr.DataArray of upper bounds # Modify bounds after creation prod.upper = prod.upper * 0.9 # derate by 10 % ```