77
88type ActiveCutsContainer
99 ncuts:: Int
10- territories:: Array{Array}
10+ territories:: Array{Array} # set of states where cut k is active
1111 nstates:: Int
12- states:: Array{Float64, 2}
12+ states:: Array{Float64, 2} # set of states where cuts are tested
1313end
1414
1515
16- """ Remove redundant cuts in Polyhedral Value function `V`"""
17- function remove_cuts (V:: PolyhedralFunction )
16+ """ Remove redundant cuts in Polyhedral Value function `V`
17+
18+ # Arguments
19+ * `V::PolyhedralFunction`:
20+ """
21+ function remove_cuts! (V:: PolyhedralFunction )
1822 Vf = hcat (V. lambdas, V. betas)
1923 Vf = unique (Vf, 1 )
2024 return PolyhedralFunction (Vf[:, end ], Vf[:, 1 : end - 1 ], size (Vf)[1 ])
2125end
2226
2327
24- """ Remove redundant cuts in a vector of Polyhedral Functions `Vts`."""
28+ """ Remove redundant cuts in a vector of Polyhedral Functions `Vts`.
29+
30+ # Arguments
31+ * `Vts::Vector{PolyhedralFunction}`:
32+ """
2533function remove_redundant_cuts! (Vts:: Vector{PolyhedralFunction} )
2634 n_functions = length (Vts)- 1
2735 for i in 1 : n_functions
28- Vts[i] = remove_cuts (Vts[i])
36+ Vts[i] = remove_cuts! (Vts[i])
2937 end
3038end
3139
@@ -35,13 +43,14 @@ Exact pruning of all polyhedral functions in input array.
3543
3644# Arguments
3745* `model::SPModel`:
38- * `params ::SDDPparameters`:
46+ * `param ::SDDPparameters`:
3947* `Vector{PolyhedralFunction}`:
4048 Polyhedral functions where cuts will be removed
4149* `trajectories::Array{Float64, 3}`
4250 Previous trajectories
4351* `territory::Array{ActiveCutsContainer}`
44- Container storing the territory for each cuts
52+ Container storing the territory (i.e. the set of tested states where
53+ a given cut is active) for each cuts
4554* `it::Int64`:
4655 current iteration number
4756* `verbose::Int64`
@@ -79,15 +88,15 @@ function prune_cuts!(model::SPModel,
7988 # apply heuristic to prune cuts:
8089 V[i] = level1_cuts_pruning! (territory[i], V[i])
8190 elseif param. pruning[:type ] == " exact+"
82- # apply mixed heuristic to prune cuts :
91+ # apply heuristicly accelerated exact pruning :
8392 V[i] = exact_cuts_pruning_accelerated! (model, territory[i], V[i], param. SOLVER)
8493 end
8594 end
8695
8796 # final number of cuts:
8897 ncuts_final = get_total_number_cuts (V)
8998
90- (verbose > 0 ) && @printf (" Deflation : %.3f \n " , ncuts_final/ ncuts_initial)
99+ (verbose > 0 ) && @printf (" New cuts/Old cuts ratio : %.3f \n " , ncuts_final/ ncuts_initial)
91100 end
92101end
93102
@@ -97,18 +106,18 @@ Remove useless cuts in PolyhedralFunction.
97106
98107# Arguments
99108* `model::SPModel`:
100- * `params ::SDDPparameters`:
109+ * `param ::SDDPparameters`:
101110* `V::PolyhedralFunction`:
102111 Polyhedral function where cuts will be removed
103112
104113# Return
105114* `PolyhedralFunction`: pruned polyhedral function
106115"""
107- function exact_cuts_pruning (model:: SPModel , params :: SDDPparameters , V:: PolyhedralFunction )
116+ function exact_cuts_pruning (model:: SPModel , param :: SDDPparameters , V:: PolyhedralFunction )
108117 ncuts = V. numCuts
109118 # Find all active cuts:
110119 if ncuts > 1
111- active_cuts = Bool[is_cut_relevant (model, i, V, params . SOLVER)[1 ] for i= 1 : ncuts]
120+ active_cuts = Bool[is_cut_relevant (model, i, V, param . SOLVER)[1 ] for i= 1 : ncuts]
112121 return PolyhedralFunction (V. betas[active_cuts], V. lambdas[active_cuts, :], sum (active_cuts))
113122 else
114123 return V
@@ -160,20 +169,29 @@ end
160169ActiveCutsContainer (ndim) = ActiveCutsContainer (0 , [], 0 , Array {Float64} (0 , ndim))
161170
162171
163- """ Update territories with cuts previously computed during backward pass."""
164- function find_level1_cuts! (cutscontainer, V, states)
172+ """ Update territories (i.e. the set of tested states where
173+ a given cut is active) with cuts previously computed during backward pass.
174+
175+ # Arguments
176+ * `cutscontainer::ActiveCutsContainer`:
177+ * `Vt::PolyhedralFunction`:
178+ Object storing all cuts
179+ * `states`:
180+ Object storing all visited states
181+ """
182+ function find_level1_cuts! (cutscontainer:: ActiveCutsContainer , V:: PolyhedralFunction , states)
165183 nc = V. numCuts
166184 # get number of new positions to analyse:
167185 nx = size (states, 1 )
168- nt = nc - cutscontainer. ncuts
186+ nt = nc - cutscontainer. numCuts
169187
170188 for i in 1 : nt
171189 add_cut! (cutscontainer)
172190 update_territory! (cutscontainer, V, nc - nt + i)
173191 end
174192
175193 # ensure that territory has the same number of cuts as V!
176- assert (cutscontainer. ncuts == V. numCuts)
194+ assert (cutscontainer. numCuts == V. numCuts)
177195
178196 for i in 1 : nx
179197 x = collect (states[i, :])
@@ -182,9 +200,18 @@ function find_level1_cuts!(cutscontainer, V, states)
182200end
183201
184202
185- """ Update territories considering new cut with index `indcut`."""
186- function update_territory! (cutscontainer, V, indcut)
187- for k in 1 : cutscontainer. ncuts
203+ """ Update territories (i.e. the set of tested states where
204+ a given cut is active) considering new cut given by index `indcut`.
205+
206+ # Arguments
207+ * `cutscontainer::ActiveCutsContainer`:
208+ * `V::PolyhedralFunction`:
209+ Object storing all cuts
210+ * `indcut::Int64`:
211+ new cut index
212+ """
213+ function update_territory! (cutscontainer:: ActiveCutsContainer , V:: PolyhedralFunction , indcut:: Int64 )
214+ for k in 1 : cutscontainer. numCuts
188215 if k == indcut
189216 continue
190217 end
@@ -204,16 +231,16 @@ function update_territory!(cutscontainer, V, indcut)
204231end
205232
206233
207- """ Add cut to `territory `."""
208- function add_cut! (cutscontainer)
234+ """ Add cut to `ActiveCutsContainer `."""
235+ function add_cut! (cutscontainer:: ActiveCutsContainer )
209236 push! (cutscontainer. territories, [])
210- cutscontainer. ncuts += 1
237+ cutscontainer. numCuts += 1
211238end
212239
213240
214- """ Add a new state and update territories."""
241+ """ Add a new state to test and accordingly update territories of each cut ."""
215242function add_state! (cutscontainer:: ActiveCutsContainer , V:: PolyhedralFunction , x:: Array{Float64} )
216- # Get cut which is the supremum at point `x`:
243+ # Get cut which is active at point `x`:
217244 bcost, bcuts = optimalcut (x, V)
218245
219246 # Add `x` to the territory of cut `bcuts`:
@@ -225,26 +252,48 @@ function add_state!(cutscontainer::ActiveCutsContainer, V::PolyhedralFunction, x
225252end
226253
227254
228- """ Remove inactive cuts in PolyhedralFunction with territory heuristic."""
255+ """ Remove cuts in PolyhedralFunction that are inactive on all visited states.
256+ # Arguments
257+ * `cutscontainer::ActiveCutsContainer`:
258+ * `V::PolyhedralFunction`:
259+ Object storing all cuts
260+ # Return
261+ * `V::PolyhedralFunction`
262+ the new PolyhedralFunction
263+ """
229264function level1_cuts_pruning! (cutscontainer:: ActiveCutsContainer , V:: PolyhedralFunction )
230- assert (cutscontainer. ncuts == V. numCuts)
265+ assert (cutscontainer. numCuts == V. numCuts)
231266
232267 nstates = [length (terr) for terr in cutscontainer. territories]
233268 active_cuts = nstates .> 0
234269
235270 cutscontainer. territories = cutscontainer. territories[active_cuts]
236- cutscontainer. ncuts = sum (active_cuts)
271+ cutscontainer. numCuts = sum (active_cuts)
237272 return PolyhedralFunction (V. betas[active_cuts],
238273 V. lambdas[active_cuts, :],
239274 sum (active_cuts))
240275end
241276
242277
243- """ Remove empty cuts in PolyhedralFunction with usefulness test."""
278+ """ Remove useless cuts in PolyhedralFunction
279+
280+ First test if cuts are active on the visited states,
281+ then test remaining cuts.
282+
283+ # Arguments
284+ * `model::SPModel`:
285+ * `cutscontainer::ActiveCutsContainer`:
286+ * `V::PolyhedralFunction`:
287+ Object storing all cuts
288+
289+ # Return
290+ * `V::PolyhedralFunction`
291+ the new PolyhedralFunction
292+ """
244293function exact_cuts_pruning_accelerated! (model:: SPModel ,
245294 cutscontainer:: ActiveCutsContainer ,
246295 V:: PolyhedralFunction , solver)
247- assert (cutscontainer. ncuts == V. numCuts)
296+ assert (cutscontainer. numCuts == V. numCuts)
248297
249298 nstates = [length (terr) for terr in cutscontainer. territories]
250299 # Set of inactive cuts:
@@ -253,7 +302,7 @@ function exact_cuts_pruning_accelerated!(model::SPModel,
253302 active_cuts = nstates .> 0
254303
255304 # get index of inactive cuts:
256- index = collect (1 : cutscontainer. ncuts )[inactive_cuts]
305+ index = collect (1 : cutscontainer. numCuts )[inactive_cuts]
257306
258307 # Check if inactive cuts are useful or not:
259308 for id in index
@@ -265,14 +314,26 @@ function exact_cuts_pruning_accelerated!(model::SPModel,
265314
266315 # Remove useless cuts:
267316 cutscontainer. territories = cutscontainer. territories[active_cuts]
268- cutscontainer. ncuts = sum (active_cuts)
317+ cutscontainer. numCuts = sum (active_cuts)
269318 return PolyhedralFunction (V. betas[active_cuts],
270319 V. lambdas[active_cuts, :],
271320 sum (active_cuts))
272321end
273322
274323
275- """ Find active cut at point `xf`."""
324+ """ Find active cut at point `xf`.
325+
326+ # Arguments
327+ * `xf::Vector{Float64}`:
328+ * `V::PolyhedralFunction`:
329+ Object storing all cuts
330+
331+ # Return
332+ `bestcost::Float64`
333+ Value of maximal cut at point `xf`
334+ `bestcut::Int64`
335+ Index of maximal cut at point `xf`
336+ """
276337function optimalcut (xf:: Vector{Float64} , V:: PolyhedralFunction )
277338 bestcost = - Inf :: Float64
278339 bestcut = - 1
0 commit comments