# KKT condition not satisfied in DCOPF

**URL:** <https://discourse.julialang.org/t/kkt-condition-not-satisfied-in-dcopf/130902>\
**Category:** Optimization (Mathematical)\
**Tags:** power-flow\
**Created:** [July 21, 2025, 11:29am UTC](https://discourse.julialang.org/t/kkt-condition-not-satisfied-in-dcopf/130902 "2025-07-21T11:29:53Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![simoni0](https://avatars.discourse-cdn.com/v4/letter/s/6bbea6/32.png) [@simoni0](https://discourse.julialang.org/u/simoni0)\
**Post date:** [July 21, 2025, 11:29am UTC](https://discourse.julialang.org/t/kkt-condition-not-satisfied-in-dcopf/130902/1 "2025-07-21T11:29:53Z")

</div>

I wanted to evaluate whether the KKT condition \lambda\_i - \lambda\_j = \mu^{+}\_{ij} - \mu^{-}\_{ij} holds for standard DC-OPF. I made a small test on the 5-bus case.

```julia
using PowerModels
using GLPK

result = PowerModels.solve_dc_opf("pglib_opf_case5_pjm.m", GLPK.Optimizer, setting = Dict("output" => Dict("duals" => true)))
lmps = Dict()
mus_fr = Dict()
mus_to = Dict()
for (b, bus) in result["solution"]["bus"]
    push!(lmps, parse(Int64,b) => bus["lam_kcl_r"])
end
for (b, branch) in result["solution"]["branch"]
    push!(mus_fr, parse(Int64,b) => branch["mu_sm_fr"])
    push!(mus_to, parse(Int64,b) => branch["mu_sm_to"])
end
lmps[5] - lmps[4] - (mus_fr[6] - mus_to[6])# = 0

```

Line (6,4,5) is congested as can be seen by dual multipliers \mu.

```julia
Dict{Any, Any} with 6 entries:
  5 => 0.0
  4 => 0.0
  6 => 6232.2
  2 => 0.0
  3 => 0.0
  1 => 0.0

lmps[4] = -3994
lmps[5] = -1000
mus_fr[6] = 6232
mus_fr[5] = 0

```

Without congestion, it is easy to see and verify that the difference in lmps is 0 and lagrangian multipliers \mu as well.

With congestion, however, as far as I understand, lmps[5] - lmps[4] - (mus\_fr[6] - mus\_to[6])# = 0 should be 0, but it is not. I tried for multiple solvers and test cases.

Am I missing something fundamental?

Thanks in advance.

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [July 21, 2025, 11:55am UTC](https://discourse.julialang.org/t/kkt-condition-not-satisfied-in-dcopf/130902/2 "2025-07-21T11:55:45Z")

</div>

DCopf is simple, why don’t you directly write an LP yourself (e.g. with JuMP), with the raw data (in PowerModels)?

---

<div class="post-metadata">

**Author:** ![simoni0](https://avatars.discourse-cdn.com/v4/letter/s/6bbea6/32.png) [@simoni0](https://discourse.julialang.org/u/simoni0)\
**Post date:** [July 21, 2025, 12:05pm UTC](https://discourse.julialang.org/t/kkt-condition-not-satisfied-in-dcopf/130902/3 "2025-07-21T12:05:19Z")

</div>

I actually did for a small synthetic 3bus test case but made the same observation. With PowersModels, at least, i can exclude any mistake with regard to DCOPF implementation on my end as its tried and tested.

---

<div class="post-metadata">

**Author:** ![simoni0](https://avatars.discourse-cdn.com/v4/letter/s/6bbea6/32.png) [@simoni0](https://discourse.julialang.org/u/simoni0)\
**Post date:** [July 21, 2025, 6:06pm UTC](https://discourse.julialang.org/t/kkt-condition-not-satisfied-in-dcopf/130902/4 "2025-07-21T18:06:25Z")

</div>

I forgot a dual multiplier related to the power flow. Adding it, solves the issue. There is no direct way to access it through PowerModels, however.

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [July 21, 2025, 6:33pm UTC](https://discourse.julialang.org/t/kkt-condition-not-satisfied-in-dcopf/130902/5 "2025-07-21T18:33:41Z")

</div>

Hi @simoni0 welcome to the forum 😄

Im pleased you got it sorted. I’d strongly encourage you to use HiGHS.jl instead of GLPK.jl. its generally faster and more robust
