55# file, You can obtain one at http://mozilla.org/MPL/2.0/.
66# ############################################################################
77
8-
98type Territories
109 ncuts:: Int
1110 territories:: Array{Array}
1211 nstates:: Int
1312 states:: Array{Float64, 2}
1413end
1514
16- Territories (ndim) = Territories (0 , [], 0 , Array {Float64} (0 , ndim))
17-
1815
1916"""
2017Exact pruning of all polyhedral functions in input array.
@@ -24,10 +21,53 @@ Exact pruning of all polyhedral functions in input array.
2421* `params::SDDPparameters`:
2522* `Vector{PolyhedralFunction}`:
2623 Polyhedral functions where cuts will be removed
24+ * `trajectories::Array{Float64, 3}`
25+ Previous trajectories
26+ * `territory::Array{Territories}`
27+ Container storing the territory for each cuts
28+ * `it::Int64`:
29+ current iteration number
30+ * `verbose::Int64`
2731"""
28- function prune_cuts! (model:: SPModel , params:: SDDPparameters , V:: Vector{PolyhedralFunction} )
29- for i in 1 : length (V)- 1
30- V[i] = exact_prune_cuts (model, params, V[i])
32+ function prune_cuts! (model:: SPModel ,
33+ param:: SDDPparameters ,
34+ V:: Vector{PolyhedralFunction} ,
35+ trajectories:: Array{Float64, 3} ,
36+ territory:: Union{Void, Array{Territories}} ,
37+ it:: Int64 ,
38+ verbose:: Int64 )
39+ # Basic pruning: remove redundant cuts
40+ remove_redundant_cuts! (V)
41+
42+ # If pruning is performed with territory heuristic, update territory
43+ # at given iteration:
44+ if param. pruning[:type ] == " territory"
45+ for t in 1 : model. stageNumber- 1
46+ states = reshape (trajectories[t, :, :], param. forwardPassNumber, model. dimStates)
47+ find_territory! (territory[t], V[t], states)
48+ end
49+ end
50+
51+ # If specified to prune cuts at this iteration, do it:
52+ if param. pruning[:pruning ] && (it% param. pruning[:period ]== 0 )
53+ # initial number of cuts:
54+ ncuts_initial = get_total_number_cuts (V)
55+ (verbose > 0 ) && print (" Prune cuts ..." )
56+
57+ for i in 1 : length (V)- 1
58+ if param. pruning[:type ] == " exact"
59+ # apply exact cuts pruning:
60+ V[i] = exact_prune_cuts (model, param, V[i])
61+ elseif param. pruning[:type ] == " territory"
62+ # apply heuristic to prune cuts:
63+ V[i] = remove_empty_cuts! (territory[i], V[i])
64+ end
65+ end
66+
67+ # final number of cuts:
68+ ncuts_final = get_total_number_cuts (V)
69+
70+ (verbose > 0 ) && println (" Deflation: " , ncuts_final/ ncuts_initial)
3171 end
3272end
3373
96136# #######################################
97137# Territory algorithm
98138# #######################################
99- function territory_prune_cuts! (territory:: Territories ,
100- V:: PolyhedralFunction ,
101- states:: Array{Float64, 2} )
102- find_territory! (territory, V, states)
103- return remove_empty_cuts (territory, V)
104- end
139+
140+ Territories (ndim) = Territories (0 , [], 0 , Array {Float64} (0 , ndim))
105141
106142
107143""" Update territories with cuts previously computed during backward pass. """
@@ -112,9 +148,11 @@ function find_territory!(territory, V, states)
112148 nt = nc - territory. ncuts
113149
114150 for i in 1 : nt
115- add_cut! (territory, V )
151+ add_cut! (territory)
116152 update_territory! (territory, V, nc - nt + i)
117153 end
154+
155+ # ensure that territory has the same number of cuts as V!
118156 assert (territory. ncuts == V. numCuts)
119157
120158 for i in 1 : nx
@@ -125,15 +163,14 @@ function find_territory!(territory, V, states)
125163end
126164
127165
128- """ Update territories with new cuts added during previous backward pass. """
166+ """ Update territories considering new cut with index `indcut`. """
129167function update_territory! (territory, V, indcut)
130168 for k in 1 : territory. ncuts
131169 if k == indcut
132170 continue
133171 end
134- terr = copy (territory. territories[k])
135172 todelete = []
136- for (num, (ix, cost)) in enumerate (terr )
173+ for (num, (ix, cost)) in enumerate (territory . territories[k] )
137174 x = collect (territory. states[ix, :])
138175
139176 costnewcut = cutvalue (V, indcut, x)
@@ -148,31 +185,32 @@ function update_territory!(territory, V, indcut)
148185end
149186
150187
151- """ Add a new cut to the """
152- function add_cut! (territory, V )
188+ """ Add cut to `territory`. """
189+ function add_cut! (territory)
153190 push! (territory. territories, [])
154191 territory. ncuts += 1
155192end
156193
157194
158- function add_state! (territory, V, x)
195+ """ Add a new state and update territories."""
196+ function add_state! (territory:: Territories , V:: PolyhedralFunction , x:: Array{Float64} )
197+ # Get cut which is the supremum at point `x`:
159198 bcost, bcuts = optimalcut (x, V)
160199
161- indx = territory. nstates + 1
162- push! (territory. territories[bcuts], (indx, bcost))
200+ # Add `x` to the territory of cut `bcuts`:
201+ territory. nstates += 1
202+ push! (territory. territories[bcuts], (territory. nstates, bcost))
163203
204+ # Add `x` to the list of visited state:
164205 territory. states = vcat (territory. states, x' )
165- territory. nstates += 1
166206end
167207
168208
169- """
170- Remove empty cuts in PolyhedralFunction
171- """
172- function remove_empty_cuts! (territory, V)
173- assert (length (territory) == V. numCuts)
209+ """ Remove empty cuts in PolyhedralFunction"""
210+ function remove_empty_cuts! (territory:: Territories , V:: PolyhedralFunction )
211+ assert (territory. ncuts == V. numCuts)
174212
175- nstates = [length (cont ) for cont in territory. territories]
213+ nstates = [length (terr ) for terr in territory. territories]
176214 active_cuts = nstates .> 0
177215
178216 territory. territories = territory. territories[active_cuts]
@@ -183,9 +221,7 @@ function remove_empty_cuts!(territory, V)
183221end
184222
185223
186- """
187- Get cut which approximate the best value function at point `x`.
188- """
224+ """ Get cut which approximate the best value function at point `x`."""
189225function optimalcut (xf:: Vector{Float64} , V:: PolyhedralFunction )
190226 bestcost = - Inf :: Float64
191227 bestcut = - 1
@@ -206,12 +242,29 @@ function optimalcut(xf::Vector{Float64}, V::PolyhedralFunction)
206242end
207243
208244
209- """ Get approximation of value function at given point `x`. """
210- function cutvalue (V, indc, x)
245+ """
246+ Get approximation of value function at given point `x`.
247+
248+ # Arguments
249+ - `V::PolyhedralFunction`
250+ Approximation of the value function as linear cuts
251+ - `indc::Int64`
252+ Index of cut to consider
253+ - `x::Array{Float64}`
254+ Coordinates of state
255+
256+ # Return
257+ `cost::Float64`
258+ Value of cut `indc` at point `x`
259+ """
260+ function cutvalue (V:: PolyhedralFunction , indc:: Int , x:: Array{Float64} )
211261 cost = V. betas[indc]
212262 for j in 1 : size (V. lambdas, 2 )
213263 cost += V. lambdas[indc, j]* x[j]
214264 end
215265 return cost
216266end
217267
268+ # Return total number of cuts in PolyhedralFunction array:
269+ get_total_number_cuts (V:: Array{PolyhedralFunction} ) = sum ([v. numCuts for v in V])
270+
0 commit comments