Implementation
The Original Unit Commitment Implementation
The Mosel code printed below implements and solves the original formulation of the unit commitment problem.
declarations NT = 7 ! Number of time periods TIME = 1..NT ! Time periods PLANTS = 1..4 ! Power generation plant UNITS: set of string ! Power generation units LEN, DEM: array(TIME) of integer ! Length and demand of time periods PMIN,PMAX: array(PLANTS) of integer ! Min. and max output of a generator type CSTART: array(PLANTS) of integer ! Start-up cost of a generator CMIN: array(PLANTS) of integer ! Hourly cost of gen. at min. output CADD: array(PLANTS) of real ! Cost/hour/MW of prod. above min. level PLANT: array(UNITS) of integer ! Unit generation plant YEARS: range ! Historical years HDEM: array(YEARS,TIME) of integer ! Historical demand profiles start: array(UNITS,TIME) of mpvar ! Is generation unit starting ? work: array(UNITS,TIME) of mpvar ! Is generation unit up ? padd: array(UNITS,TIME) of mpvar ! Production above min. output level end-declarations initializations from 'a6electr_ro_simple.dat' LEN DEM PMIN PMAX CSTART CMIN CADD PLANT HDEM end-initializations
! Create decision variables
 forall(u in UNITS, t in TIME) do
  start(u,t) is_binary
  work(u,t) is_binary
 end-do
! Objective function: total daily cost
 Cost:= sum(u in UNITS, t in TIME) (CSTART(PLANT(u))*start(u,t) +
  LEN(t)*(CMIN(PLANT(u))*work(u,t) + CADD(PLANT(u))*padd(u,t)))
! Number of generators started per period and per type
 forall(u in UNITS, t in TIME)
  start(u,t) >= work(u,t) - if(t>1, work(u,t-1), work(u,NT))
! Limit on power production range
 forall(u in UNITS, t in TIME)
  padd(u,t) <= (PMAX(PLANT(u))-PMIN(PLANT(u)))*work(u,t)
! Power balance
 forall(t in TIME)
  sum(u in UNITS) (PMIN(PLANT(u))*work(u,t) + padd(u,t)) = DEM(t)
! Symmetry breaker
 forall(t in TIME, p in PLANTS)
  forall(u1, u2 in UNITS | PLANT(u1) = PLANT(u2) and u1<u2)
   work(u1,t) >= work(u2,t)
!**** Solving and solution reporting ****
! Solve the original problem
 minimize(Cost)
 writeln("\n=== Nominal case ===\n")
 print_solution
! Add robust constraints
 robust_demand
! Solve robust the problem
 setparam("ROBUST_UNCERTAIN_OVERLAP", true)
 minimize(Cost)
 writeln("\n=== Robust against demand variation ===\n")
 print_solution
 The following output printing routines are invoked from the model shown above:
!**** Print highest loss of load in case of worst case scenario realization
 procedure print_risk
   write("\n", strfmt("Loss of load",20))
   forall(t in TIME) do
     s:= sum(u in UNITS) (work(u,t).sol*PMAX(PLANT(u))) ! Total capacity
     v:= maxlist(DEM(t), max(y in YEARS) HDEM(y,t))     ! Hist. peak demand
     if(s < v) then
       write(strfmt(v-s,8))
     else
       write(strfmt("",8))
     end-if
   end-do
 end-procedure
!**** Solution printing ****
 procedure print_solution
   writeln("Total cost: ", getobjval)
   write(strfmt("Time period ",-20))
   ct:=0
   forall(t in TIME) do
     write(strfmt(ct,5), "-", strfmt(ct+LEN(t),2), "")
     ct+=LEN(t)
   end-do
   write("\n",strfmt("Up Units",-20))
   forall(t in TIME) write(strfmt(sum(u in UNITS) work(u,t).sol,8))
   write("\n", strfmt("Gen. Pwr.",20))
   forall(t in TIME)
     write(strfmt(sum(u in UNITS) (work(u,t).sol*PMIN(PLANT(u))+padd(u,t).sol),8))
   write("\n", strfmt("Gen. Cap.",20))
   forall(t in TIME)
     write(strfmt(sum(u in UNITS) (work(u,t).sol*PMAX(PLANT(u))),8))
   write("\n", strfmt("Res. Dn",20))
   forall(t in TIME) write(strfmt(sum(u in UNITS) (padd(u,t).sol),8))
   write("\n", strfmt("Res. Up",20))
   forall(t in TIME)
     write(strfmt(sum(u in UNITS) work(u,t).sol*PMAX(PLANT(u)) - DEM(t),8))
   print_risk	
   writeln	
 end-procedure
 The Load Robust Unit Commitment Implementation
The extension to scenario-based robust optimization is implemented by the following subroutines.
!**** Helper routine to create scenario uncertain set ****
  public procedure makescenario(a:array(r1:range,c1:range) of integer,
	  u:array(c2:range) of uncertain)
    declarations
      aa:dynamic array(r0:range,U:set of uncertain) of real
    end-declarations
    forall(i in r1, j in c1|exists(a(i,j)) and exists(u(j)),n as counter) do
      aa(n,u(j)):=a(i,j)
    end-do
    scenario(aa)
  end-procedure
!**** Robust against past scenario ****
 public procedure robust_demand
   declarations
     demand: array(TIME) of uncertain    ! Uncertain power demand
   end-declarations
  ! Add uncertainty set (time correlation)
   makescenario(HDEM,demand)
  ! Security reserve upward
   forall(t in TIME) sum(u in UNITS) PMAX(PLANT(u))*work(u,t) >= demand(t)
 end-procedure
 The N-k Contingency-Constrained Unit Commitment Implementation
Replacing the call to the procedure robust_demand by a call to the procedure robust_contingency printed below will turn the problem formulation into a N-k contingency-constrained unit commitment model.
The example also demonstrates how to use the value of the uncertain to extract meaningful information about the units which are the most critical ones for the system.
!**** Ensure enough power production capacity allows to
!**** satisfy load even if 'k' units are forced in outage.
 procedure robust_contingency(k: integer)
   forall(t in TIME, u in UNITS) create(outage(u,t))
   forall(t in TIME, u in UNITS) outage(u,t) >= 0
   ! If the unit is forced in outage, the total capacity
   ! of the generating units are lost
   forall(t in TIME, u in UNITS) outage(u,t) <= 1
   ! forall(t in TIME) sum(u in UNITS) outage(u,t) <= k
   forall(t in TIME) cardinality(union(u in UNITS | exists(outage(u,t))) {outage(u,t)}, k)
   forall(t in TIME)
     RobCtrMaxDem(t) := 	
       sum(u in UNITS) PMAX(PLANT(u))*work(u,t) -
       sum(u in UNITS) PMAX(PLANT(u))*work(u,t)*outage(u,t) >= DEM(t)
   ! In order to reduce the number of variables we reuse
   ! outage() and let the solver do the variable duplication
   ! by setting the ROBUST_UNCERTAIN_OVERLAP parameter
   setparam("ROBUST_UNCERTAIN_OVERLAP",true)
   forall(t in TIME)
     RobCtrMinDem(t) :=
       sum(u in UNITS) PMIN(PLANT(u))*work(u,t) -
       sum(u in UNITS) PMIN(PLANT(u))*work(u,t)*outage(u,t) <= DEM(t)
 end-procedure
 
                 
