File: backwardForwardSDDP.py

package info (click to toggle)
stopt 5.12%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 8,860 kB
  • sloc: cpp: 70,456; python: 5,950; makefile: 72; sh: 57
file content (149 lines) | stat: -rw-r--r-- 6,926 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# All Rights Reserved
# This code is published under the GNU Lesser General Public License (GNU LGPL)
import StOptSDDP
import StOptGeners
import Simulators
import SDDPOptimizers
import imp

## @package backwardForwardSDDP
## backward and forward sweep by SDDP
## Permits to execute forward and backward sweep in python
## This is the python version of backwardForwardSDDP.cpp
## author Xavier Warin

## @brief Achieve forward and backward sweep by SDDP
## @param  p_optimizer           defines the optimiser necessary to optimize a step for one simulation solving a LP
## @param  p_nbSimulCheckForSimu defines the number of simulations to check convergence
## @param  p_initialState        initial state at the beginning of simulation
## @param  p_finalCut            object of final cuts
## @param  p_dates               vector of exercised dates, last dates correspond to the final cut object
## @param  p_meshForReg          number of mesh for regression in each direction
## @param  p_nameRegressor       name of the archive to store regressors
## @param  p_nameCut             name of the archive to store cuts
## @param  p_nameVisitedStates   name of the archive to store visited states
## @param  p_iter                maximum iteration of SDDP, on return the number of iterations achieved
## @param  p_accuracy            accuracy asked , on return estimation of accuracy achieved (expressed in %)
## @param  p_nStepConv           every p_nStepConv convergence is checked
## @return backward and forward valorization
def backwardForwardSDDP(p_optimizer, p_nbSimulCheckForSimu, p_initialState, p_finalCut,p_dates,
                        p_meshForReg, p_nameRegressor, p_nameCut, p_nameVisitedStates,
                        p_iter, p_accuracy,p_nStepConv):
    
    try:
        imp.find_module('mpi4py')
        Found = True
    except:
        print("Not parallel module found ")
        Found = False
    if Found:
        from mpi4py import MPI
        world = MPI.COMM_WORLD
    simulatorForOptim = p_optimizer.getSimulatorBackward()
    simulatorForSim = p_optimizer.getSimulatorForward()
    
    if Found:
        bTask = (world.rank==0)
    else:
        bTask = True


    if bTask:
        # archive for regressors
        archiveForRegressor =StOptGeners.BinaryFileArchive(p_nameRegressor,"w")
        # archive of first set of admissible states
        archiveForInitialState = StOptGeners.BinaryFileArchive(p_nameVisitedStates,"w")
        # list of states
        vecSetOfStates= [None] * (p_dates.size-1)
         # create regressors for each date except the last
        for  idate in range(p_dates.size-2,0,-1):
            simulatorForOptim.updateDateIndex(idate)
            # initial regressor
            particlesCurrent = simulatorForOptim.getParticles()
            # regressor
            regCurrent =StOptSDDP.LocalLinearRegressionForSDDP(False,particlesCurrent,p_meshForReg)
            # store the regressor
            archiveForRegressor.dump(regCurrent)
            setOfStates = StOptSDDP.SDDPVisitedStates(regCurrent.getNbMeshTotal())
            setOfStates.addVisitedStateForAll(p_optimizer.oneAdmissibleState(p_dates[idate + 1]),regCurrent)
            # ad admissible state
            vecSetOfStates[idate] =setOfStates
                                              
        simulatorForOptim.updateDateIndex(0)
        particlesInit = simulatorForOptim.getParticles()
        regInit= StOptSDDP.LocalLinearRegressionForSDDP(True,particlesInit,p_meshForReg)
        archiveForRegressor.dump(regInit)
        setOfStates = StOptSDDP.SDDPVisitedStates(1)
        setOfStates.addVisitedStateForAll(p_initialState,regInit)
        vecSetOfStates[0]= setOfStates

        for idate in range(0,p_dates.size-1):
            archiveForInitialState.dump(vecSetOfStates[idate])


    iterMax = p_iter;
    p_iter = 0;
    accuracy = p_accuracy;
    p_accuracy = 1e10;
    # archive to read regressor : currently all processor reads the regression
    archiveReadRegressor = StOptGeners.BinaryFileArchive(p_nameRegressor, "r");
    # only create for first task
    archiveForCuts = StOptGeners.BinaryFileArchive(p_nameCut, "w+");
    # to store  all backward values
    backwardValues =[]
    # forward value
    forwardValueForConv = 0.
    istep = 0;
    # store evolution of convergence
    backwardMinusForwardPrev = 0;
    while ((accuracy < p_accuracy) and (p_iter < iterMax)):
        # increase step
        istep += 1;
        # actualize time for simulators
        simulatorForOptim.resetTime()
        simulatorForSim.resetTime()
        
        if Found:
            world.Barrier()
        # backward sweep
        backwardValues.append(StOptSDDP.backwardSDDP(p_optimizer , simulatorForOptim, p_dates,  p_initialState,
                                                     p_finalCut, archiveReadRegressor,
                                                     p_nameVisitedStates , archiveForCuts))        
        if Found:
            world.Barrier()

        if ((istep == p_nStepConv) or (p_iter == 0)):
            istep = 0
            oldParticleNb = simulatorForSim.getNbSimul()
            simulatorForSim.updateSimulationNumberAndResetTime(p_nbSimulCheckForSimu)
            bIncreaseCut = False;
            
            forwardValueForConv =  StOptSDDP.forwardSDDP(p_optimizer , simulatorForSim, p_dates, p_initialState, p_finalCut, bIncreaseCut, archiveReadRegressor,
                                                         archiveForCuts, p_nameVisitedStates)

            p_accuracy  = abs((backwardValues[p_iter] - forwardValueForConv) / forwardValueForConv)
            simulatorForSim.updateSimulationNumberAndResetTime(oldParticleNb)

            if bTask:
                print(" ACCURACY ", p_accuracy, " Backward ", backwardValues[p_iter], " Forward ", forwardValueForConv , "p_iter "  ,p_iter , " accuracy " ,  p_accuracy )
            backwardMinusForward = backwardValues[p_iter] - forwardValueForConv;
            if (p_iter > 0):
                if (backwardMinusForward * backwardMinusForwardPrev < 0):
                    if bTask:
                        print(" Curve are crossing : increase sample and simulations to get more accurate solution, decrease step for checking convergence")
                    #exit
                    p_accuracy = 0.
            backwardMinusForwardPrev = backwardMinusForward;
        elif(p_iter>0):
            backwardMinusForward = backwardValues[p_iter] - forwardValueForConv;
            if (backwardMinusForward * backwardMinusForwardPrev < 0):
                if bTask:
                    print(" Curve are crossing : increase sample and simulations to get more accurate solution, decrease step for checking convergence")
                    #exit
                p_accuracy = 0.
        p_iter += 1;
    if Found:
        world.Barrier()
    return [backwardValues[p_iter - 1], forwardValueForConv]