Power System Optimization with Amplpower package#

ampl_power.ipynb Open In Colab Kaggle Gradient Open In SageMaker Studio Lab Hits

Description: this notebook uses amplpower package to solver opf problems

Tags: amplpower, amplpy, energy, opf, matpower

Notebook author: Marcos Dominguez Velad <marcos@ampl.com>

Model author: Salvador Pineda Morente spineda@uma.es

Power system optimization is a critical aspect of modern electrical engineering, enabling efficient energy dispatch, grid stability, and cost-effective operation.

Amplpower is a powerful Python library designed to model and solve power system optimization problems using AMPL, a fast modeling language for large-scale mathematical optimization.

This package is developed by Salvador Pineda (spineda@uma.es), an Associate Professor at University of Malaga and member of the OASYS Research Group (https://sites.google.com/view/groupoasys/home).

What is Amplpower?#

Amplpower provides an intuitive interface to formulate and solve Optimal Power Flow (OPF) problems reading “.m” Matpower files.

Built on top of AMPL and compatible with the solvers AMPL support like Gurobi, IPOPT, HiGHS, Knitro, and many more.

Amplpower features#

  • 🐍 Python-native workflow - Combine optimization with virtual environments, data analysis, visualization, and your continuous integration / continuous development pipeline.

  • 🚀 Fastest model instantiation speed - AMPL is a modeling language designed to instantiate complex models fast, so it is ideal to write OPF problems, and other kinds of energy problems.

  • Flexibility to formulate the model - The package provide several options to choose the model being solved. Furthermore, the model is written in AMPL syntax, so it is easy to understand, modify, and enhance, letting researchers use the default models from the package or even write their own ones.

  • Support for multiple solvers - Every solver supported by AMPL is available, commercial and open-source ones, under the appropriate license.

For detailed documentation, visit: Amplpower Docs .

Since Amplpower is an open-source project, to run the models you will need an Ampl license. You can get a free Community Edition at https://portal.ampl.com, and activate the license (this happens by default when you run from Google Colab).

Notebook steps#

  1. Installing the amplpower package

  2. Activating an Ampl license for a notebook (by default in Google Colab it is a Community Edition license)

  3. Download a power system from Matpower, like ‘case9.m’ (https://github.com/MATPOWER/matpower/blob/master/data/case9.m)

  4. Solve case9.m for different OPF formulations.

# Install dependencies
%pip install amplpower
# Google Colab & Kaggle integration
from amplpy import AMPL, ampl_notebook

ampl = ampl_notebook(
    modules=["highs", "coin", "gurobi"],  # modules to install
    license_uuid="default",  # license to use
)  # instantiate AMPL object and register magics
!wget https://raw.githubusercontent.com/MATPOWER/matpower/refs/heads/master/data/case9.m -O case9.m
--2025-04-01 15:09:24--  https://raw.githubusercontent.com/MATPOWER/matpower/refs/heads/master/data/case9.m
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.110.133, 185.199.109.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2235 (2.2K) [text/plain]
Saving to: ‘case9.m’


case9.m               0%[                    ]       0  --.-KB/s               
case9.m             100%[===================>]   2.18K  --.-KB/s    in 0s      

2025-04-01 15:09:24 (31.4 MB/s) - ‘case9.m’ saved [2235/2235]
power_system_file = "case9.m"

# Import the PowerSystem class from the amplpower package
from amplpower import PowerSystem

# Load the case file
ps = PowerSystem(power_system_file)

# Solve the DC OPF
results = ps.solve_opf(
    opf_type="dc", switching="off", connectivity="off", solver="highs"
)

# Solve the AC OPF (rectangular formulation)
results = ps.solve_opf(
    opf_type="acrect", switching="off", connectivity="off", solver="gurobi"
)

# Solve the AC OPF (polar formulation)
results = ps.solve_opf(
    opf_type="acpolar", switching="off", connectivity="off", solver="ipopt"
)
=======Initializing the power system with case file: case9.m
Number of buses: 9
Number of lines: 9
Number of generators: 3
baseMVA: 100

Buses:
   BUS_I  BUS_TYPE   PD   QD   GS   BS  BUS_AREA  VM  VA  BASE_KV  ZONE  VMAX  \
0      0         3  0.0  0.0  0.0  0.0         1   1   0      345     1   1.1   
1      1         2  0.0  0.0  0.0  0.0         1   1   0      345     1   1.1   
2      2         2  0.0  0.0  0.0  0.0         1   1   0      345     1   1.1   
3      3         1  0.0  0.0  0.0  0.0         1   1   0      345     1   1.1   
4      4         1  0.9  0.3  0.0  0.0         1   1   0      345     1   1.1   

   VMIN      AMAX      AMIN  
0   0.9  1.570796 -1.570796  
1   0.9  1.570796 -1.570796  
2   0.9  1.570796 -1.570796  
3   0.9  1.570796 -1.570796  
4   0.9  1.570796 -1.570796  

Generators:
   GEN_BUS     PG      QG  QMAX  QMIN     VG  MBASE  GEN_STATUS  PMAX  PMIN  \
0        0  0.723  0.2703   3.0  -3.0  1.040    100           1   2.5   0.1   
1        1  1.630  0.0654   3.0  -3.0  1.025    100           1   3.0   0.1   
2        2  0.850 -0.1095   3.0  -3.0  1.025    100           1   2.7   0.1   

   ...  PC2  QC1MIN  QC1MAX  QC2MIN  QC2MAX  RAMP_AGC  RAMP_10  RAMP_30  \
0  ...    0       0       0       0       0         0        0        0   
1  ...    0       0       0       0       0         0        0        0   
2  ...    0       0       0       0       0         0        0        0   

   RAMP_Q  APF  
0       0    0  
1       0    0  
2       0    0  

[3 rows x 21 columns]

Branches:
   F_BUS  T_BUS    BR_R    BR_X   BR_B  RATE_A  RATE_B  RATE_C  TAP  SHIFT  \
0      0      3  0.0000  0.0576  0.000     2.5     2.5     2.5    0      0   
1      3      4  0.0170  0.0920  0.158     2.5     2.5     2.5    0      0   
2      4      5  0.0390  0.1700  0.358     1.5     1.5     1.5    0      0   
3      2      5  0.0000  0.0586  0.000     3.0     3.0     3.0    0      0   
4      5      6  0.0119  0.1008  0.209     1.5     1.5     1.5    0      0   

   BR_STATUS  ANGMIN  ANGMAX  
0          1    -360     360  
1          1    -360     360  
2          1    -360     360  
3          1    -360     360  
4          1    -360     360  

Generator Costs:
   MODEL  STARTUP  SHUTDOWN  NCOST  COST_2  COST_1  COST_0
0      2     1500         0      3  0.1100     5.0     150
1      2     2000         0      3  0.0850     1.2     600
2      2     3000         0      3  0.1225     1.0     335
=======Computing initial bigM values for DC power flow
=======Computing initial bigM values for AC power flow
=======Solving OPF (dc) with switching off and connectivity off with solver highs and options outlev=1 timelimit=3600
HiGHS 1.10.0:   tech:outlev = 1
  lim:time = 3600

AMPL MP initial flat model has 29 variables (0 integer, 0 binary);
Objectives: 1 quadratic; 
Constraints:  27 linear;

AMPL MP did not modify the model.


Running HiGHS 1.10.0 (git hash: fd86653): Copyright (c) 2025 HiGHS under MIT licence terms
QP   has 27 rows; 30 cols; 73 matrix nonzeros; 30 Hessian nonzeros
Coefficient ranges:
  Matrix [1e+00, 2e+01]
  Cost   [1e+00, 5e+02]
  Bound  [1e-01, 1e+03]
  RHS    [9e-01, 1e+00]
  Iteration        Objective     NullspaceDim
          0        10492.434                0      0.01s
          4        5216.0855                2      0.01s
Model status        : Optimal
Simplex   iterations: 6
QP ASM    iterations: 4
Objective value     :  5.2160266077e+03
HiGHS run time      :          0.01
HiGHS 1.10.0: optimal solution; objective 5216.026608
6 simplex iterations
0 barrier iterations
=======Solving OPF (acrect) with switching off and connectivity off with solver gurobi and options outlev=1 timelimit=3600
Gurobi 12.0.1: Set parameter LogToConsole to value 1
  tech:outlev = 1
Set parameter TimeLimit to value 3600
  lim:time = 3600

AMPL MP initial flat model has 86 variables (0 integer, 0 binary);
Objectives: 1 quadratic; 
Constraints:  54 linear; 54 quadratic;

AMPL MP final model has 87 variables (0 integer, 0 binary);
Objectives: 1 quadratic; 
Constraints:  54 linear; 54 quadratic;


Set parameter InfUnbdInfo to value 1
Gurobi Optimizer version 12.0.1 build v12.0.1rc0 (linux64 - "Ubuntu 22.04.4 LTS")

CPU model: Intel(R) Xeon(R) CPU @ 2.20GHz, instruction set [SSE2|AVX|AVX2]
Thread count: 1 physical cores, 2 logical processors, using up to 2 threads

Non-default parameters:
TimeLimit  3600
InfUnbdInfo  1

Optimize a model with 54 rows, 87 columns and 168 nonzeros
Model fingerprint: 0xe3e952d6
Model has 3 quadratic objective terms
Model has 54 quadratic constraints
Coefficient statistics:
  Matrix range     [1e+00, 2e+01]
  QMatrix range    [1e+00, 1e+00]
  QLMatrix range   [1e+00, 1e+00]
  Objective range  [1e+00, 5e+02]
  QObjective range [2e+03, 2e+03]
  Bounds range     [1e-01, 1e+03]
  RHS range        [3e-01, 1e+00]
  QRHS range       [2e+00, 9e+00]
Presolve removed 9 rows and 10 columns

Continuous model is non-convex -- solving as a MIP


User MIP start did not produce a new incumbent solution
User MIP start violates constraint R0 by 0.100000000

Presolve removed 12 rows and 13 columns
Presolve time: 0.00s
Presolved: 253 rows, 123 columns, 704 nonzeros
Presolved model has 3 quadratic objective terms
Presolved model has 27 quadratic constraint(s)
Presolved model has 51 bilinear constraint(s)
Variable types: 123 continuous, 0 integer (0 binary)
Found heuristic solution: objective 5296.6862040

Root relaxation: objective 2.775873e+03, 573 iterations, 0.01 seconds (0.00 work units)
Another try with MIP start

    Nodes    |    Current Node    |     Objective Bounds      |     Work
 Expl Unexpl |  Obj  Depth IntInf | Incumbent    BestBd   Gap | It/Node Time

     0     0 2775.87307    0   48 5296.68620 2775.87307  47.6%     -    0s
     0     0 5030.87061    0   48 5296.68620 5030.87061  5.02%     -    0s
     0     0 5037.38850    0   48 5296.68620 5037.38850  4.90%     -    0s
     0     0 5144.88557    0   48 5296.68620 5144.88557  2.87%     -    0s
     0     0 5144.93245    0   48 5296.68620 5144.93245  2.87%     -    0s
     0     0 5256.07084    0   45 5296.68620 5256.07084  0.77%     -    0s
     0     0 5256.07084    0   45 5296.68620 5256.07084  0.77%     -    0s
     0     0 5256.07084    0   45 5296.68620 5256.07084  0.77%     -    0s
     0     0 5281.92741    0   38 5296.68620 5281.92741  0.28%     -    0s
     0     0 5281.93688    0   47 5296.68620 5281.93688  0.28%     -    0s
     0     0 5295.47246    0   37 5296.68620 5295.47246  0.02%     -    0s
     0     0 5295.47246    0   36 5296.68620 5295.47246  0.02%     -    0s
     0     0 5296.06759    0   48 5296.68620 5296.06759  0.01%     -    0s
     0     0 5296.06759    0   48 5296.68620 5296.06759  0.01%     -    0s
     0     0          -    0      5296.68620 5296.19555  0.01%     -    0s

Cutting planes:
  RLT: 1
  PSD: 15

Explored 1 nodes (2624 simplex iterations) in 0.21 seconds (0.03 work units)
Thread count was 2 (of 2 available processors)

Solution count 1: 5296.69 

Optimal solution found (tolerance 1.00e-04)
Best objective 5.296686204001e+03, best bound 5.296195548001e+03, gap 0.0093%
Gurobi 12.0.1: optimal solution; objective 5296.686204
2624 simplex iterations
1 branching node
absmipgap=0.490656, relmipgap=9.26345e-05
=======Solving OPF (acpolar) with switching off and connectivity off with solver ipopt and options outlev=1 timelimit=3600
Ipopt 3.12.13: 

******************************************************************************
This program contains Ipopt, a library for large-scale nonlinear optimization.
 Ipopt is released as open source code under the Eclipse Public License (EPL).
         For more information visit http://projects.coin-or.org/Ipopt
******************************************************************************

This is Ipopt version 3.12.13, running with linear solver mumps.
NOTE: Other linear solvers might be more efficient (see Ipopt documentation).

Number of nonzeros in equality constraint Jacobian...:      218
Number of nonzeros in inequality constraint Jacobian.:       36
Number of nonzeros in Lagrangian Hessian.............:       98

Total number of variables............................:       59
                     variables with only lower bounds:        0
                variables with lower and upper bounds:       59
                     variables with only upper bounds:        0
Total number of equality constraints.................:       54
Total number of inequality constraints...............:       18
        inequality constraints with only lower bounds:        0
   inequality constraints with lower and upper bounds:        0
        inequality constraints with only upper bounds:       18

iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
   0  1.2026175e+03 1.25e+00 1.20e+01  -1.0 0.00e+00    -  0.00e+00 0.00e+00   0
   1  5.3146390e+03 3.09e-02 1.97e+02  -1.0 1.28e+00    -  9.07e-03 1.00e+00H  1
   2  5.2978886e+03 8.12e-03 1.39e+02  -1.0 3.75e-01    -  2.75e-01 2.51e-01f  1
   3  5.3026379e+03 5.95e-03 5.93e+00  -1.0 1.52e-01    -  9.82e-01 1.00e+00f  1
   4  5.2993670e+03 1.66e-03 2.73e-01  -1.0 3.51e-02    -  1.00e+00 1.00e+00h  1
   5  5.2972809e+03 4.70e-04 4.40e-02  -1.7 2.27e-02    -  1.00e+00 1.00e+00f  1
   6  5.2967154e+03 1.27e-04 6.36e-01  -2.5 1.06e-02    -  1.00e+00 8.02e-01f  1
   7  5.2967429e+03 7.54e-06 1.06e-01  -2.5 7.60e-03    -  9.86e-01 1.00e+00f  1
   8  5.2967304e+03 4.96e-07 2.23e-04  -2.5 2.04e-03    -  1.00e+00 1.00e+00h  1
   9  5.2966898e+03 2.78e-06 1.18e-01  -3.8 3.84e-03    -  1.00e+00 9.30e-01f  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  10  5.2966885e+03 3.39e-07 3.34e-05  -3.8 1.46e-03    -  1.00e+00 1.00e+00f  1
  11  5.2966862e+03 4.73e-08 4.64e-06  -5.7 5.15e-04    -  1.00e+00 1.00e+00h  1
  12  5.2966862e+03 1.19e-10 1.35e-08  -8.6 2.72e-05    -  1.00e+00 1.00e+00h  1
  13  5.2966862e+03 4.99e-15 1.51e-12  -9.0 6.04e-08    -  1.00e+00 1.00e+00h  1

Number of Iterations....: 13

                                   (scaled)                 (unscaled)
Objective...............:   1.0593372404463114e+03    5.2966862022315563e+03
Dual infeasibility......:   1.5072696893307794e-12    7.5363484466538971e-12
Constraint violation....:   4.9907994403852740e-15    4.9907994403852740e-15
Complementarity.........:   9.0917709744900101e-10    4.5458854872450045e-09
Overall NLP error.......:   9.0917709744900101e-10    4.5458854872450045e-09


Number of objective function evaluations             = 15
Number of objective gradient evaluations             = 14
Number of equality constraint evaluations            = 15
Number of inequality constraint evaluations          = 15
Number of equality constraint Jacobian evaluations   = 14
Number of inequality constraint Jacobian evaluations = 14
Number of Lagrangian Hessian evaluations             = 13
Total CPU secs in IPOPT (w/o function evaluations)   =      0.026
Total CPU secs in NLP function evaluations           =      0.001

EXIT: Optimal Solution Found.
 
Ipopt 3.12.13: Optimal Solution Found

suffix ipopt_zU_out OUT;
suffix ipopt_zL_out OUT;

Look for more examples or documentation at https://amplpower.readthedocs.io/en/latest/