@@ -58,7 +58,7 @@ function prune_cuts!(model::SPModel,
5858
5959 # If pruning is performed with territory heuristic, update territory
6060 # at given iteration:
61- if param. pruning[:type ] == " territory"
61+ if param. pruning[:type ] ∈ [ " territory" , " mixed " ]
6262 for t in 1 : model. stageNumber- 1
6363 states = reshape (trajectories[t, :, :], param. forwardPassNumber, model. dimStates)
6464 find_territory! (territory[t], V[t], states)
@@ -78,13 +78,16 @@ function prune_cuts!(model::SPModel,
7878 elseif param. pruning[:type ] == " territory"
7979 # apply heuristic to prune cuts:
8080 V[i] = remove_empty_cuts! (territory[i], V[i])
81+ elseif param. pruning[:type ] == " mixed"
82+ # apply mixed heuristic to prune cuts:
83+ V[i] = remove_cuts_usefulness! (model, territory[i], V[i], param. SOLVER)
8184 end
8285 end
8386
8487 # final number of cuts:
8588 ncuts_final = get_total_number_cuts (V)
8689
87- (verbose > 0 ) && println (" Deflation: " , ncuts_final/ ncuts_initial)
90+ (verbose > 0 ) && @printf (" Deflation: %.3f \n " , ncuts_final/ ncuts_initial)
8891 end
8992end
9093
@@ -105,7 +108,7 @@ function exact_prune_cuts(model::SPModel, params::SDDPparameters, V::PolyhedralF
105108 ncuts = V. numCuts
106109 # Find all active cuts:
107110 if ncuts > 1
108- active_cuts = Bool[is_cut_relevant (model, i, V, params. SOLVER) for i= 1 : ncuts]
111+ active_cuts = Bool[is_cut_relevant (model, i, V, params. SOLVER)[ 1 ] for i= 1 : ncuts]
109112 return PolyhedralFunction (V. betas[active_cuts], V. lambdas[active_cuts, :], sum (active_cuts))
110113 else
111114 return V
@@ -146,7 +149,7 @@ function is_cut_relevant(model::SPModel, k::Int, Vt::PolyhedralFunction, solver;
146149 @objective (m, Min, alpha - dot (λ_k, x) - Vt. betas[k])
147150 solve (m)
148151 sol = getobjectivevalue (m)
149- return sol < epsilon
152+ return ( sol < epsilon), getvalue (x)
150153end
151154
152155
@@ -223,7 +226,7 @@ function add_state!(territory::Territories, V::PolyhedralFunction, x::Array{Floa
223226end
224227
225228
226- """ Remove empty cuts in PolyhedralFunction"""
229+ """ Remove empty cuts with heuristic in PolyhedralFunction. """
227230function remove_empty_cuts! (territory:: Territories , V:: PolyhedralFunction )
228231 assert (territory. ncuts == V. numCuts)
229232
@@ -238,6 +241,36 @@ function remove_empty_cuts!(territory::Territories, V::PolyhedralFunction)
238241end
239242
240243
244+ """ Remove empty cuts in PolyhedralFunction with usefulness test."""
245+ function remove_cuts_usefulness! (model:: SPModel , territory:: Territories , V:: PolyhedralFunction , solver)
246+ assert (territory. ncuts == V. numCuts)
247+
248+ nstates = [length (terr) for terr in territory. territories]
249+ # Set of inactive cuts:
250+ inactive_cuts = nstates .== 0
251+ # Set of active cuts:
252+ active_cuts = nstates .> 0
253+
254+ # get index of inactive cuts:
255+ index = collect (1 : territory. ncuts)[inactive_cuts]
256+
257+ # Check if inactive cuts are useful or not:
258+ for id in index
259+ status, x = is_cut_relevant (model, id, V, solver)
260+ if status
261+ active_cuts[id] = true
262+ end
263+ end
264+
265+ # Remove useless cuts:
266+ territory. territories = territory. territories[active_cuts]
267+ territory. ncuts = sum (active_cuts)
268+ return PolyhedralFunction (V. betas[active_cuts],
269+ V. lambdas[active_cuts, :],
270+ sum (active_cuts))
271+ end
272+
273+
241274""" Get cut which approximate the best value function at point `x`."""
242275function optimalcut (xf:: Vector{Float64} , V:: PolyhedralFunction )
243276 bestcost = - Inf :: Float64
0 commit comments