You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

203 lines
7.7 KiB

2 months ago
  1. /* Power plant LP scheduler, example data with 25hrs for daylightsavings */
  2. /* Implemented, inspected, written and converted to GNU MathProg
  3. by NASZVADI, Peter, 199x-2017 <vuk@cs.elte.hu> */
  4. /*
  5. Fast electric power plant scheduler implementation based on new
  6. results in author's Thesis.
  7. The base problem is:
  8. * given some power plants
  9. * a short time scale partitioned to equidistant intervals
  10. * the task is to yielding the cheapest schedule for the plants
  11. * the daily demand forecast is usually accurate and part of the input
  12. The power plants has technical limitations:
  13. * upper and lower bounds of produced energy
  14. * and also a gradient barrier in both directions
  15. (can depend on time, but this GMPL implementation is simplified)
  16. * Also units with same properties (technical and price) should be
  17. scheduled together usually with near same performance values
  18. * Assumed a simplified network topology, which is contractive, so
  19. keeping Kirchhoff's laws is a necessary constraint too
  20. * All solutions must be integer
  21. The LP relaxation is equivalent with the MIP problem due to the
  22. model's matrix interesting property: it is Totally Unimodular
  23. (proven in 2004 by author) and also a Network Matrix (2006,
  24. presented at OTDK 2016, Szeged, Hungary) so:
  25. * it is strictly polynomial if it is solved by most simplex algs
  26. * all base solutions become integer if the RHS vector is integer
  27. (it is in real life, so this is an acceptable assumption)
  28. * The transposed matrix is NOT a Network Matrix in most cases!
  29. However, adding several other constraints easily turns the problem
  30. to be NP-hard, which is also pinpointed and discussed in the Thesis.
  31. See more about electric power plants' scheduling in the
  32. author's Thesis (in Hungarian):
  33. http://www.cs.elte.hu/matdiploma/vuk.pdf
  34. It is possible to run with custom parameters, what is needed
  35. to define is:
  36. * TIME set (daylightsaving cases or other than hour intervals)
  37. * PLANTS set (the 'Demand' is mandatory and usually negative)
  38. * PRICE parameter (can be negative if energy is sold to a consumer)
  39. * BOUND parameter (technical bounds)
  40. * MAXGRAD parameter (technical bounds)
  41. Then generate a pretty-printed solution by typing:
  42. glpsol --math powpl25h.mod
  43. */
  44. set TIME, default {
  45. '00:00', '01:00', '02:00', '03:00', '04:00',
  46. '05:00', '06:00', '07:00', '08:00', '09:00',
  47. '10:00', '11:00', '12:00', '13:00', '14:00',
  48. '15:00', '16:00', '17:00', '18:00', '19:00',
  49. '20:00', '21:00', '22:00', '23:00', '24:00'
  50. };
  51. /* Time labels, assumed natural ordering. daylightsaving's bias
  52. can be inserted p.ex. in Central Europe like:
  53. ... '01:00', '02:00', '02:00b', '03:00', ... */
  54. set TADJ := setof{(r, s) in TIME cross TIME: r < s}(r, s) diff
  55. setof{(t, u, v) in TIME cross TIME cross TIME: t < u and u < v}(t, v);
  56. /* Tricky adjacent time label generator because GMPL lacks order determination
  57. of set elements (except intervals composed of equidistant numbers) */
  58. set PLANTS, default {'Demand'};
  59. /* Demand is a promoted, mandatory one, usually filled
  60. with negative MW values in data section */
  61. set DIRECTION, default {'Up', 'Down'};
  62. /* All possible directions of gradients, do not touch */
  63. param MAXINT, default 10000;
  64. /* A "macro" for bounding absolute value of all used numbers
  65. and used as default value */
  66. param PRICE{PLANTS}, default MAXINT;
  67. /* Should be specified in data section, self-explanatory.
  68. can be negative if there are energy buyers */
  69. param BOUND{(p, t, d) in PLANTS cross TIME cross DIRECTION},
  70. default if t = '00:00' then if d = 'Down' then BOUND[p, t, 'Up'] else 0 else
  71. if p <> 'Demand' or d = 'Up' then sum{(u, v) in TADJ: v = t} BOUND[p, u, d]
  72. else BOUND[p, t, 'Up'];
  73. /* Obvious, technical bounds of each power plant unit (real or virtual like
  74. 'Demand'). If some parts are not given in data section, calculated
  75. from preceeding values. Also for time '00:00', its 'Down' values by
  76. default are the same as denoted with 'Up' */
  77. param MAXGRAD{(p, d) in PLANTS cross DIRECTION}, default MAXINT;
  78. /* Usually nonnegative integer, might differ in distinct directions per unit
  79. in the cited thesis, it is allowed to gradient bounds to depend on time,
  80. but this is a simplified model */
  81. var x{(t, p) in TIME cross PLANTS}, <= BOUND[p, t, 'Up'], >= BOUND[p, t, 'Down'];
  82. /* The schedule, dimension is MW */
  83. s.t. kirchhoff{t in TIME: t <> '00:00'}: sum{p in PLANTS} x[t, p] = 0;
  84. /* Conservative property */
  85. s.t. gradient{(p, t, u) in PLANTS cross TADJ}:
  86. -MAXGRAD[p, 'Down'] <= x[t, p] - x[u, p] <= MAXGRAD[p, 'Up'];
  87. /* Technical limitations, each unit usually cannot change performance
  88. arbitrarily in a short time, so limited in both directions per time unit*/
  89. minimize obj: sum{(t, p) in TIME cross PLANTS}(x[t, p] * PRICE[p]);
  90. /* The objective is the cost of the schedule */
  91. solve;
  92. /* Pretty print solution in table */
  93. printf '+--------+';
  94. for{p in PLANTS}{
  95. printf '-% 6s-+', '------';
  96. }
  97. printf '\n';
  98. printf '|%7s |', ' ';
  99. for{p in PLANTS}{
  100. printf ' % 6s |', p;
  101. }
  102. printf '\n';
  103. printf '+--------+';
  104. for{p in PLANTS}{
  105. printf '-% 6s-+', '------';
  106. }
  107. printf '\n';
  108. for{t in TIME}{
  109. printf '|%7s |', t;
  110. for{p in PLANTS}{
  111. printf ' % 6s |', x[t, p].val;
  112. }
  113. printf '\n';
  114. }
  115. printf '+--------+';
  116. for{p in PLANTS}{
  117. printf '-% 6s-+', '------';
  118. }
  119. printf '\n';
  120. data;
  121. set TIME :=
  122. '00:00', '01:00', '02:00', '02:00b', '03:00', '04:00',
  123. '05:00', '06:00', '07:00', '08:00', '09:00',
  124. '10:00', '11:00', '12:00', '13:00', '14:00',
  125. '15:00', '16:00', '17:00', '18:00', '19:00',
  126. '20:00', '21:00', '22:00', '23:00', '24:00';
  127. /*
  128. Generated random default values and names, the demand is the sum of
  129. 2 sinewaves.
  130. Also specified a treshold for nuclear plants from 15:00 till 19:00
  131. The sun is shining only morning and in the afternoon: 07:00-18:00, so
  132. solar plant cannot produce electric energy after sunset.
  133. Only touch this section, or export it to a data file!
  134. */
  135. set PLANTS 'Demand', 'Atom1', 'Atom2', 'Coal', 'Gas1', 'Gas2', 'Green', 'Oil', 'Solar', 'Dam';
  136. param PRICE :=
  137. 'Demand' 0
  138. 'Atom1' 2
  139. 'Atom2' 2
  140. 'Coal' 15.6
  141. 'Gas1' 12
  142. 'Gas2' 11.5
  143. 'Green' 8.8
  144. 'Oil' 23.3
  145. 'Solar' 7.6
  146. 'Dam' 3;
  147. /* price per MW */
  148. param BOUND :=
  149. [*, *, 'Up'] (tr): 'Atom1' 'Atom2' 'Coal' 'Gas1' 'Gas2' 'Green' 'Oil' 'Solar' 'Dam' :=
  150. '00:00' 240 240 100 150 150 20 90 0 20
  151. '01:00' 240 240 155 192 208 35 230 0 20
  152. [*, *, 'Up'] (tr): 'Atom1' 'Atom2' :=
  153. '15:00' 200 200
  154. '19:00' 235 235
  155. [*, *, 'Up'] (tr): 'Solar' :=
  156. '07:00' 20
  157. '18:00' 0
  158. [*, *, 'Down'] (tr): 'Atom1' 'Atom2' 'Coal' 'Gas1' 'Gas2' 'Green' 'Oil' 'Solar' 'Dam' :=
  159. '01:00' 100 100 50 62 68 0 75 0 20
  160. [*, *, 'Up'] : '01:00' '02:00' '02:00b' '03:00' '04:00' '05:00' '06:00' '07:00' '08:00' :=
  161. 'Demand' -868 -851 -842 -837 -791 -887 -912 -1046 -1155
  162. [*, *, 'Up'] : '09:00' '10:00' '11:00' '12:00' '13:00' '14:00' '15:00' '16:00' :=
  163. 'Demand' -945 -873 -797 -990 -1241 -1134 -815 -782
  164. [*, *, 'Up'] : '17:00' '18:00' '19:00' '20:00' '21:00' '22:00' '23:00' '24:00' :=
  165. 'Demand' -772 -827 -931 -1105 -1215 -1249 -1183 -952;
  166. param MAXGRAD (tr)
  167. : 'Atom1' 'Atom2' 'Coal' 'Gas1' 'Gas2' 'Green' 'Oil' 'Solar' 'Dam' :=
  168. 'Up' 30 30 35 89 95 5 56 2 4
  169. 'Down' 30 30 45 96 102 5 56 2 4;
  170. end;