Exemplo n.º 1
0
def test_nodes_6():
    ''' pytest pyswmm/tests/test_nodes.py -k `test_nodes_6` '''
    sim = Simulation(MODEL_WEIR_SETTING_PATH)
    print("\n\n\nNODES\n")
    J5 = Nodes(sim)["J5"]

    for ind, step in enumerate(sim):
        pass
    
    assert(J5.statistics['peak_total_inflow'] >= 0.478)
    assert(J5.statistics['average_depth'] >= 0.00018)
    assert(J5.statistics['surcharge_duration'] >= 0.0)
    assert(J5.statistics['max_ponded_volume'] >= 0.0)
    assert(J5.statistics['courant_crit_duration'] >= 0.0)
    assert(J5.statistics['peak_lateral_inflowrate'] >= 0.0)
    assert(J5.statistics['flooding_duration'] >= 0.0)
    assert(J5.statistics['peak_flooding_rate'] >= 0.0)
    assert(J5.statistics['lateral_infow_vol'] >= 0.0)
    assert(J5.statistics['max_flooding_date'] >= 42309)
    assert(J5.statistics['max_depth_date'] >= 42309)
    assert(J5.statistics['max_inflow_date'] >= 42309)
    assert(J5.statistics['max_depth'] >= 0.0292)
    assert(J5.statistics['flooding_volume'] >= 0.0)
    assert(J5.statistics['max_report_depth'] >= 0.0286)
    sim.close()
Exemplo n.º 2
0
def test_outfalls_8_mgd():
    ''' pytest pyswmm/tests/test_nodes.py -k `test_outfalls_8_mgd` '''
    sim = Simulation(MODEL_STORAGE_PUMP_MGD)
    print("\n\n\nOUTFALL\n")
    outfall = Nodes(sim)["J3"]
    storage = Nodes(sim)["SU1"]
    junction = Nodes(sim)["J2"]

    for ind, step in enumerate(sim):
        pass
    stats = outfall.outfall_statistics
    outfall_cuinflow = outfall.cumulative_inflow
    sim.close()

    assert (stats['total_periods'] == approx(208796, rel=UT_PRECISION))
    assert (stats['pollutant_loading']['test'] == approx(1305.25,
                                                         rel=UT_PRECISION))
    assert (stats['pollutant_loading']['test'] == approx(1305.75,
                                                         rel=UT_PRECISION))
    assert (stats['average_flowrate'] == approx(4.3, rel=UT_PRECISION))
    assert (stats['average_flowrate'] == approx(4.32, rel=UT_PRECISION))
    assert (stats['peak_flowrate'] == approx(4.33, rel=UT_PRECISION))
    assert (stats['peak_flowrate'] == approx(4.34, rel=UT_PRECISION))
    assert (outfall_cuinflow == approx(1395293, rel=UT_PRECISION))
    assert (outfall_cuinflow == approx(1395299, rel=UT_PRECISION)
            and outfall_cuinflow == approx(1395350, rel=UT_PRECISION))
Exemplo n.º 3
0
def test_simulation_1():
    sim = Simulation(MODEL_WEIR_SETTING_PATH)
    for ind, step in enumerate(sim):
        print(sim.current_time)
        sim.step_advance(randint(300, 900))

    sim.close()
Exemplo n.º 4
0
def test_simulation_1():
    sim = Simulation(MODEL_WEIR_SETTING_PATH)
    for ind, step in enumerate(sim):
        print(step.getCurrentSimulationTime())
        sim.step_advance(randint(300, 900))

    sim.report()
    sim.close()
Exemplo n.º 5
0
def test_outfalls_8():
    sim = Simulation(MODEL_STORAGE_PUMP)
    print("\n\n\nOUTFALL\n")
    outfall = Nodes(sim)["J3"]

    for ind, step in enumerate(sim):
        if ind % 1000 == 0:
            print(outfall.outfall_statistics)
    sim.close()
Exemplo n.º 6
0
def test_nodes_6():
    sim = Simulation(MODEL_WEIR_SETTING_PATH)
    print("\n\n\nNODES\n")
    J5 = Nodes(sim)["J5"]

    for ind, step in enumerate(sim):
        if ind % 1000 == 0:
            print(J5.statistics)
    sim.close()
Exemplo n.º 7
0
def test_outfalls_7():
    sim = Simulation(MODEL_STORAGE_PUMP)
    print("\n\n\nSTORAGE\n")
    STOR1 = Nodes(sim)["SU1"]

    for ind, step in enumerate(sim):
        if ind % 1000 == 0:
            print(STOR1.storage_statistics)
    sim.close()
Exemplo n.º 8
0
def test_storage_7():
    ''' pytest pyswmm/tests/test_nodes.py -k `test_storage_7` '''
    sim = Simulation(MODEL_STORAGE_PUMP)
    print("\n\n\nSTORAGE\n")
    STOR1 = Nodes(sim)["SU1"]

    for ind, step in enumerate(sim):
        pass

    stats = STOR1.storage_statistics
    assert (stats['max_volume'] == approx(5000.0, rel=UT_PRECISION))
    assert (stats['peak_flowrate'] == approx(0.0, rel=UT_PRECISION))
    assert (stats['exfil_loss'] == approx(0.0, rel=UT_PRECISION))
    assert (stats['evap_loss'] == approx(0.0, rel=UT_PRECISION))
    assert (stats['average_volume'] == approx(4979.0, rel=UT_PRECISION))
    assert (stats['average_volume'] == approx(4980.0, rel=UT_PRECISION))
    assert (stats['max_vol_date'] == approx(42309.0, rel=UT_PRECISION))
    assert (stats['max_vol_date'] == approx(42310.0, rel=UT_PRECISION))
    assert (stats['initial_volume'] == approx(0.0, rel=UT_PRECISION))

    stats = STOR1.statistics
    assert (stats['peak_total_inflow'] == approx(2.9, rel=UT_PRECISION))
    assert (stats['peak_total_inflow'] == approx(3.1, rel=UT_PRECISION))

    assert (stats['average_depth'] == approx(4.9, rel=UT_PRECISION))
    assert (stats['average_depth'] == approx(5, rel=UT_PRECISION))

    assert (stats['flooding_duration'] == approx(57, rel=UT_PRECISION))
    assert (stats['flooding_duration'] == approx(58, rel=UT_PRECISION))

    assert (stats['peak_flooding_rate'] == approx(2.9, rel=UT_PRECISION))
    assert (stats['peak_flooding_rate'] == approx(3.1, rel=UT_PRECISION))

    assert (stats['lateral_infow_vol'] == approx(0.0, rel=UT_PRECISION))

    assert (stats['max_flooding_date'] == approx(42309, rel=UT_PRECISION))
    assert (stats['max_flooding_date'] == approx(42310, rel=UT_PRECISION))

    assert (stats['max_depth_date'] == approx(42309, rel=UT_PRECISION))
    assert (stats['max_depth_date'] == approx(42310, rel=UT_PRECISION))

    assert (stats['max_inflow_date'] == approx(42309, rel=UT_PRECISION))
    assert (stats['max_inflow_date'] == approx(42310, rel=UT_PRECISION))

    assert (stats['max_depth'] == approx(4.99, rel=UT_PRECISION))
    assert (stats['max_depth'] == approx(5.01, rel=UT_PRECISION))

    assert (stats['flooding_volume'] == approx(621390, rel=UT_PRECISION))
    assert (stats['flooding_volume'] == approx(621393, rel=UT_PRECISION))

    assert (stats['max_report_depth'] == approx(4.99, rel=UT_PRECISION))
    assert (stats['max_report_depth'] == approx(5.01, rel=UT_PRECISION))

    print(STOR1.statistics)

    sim.close()
Exemplo n.º 9
0
def test_storage_7():
    ''' pytest pyswmm/tests/test_nodes.py -k `test_storage_7` '''
    sim = Simulation(MODEL_STORAGE_PUMP)
    print("\n\n\nSTORAGE\n")
    STOR1 = Nodes(sim)["SU1"]

    for ind, step in enumerate(sim):
        pass

    stats = STOR1.storage_statistics
    assert(stats['max_volume'] ==  5000.0)
    assert(stats['peak_flowrate'] ==  0.0)
    assert(stats['exfil_loss'] ==  0.0)
    assert(stats['evap_loss'] ==  0.0)
    assert(stats['average_volume'] >=  4979.0)
    assert(stats['average_volume'] <=  4980.0)
    assert(stats['max_vol_date'] >=  42309.0)
    assert(stats['max_vol_date'] <=  42310.0)
    assert(stats['initial_volume'] ==  0.0)

    stats = STOR1.statistics
    assert(stats['peak_total_inflow'] >= 2.9)
    assert(stats['peak_total_inflow'] <= 3.1)
    
    assert(stats['average_depth'] >= 4.9)
    assert(stats['average_depth'] <= 5)

    assert(stats['flooding_duration'] >= 57)
    assert(stats['flooding_duration'] <= 58)
    
    assert(stats['peak_flooding_rate'] >= 2.9)
    assert(stats['peak_flooding_rate'] <= 3.1)
    
    assert(stats['lateral_infow_vol'] == 0.0)
    
    assert(stats['max_flooding_date'] >= 42309)
    assert(stats['max_flooding_date'] <= 42310)
    
    assert(stats['max_depth_date'] >= 42309)
    assert(stats['max_depth_date'] <= 42310)
    
    assert(stats['max_inflow_date'] >= 42309)
    assert(stats['max_inflow_date'] <= 42310)

    assert(stats['max_depth'] >= 4.99)
    assert(stats['max_depth'] <= 5.01)
    
    assert(stats['flooding_volume'] >= 621390)
    assert(stats['flooding_volume'] <= 621393)
    
    assert(stats['max_report_depth'] >= 4.99)
    assert(stats['max_report_depth'] <= 5.01)

    print(STOR1.statistics)
    sim.close()
Exemplo n.º 10
0
def test_nodes_5():
    sim = Simulation(MODEL_WEIR_SETTING_PATH)
    print("\n\n\nNODES\n")
    J5 = Nodes(sim)["J5"]

    for ind, step in enumerate(sim):
        if ind == 7:
            J5.generated_inflow(544.0)
        if ind > 8:
            assert (J5.lateral_inflow >= 543.9)
            print(J5.lateral_inflow)
    sim.close()
Exemplo n.º 11
0
def test_nodes_5():
    sim = Simulation(MODEL_WEIR_SETTING_PATH)
    print("\n\n\nNODES\n")
    J5 = Nodes(sim)["J5"]

    for ind, step in enumerate(sim):
        if ind == 7:
            J5.generated_inflow(544.0)
        if ind > 8:
            assert (J5.lateral_inflow == approx(543.9, rel=UT_PRECISION))
            if ind % 1000 == 0:
                print(J5.lateral_inflow)
    sim.close()
Exemplo n.º 12
0
def test_nodes_11():
    ''' pytest pyswmm/tests/test_nodes.py -k `test_outfalls_8_mgd` '''
    sim = Simulation(MODEL_STORAGE_PUMP_MGD)
    print("\n\n\nOUTFALL\n")
    outfall = Nodes(sim)["J3"]

    for ind, step in enumerate(sim):
        pass
    stats = outfall.outfall_statistics
    outfall_cuinflow = outfall.cumulative_inflow
    sim.close()
    assert (outfall_cuinflow == approx(1395293, rel=UT_PRECISION))
    assert (outfall_cuinflow == approx(1395299, rel=UT_PRECISION)
            and outfall_cuinflow == approx(1395350, rel=UT_PRECISION))
Exemplo n.º 13
0
 def fit_func(nest, My_Current_step, CONTROL_RULES, Current_States):
     sim = Simulation(r"./test.inp")
     Linkname = ["C1", "C2", "O1", "O2"]
     Nodename = ["St1", "St2", "J1", "J2"]
     links = Links(sim)
     nodes = Nodes(sim)
     t = 0
     for link in Linkname:
         a2 = links[link]
         a2.initial_flow = Current_States[t][0]
         t = t + 1
     for node in Nodename:
         a1 = nodes[node]
         a1.initial_depth = Current_States[t][0]
         t = t + 1
     flood1 = np.array([])
     flood2 = np.array([])
     flood3 = np.array([])
     flood4 = np.array([])
     o1 = Links(sim)["O1"]
     o2 = Links(sim)["O2"]
     j1 = Nodes(sim)["J1"]
     j2 = Nodes(sim)["J2"]
     j3 = Nodes(sim)["St1"]
     j4 = Nodes(sim)["St2"]
     sim.start_time = my_Start_time + datetime.timedelta(
         minutes=My_timestep * (My_Current_step))
     sim.end_time = my_Start_time + datetime.timedelta(
         minutes=My_timestep * (My_Current_step + HorizonLength + 1))
     sim.step_advance(My_timestep * 60)
     CONTROL_RULES[My_Current_step:My_Current_step +
                   HorizonLength] = nest.reshape([4, -1])
     i = 0
     for step in sim:
         o1.target_setting = CONTROL_RULES[i + My_Current_step][0]
         o2.target_setting = CONTROL_RULES[i + My_Current_step][1]
         i = i + 1
         flood1 = np.append(flood1, [j1.flooding])
         flood2 = np.append(flood2, [j2.flooding])
         flood3 = np.append(flood3, [j3.flooding])
         flood4 = np.append(flood4, [j4.flooding])
     sim.close()
     return mytrape(flood1, 60 * My_timestep) + mytrape(
         flood2, 60 * My_timestep) + mytrape(
             flood3, 60 * My_timestep) + mytrape(flood4, 60 * My_timestep)
Exemplo n.º 14
0
def test_simulation_1():
    sim = Simulation(MODEL_WEIR_SETTING_PATH)
    print(f'system units: {sim.system_units}')
    print(f'swmm version: {sim._model.swmm_getVersion()}')
    allow_ponding = sim._model.getSimOptionSetting(
        tka.SimAnalysisSettings.AllowPonding)
    routing_step = sim._model.getSimAnalysisSetting(
        tka.SimulationParameters.RouteStep)
    print(f'analysis setting: {allow_ponding}')
    print(f'analysis param: {routing_step}')
    assert sim.system_units == 'US'
    assert not allow_ponding
    assert routing_step == 1
    for ind, step in enumerate(sim):
        print(sim.current_time)
        sim.step_advance(randint(300, 900))

    sim.close()
Exemplo n.º 15
0
def Initial_State():
    sim = Simulation(r"./test.inp")
    links = Links(sim)
    nodes = Nodes(sim)
    Linkname = ["C1", "C2", "O1", "O2"]
    Nodename = ["St1", "St2", "J1", "J2"]
    T = len(Linkname) + len(Nodename)
    Current_States = np.zeros([T, 1])
    t = 0
    for link in Linkname:
        a2 = links[link]
        Current_States[t][0] = a2.initial_flow
        t = t + 1
    for node in Nodename:
        a1 = nodes[node]
        Current_States[t][0] = a1.initial_depth
        t = t + 1
    sim.close()
    return Current_States
Exemplo n.º 16
0
def test_outfalls_8():
    ''' pytest pyswmm/tests/test_nodes.py -k `test_outfalls_8` '''
    sim = Simulation(MODEL_STORAGE_PUMP)
    print("\n\n\nOUTFALL\n")
    outfall = Nodes(sim)["J3"]

    for ind, step in enumerate(sim):
        pass
    stats = outfall.outfall_statistics
    outfall_cuinflow = outfall.cumulative_inflow
    sim.close()
    assert(stats['total_periods'] ==  208795)
    assert(stats['pollutant_loading']['test'] >= 1756)
    assert(stats['pollutant_loading']['test'] <= 1756.2)
    assert(stats['average_flowrate'] >= 8.9)
    assert(stats['average_flowrate'] <= 9.0)
    assert(stats['peak_flowrate'] > 9.0)
    assert(stats['peak_flowrate'] < 9.1)
    assert(outfall_cuinflow >= 1876800)
    assert(outfall_cuinflow <= 1876900)
Exemplo n.º 17
0
def test_outfalls_8_mgd():
    ''' pytest pyswmm/tests/test_nodes.py -k `test_outfalls_8_mgd` '''
    sim = Simulation(MODEL_STORAGE_PUMP_MGD)
    print("\n\n\nOUTFALL\n")
    outfall = Nodes(sim)["J3"]

    for ind, step in enumerate(sim):
        pass
    stats = outfall.outfall_statistics
    outfall_cuinflow = outfall.cumulative_inflow
    sim.close()
    
    assert(stats['total_periods'] ==  208795)
    assert(stats['pollutant_loading']['test'] >= 1305.25)
    assert(stats['pollutant_loading']['test'] <= 1305.75)
    assert(stats['average_flowrate'] >= 4.3)
    assert(stats['average_flowrate'] <= 4.32)
    assert(stats['peak_flowrate'] > 4.33)
    assert(stats['peak_flowrate'] < 4.34)
    assert(outfall_cuinflow >= 1395293)
    assert(outfall_cuinflow <= 1395299)
Exemplo n.º 18
0
def test_outfalls_8():
    ''' pytest pyswmm/tests/test_nodes.py -k `test_outfalls_8` '''
    sim = Simulation(MODEL_STORAGE_PUMP)
    print("\n\n\nOUTFALL\n")
    outfall = Nodes(sim)["J3"]

    for ind, step in enumerate(sim):
        pass
    stats = outfall.outfall_statistics
    outfall_cuinflow = outfall.cumulative_inflow
    sim.close()
    assert (stats['total_periods'] == approx(208796, rel=UT_PRECISION))
    assert (stats['pollutant_loading']['test'] == approx(1756,
                                                         rel=UT_PRECISION))
    assert (stats['pollutant_loading']['test'] == approx(1756.2,
                                                         rel=UT_PRECISION))
    assert (stats['average_flowrate'] == approx(8.9, rel=UT_PRECISION))
    assert (stats['average_flowrate'] == approx(9.0, rel=UT_PRECISION))
    assert (stats['peak_flowrate'] == approx(9.0, rel=UT_PRECISION))
    assert (stats['peak_flowrate'] == approx(9.1, rel=UT_PRECISION))
    assert (outfall_cuinflow == approx(1876800, rel=UT_PRECISION))
    assert (outfall_cuinflow == approx(1876900, rel=UT_PRECISION))
Exemplo n.º 19
0
class SWMM_env(Environment):
    """This class defines a simple thermostat environment.  It is a room with
    a heater, and when the heater is on, the room temperature will approach
    the max heater temperature (usually 1.0), and when off, the room will
    decay to a temperature of 0.0.  The exponential constant that determines
    how fast it approaches these temperatures over timesteps is tau.
    """

    # J: current_temp could be changed to current_flow which is Links(sim)["8"].flow*35.3147
    # J: this is where we define everything and start the swmm model
    def __init__(
        self, inp_file
    ):  # the max depth of the ponds is 2 meters. This I believe is also an intial setting
        ## Some initializations.  Will eventually parameterize this in the constructor.
        self.modelfile = inp_file
        self.sim = Simulation(self.modelfile)

        self.controlstep = 900  #in seconds
        self.sim.step_advance(self.controlstep)
        node_object = Nodes(self.sim)
        self.P1 = node_object["P1"]
        self.P2 = node_object["P2"]
        #self.depth = depth
        # self.P1.depth = self.depth
        # self.P2.depth = self.depth

        # init link objects - includes downstream link and both orifices
        link_object = Links(self.sim)
        self.L8 = link_object["8"]
        #self.flow = flow
        #self.L8.flow = self.L8.flow
        self.O1 = link_object["1"]
        self.O2 = link_object["2"]

        self.sim.start()
        if self.sim.current_time == self.sim.start_time:
            #initially sets the orifices at half way open
            self.O1.target_setting = 0.5
            self.O2.target_setting = 0.5
        sim_len = self.sim.end_time - self.sim.start_time
        self.T = int(sim_len.total_seconds() / self.controlstep)
        self.state = np.concatenate([
            np.asarray([
                self.P1.depth, self.P2.depth, self.L8.flow, self.P1.flooding,
                self.P2.flooding, self.O1.current_setting,
                self.O2.current_setting
            ])
        ])
        super().__init__()

# J: I think this should consider the 6 states referenced in the self.state line above.
# def states(self):
#     return dict(type='float', shape=(6,))

# J: would the actions be the position of the valves at P1 and P2? Would we need to figure
# J: out how to program the lid for this section, given two valve positions?
# need to add a min and a max value to capture everything between 0 and 1

    def actions(self):
        """Action 0 means no heater, temperature approaches 0.0.  Action 1 means
        the heater is on and the room temperature approaches 1.0.
        """
        return dict(type='int', num_values=2)

    #(original comment) Optional, should only be defined if environment has a natural maximum
    #(original comment) episode length
    # I can change the frequency (maybe 15 minutes, maybe something else)
    # def max_episode_timesteps(self):
    #     return super().max_episode_timesteps()

### J: Not sure how this works with the swmm model.
# Optional

    def close(self):
        self.sim.report()
        self.sim.close()

### J: Not sure how this works with the swmm model.

    def reset(self):
        """Reset state.
        """
        # state = np.random.random(size=(1,))

        self.sim.close()
        self.sim = Simulation(self.modelfile)
        self.sim.step_advance(self.controlstep)
        node_object = Nodes(self.sim)
        self.P1 = node_object["P1"]
        self.P2 = node_object["P2"]
        self.P1.depth = self.depth
        self.P2.depth = self.depth

        link_object = Links(self.sim)
        self.L8 = link_object["8"]
        self.L8.flow = self.flow
        self.sim.start()

        if self.sim.current_time == self.sim.start_time:
            self.L8.target_setting = 0

        self.state = np.concatenate([
            np.asarray([
                self.P1.depth, self.P2.depth, self.L8.flow, self.P1.flooding,
                self.P2.flooding, self.O1.current_setting,
                self.O2.current_setting
            ])
        ])

        return self.state

# J: The response should be the total flow in Pipe8, correct? We might not need this piece
# def response(self, action):
#     """Respond to an action.  When the action is 1, the temperature
#     exponentially decays approaches 1.0.  When the action is 0,
#     the current temperature decays towards 0.0.
#     """
#     return action + (self.current_temp - action) * math.exp(-1.0 / self.tau)

# J: The reward is 0 if the flow in Pipe8 is betwee, X1 and X2, or else we could have
# J: it negatively increase as the flow increases/decreases beyond the boundary.

    def reward_compute(self):
        """ The reward here is 0 if the current temp is between 0.4 and 0.6,
        else it is distance the temp is away from the 0.4 or 0.6 boundary.
        
        Return the value within the numpy array, not the numpy array.
        """

        # the reward should take into consideration flow being outside of desired range; should it also consider flooding?
        # reward needs to be based on the state - need to pass in new state information to calculate reward
        delta = abs(self.L8.flow - 0.25)
        if delta < 0.1:
            return 0.0
        else:
            return -delta[0] + 0.1

# check this with the step function in Ben's code

    def execute(self, actions):
        ## Check the action is either 0 or 1 -- heater on or off.

        self.O1.target_setting = actions[0]
        self.O2.target_setting = actions[1]

        self.sim.__next__()
        self.state = np.concatenate([
            np.asarray([
                self.P1.depth, self.P2.depth, self.P1.flooding,
                self.P2.flooding, self.L8.current_setting
            ])
        ])

        # ## Increment timestamp
        # self.timestep += 1

        # ## Update the current_temp
        # self.current_temp = self.response(actions)

        ## Compute the reward
        reward = self.reward_compute()

        ## The only way to go terminal is to exceed max_episode_timestamp.
        ## terminal == False means episode is not done
        ## terminal == True means it is done.
        terminal = False

        return self.state, terminal, reward
Exemplo n.º 20
0
from pyswmm import Simulation

sim = Simulation('D:\SWMMH\Examples\\test2.inp')
#sim.report()
sim.execute()
sim.close()

Exemplo n.º 21
0
class StormwaterEnv(gym.Env):
    def __init__(self, swmm_inp=""):
        self.floodings = -1
        self.eps_flooding = []
        self.eps_depths = [[], [], []]
        self.eps_action = [[], [], []]

        super(StormwaterEnv, self).__init__()
        self.total_rewards = []
        self.eps_reward = 0

        self.num_steps = 0

        self.timestep = 0
        self.time = 0
        self.swmm_inp = swmm_inp
        self.temp_height = np.zeros(2, dtype='int32')  # St1.depth, St2.depth
        self.temp_valve = np.zeros(
            2, dtype='int32')  # R1.current_setting, R2.current_setting
        self.i = 0
        self.flood = []

        self.log_dumps = []

        self.links = ['R1', 'R2', 'R3']
        self.nodes = ['St1', 'St2', 'St3']

        self.rl, self.baseline = [], []

    def reset(self, date=False, test=False):
        self.test = test
        self.settings, self.depths, self.flooding = [], [], []
        self.i += 1
        self.swmm_inp = "data/simple1.inp"
        dTest = date
        if (not dTest):
            with open("data/dates.txt", "r") as f:
                date = list(csv.reader(f, delimiter=' '))
                random.Random(10).shuffle(date)
                if not test:
                    time = (random.randint(0, int(len(date) * 0.9)))
                    self.test = False
                else:
                    if not self.test:
                        time = int(len(date) * 0.85)
                        self.test = True

                        time = 0
                    else:
                        self.time += 1
                        time = self.time

                self.time = time

                year = int(date[time][0])
                month = int(date[time][1])
                day = int(date[time][2])

                self.t = (str(year) + " " + str(month) + " " + str(day))

            self.date = [month, day, year]
            with open("data/simple1.inp", "r") as File:
                lines = File.readlines()
            with open("data/simple1.inp", "w") as File:
                for line in lines:
                    if "REPORT_START_DATE" in line:
                        File.write(line)
                    elif "START_DATE" in line:
                        File.write("START_DATE  " + str(month) + "/" +
                                   str(day) + "/" + str(year) + "\n")
                    elif "END_DATE" in line:
                        File.write("END_DATE  " + str((month)) + "/" +
                                   str(day + 1) + "/" + str(year) + "\n")
                    else:
                        File.write(line)
        if not dTest:
            self.eps_flooding.append(self.floodings)
            self.total_rewards.append(self.eps_reward)
        self.timestep += 1

        self.eps_reward = 0
        self.floodings = 0
        self.flood = []
        self.eps_depths = [[], [], []]
        self.eps_action = [[], [], []]

        self.num_steps = 0

        self.done = False

        self.current_step = 0

        self.sim = Simulation(self.swmm_inp)

        self.control_time_step = 900  # control time step in seconds
        self.sim.step_advance(self.control_time_step)  # set control time step

        self.node_object = Nodes(self.sim)
        self.link_object = Links(self.sim)
        print(self.i)
        self.sim.start()

        self.sim_len = self.sim.end_time - self.sim.start_time

        self.num_steps = int(self.sim_len.total_seconds() /
                             self.control_time_step)

        x = 0
        for i in self.links:
            y = random.randrange(1)
            self.link_object[i].target_setting = y
            self.eps_action[x].append(y)
            x += 1

        for i in self.links:
            self.settings.append(self.link_object[i].current_setting)

        for i in self.nodes:
            self.depths.append(self.node_object[i].depth)
            self.flooding.append(self.node_object[i].flooding)
        self.reward = reward_function(self.depths, self.flooding)

        self.eps_reward += self.reward

        state = []

        state = self.settings.copy()
        state.extend(self.depths)
        state.extend(self.flooding)

        self.day = []
        time = list(open("forcast.txt", "r"))
        time = list(map(lambda s: s.strip(), time))
        for i in time:
            if (self.t in i):
                self.day.append(i)

        time = str(self.sim.current_time).split(" ")
        time = time[1].split(":")

        cur = self.day[int(time[0])].split(" ")[3]
        nxt = self.day[int(time[0]) + 1].split(" ")[3]

        #cur = int(float(cur) * random.uniform(.95,1.05))
        #nxt = int(float(nxt) * random.uniform(.85,1.15))

        state.extend([cur, nxt])
        xx = []
        for x in state:
            xx.append(float(x) * random.uniform(0.9, 1.1))

        #state = [float(x) * random.uniform(0.9,1.1) for x in state]
        return state

    def step(self, action):

        self.current_step += 1
        self.settings, self.depths, self.flooding = [], [], []

        self.node_object = Nodes(self.sim)
        self.link_object = Links(self.sim)

        x = 0
        for i in self.links:
            self.link_object[i].target_setting = action[x]
            self.eps_action[x].append(action[x])
            x += 1

        self.sim.__next__()

        for i in self.links:
            self.settings.append(self.link_object[i].current_setting)
        ii = 0

        for i in self.nodes:
            self.depths.append(self.node_object[i].depth)
            self.flooding.append(self.node_object[i].flooding)
            self.eps_depths[ii].append(self.node_object[i].depth)
            ii += 1
        self.floodings += sum(self.flooding)
        self.flood.append(sum(self.flooding))
        self.reward = reward_function(self.depths, self.flooding)

        self.eps_reward += self.reward

        state = []
        state = self.settings.copy()
        state.extend(self.depths)
        state.extend(self.flooding)

        time = str(self.sim.current_time).split(" ")
        time = time[1].split(":")

        cur = self.day[int(time[0])].split(" ")[3]
        if (int(time[0]) < 23):
            nxt = self.day[int(time[0]) + 1].split(" ")[3]
        else:
            nxt = 0

        cur = int(float(cur) * random.uniform(.95, 1.05))
        nxt = int(float(nxt) * random.uniform(.85, 1.15))

        state.extend([cur, nxt])

        xx = []
        for x in state:
            xx.append(float(x) * random.uniform(0.9, 1.1))
        return state, self.reward, self.done  #, {} # {} is debugging information

    def close(self):
        self.sim.report()
        self.sim.close()

    def graph(self, location, end=False):
        with open("plots/data.csv", "a") as f:
            writer = csv.writer(f, delimiter=',')
            writer.writerow([self.i])
        self.eps_flooding.append(self.floodings)
        self.total_rewards.append(self.eps_reward)
        self.eps_depths.append(self.eps_reward)

        self.old_flooding = self.floodings
        self.old_rewards = self.eps_reward
        self.floodrl = self.flood
        self.depthsRL = self.eps_depths
        self.actionRL = self.eps_action

        self.reset(date=True)
        for i in range(self.num_steps - 1):
            self.step([1, 1, 1])

        self.flooding1 = self.floodings
        self.eps_reward1 = self.eps_reward
        self.flood1 = self.flood
        self.depths1 = self.eps_depths
        self.action1 = self.eps_action

        #"Flooding_Sum_P, Reward_Sum_P, Flooding_CFS_P, J1_Depths_P,J2_Depths_P,J3_Depths_P,R1_P,R2_P, Flooding_Sum_RL, Reward_Sum_RL, Flooding_CFS_RL, J1_Depths_RL,J2_Depths_RL,J3_Depths_RL,R1_RL,R2_RL"
        rows =([[self.flooding1], [self.eps_reward1], self.flood1, self.depths1[0],self.depths1[1],self.depths1[2], self.action1[0], self.action1[1], \
            [self.old_flooding], [self.old_rewards], self.floodrl, self.depthsRL[0],self.depthsRL[1],self.depthsRL[2], self.actionRL[0], self.actionRL[1]])

        columns = [
            "Flooding_Sum_P", "Reward_Sum_P", "Flooding_CFS_P", "J1_Depths_P",
            "J2_Depths_P", "J3_Depths_P", "R1_P", "R2_P", "Flooding_Sum_RL",
            "Reward_Sum_RL", "Flooding_CFS_RL", "J1_Depths_RL", "J2_Depths_RL",
            "J3_Depths_RL", "R1_RL", "R2_RL"
        ]

        with open("plots/data.csv", "a") as f:
            writer = csv.writer(f, delimiter=',')
            x = 0
            for row in rows:
                row = list(row)
                row.insert(0, columns[x])
                writer.writerow(row)
                x += 1
class BasicEnv(Env):
    def __init__(self, inp_file, fcst_file, depth=4.61):
        # initialize simulation
        self.input_file = inp_file
        self.sim = Simulation(self.input_file)  # read input file
        self.fcst_file = fcst_file
        self.fcst = np.genfromtxt(self.fcst_file,
                                  delimiter=',')  # read forecast file as array
        self.control_time_step = 900  # control time step in seconds
        self.sim.step_advance(self.control_time_step)  # set control time step
        node_object = Nodes(self.sim)  # init node object
        self.St1 = node_object["St1"]
        self.St2 = node_object["St2"]
        self.J1 = node_object["J1"]
        self.depth = depth
        self.St1.full_depth = self.depth
        self.St2.full_depth = self.depth

        link_object = Links(self.sim)  # init link object
        self.R1 = link_object["R1"]
        self.R2 = link_object["R2"]

        self.sim.start()
        if self.sim.current_time == self.sim.start_time:
            self.R1.target_setting = 0.5
            self.R2.target_setting = 0.5
        sim_len = self.sim.end_time - self.sim.start_time
        self.T = int(sim_len.total_seconds() / self.control_time_step)
        self.t = 1
        self.state = np.concatenate([
            np.asarray([
                self.St1.depth, self.St2.depth, self.J1.depth,
                self.St1.flooding, self.St2.flooding, self.J1.flooding,
                self.R1.current_setting, self.R2.current_setting
            ]), self.fcst[self.t]
        ])
        self.action_space = spaces.Box(low=np.array([0, 0]),
                                       high=np.array([1, 1]),
                                       dtype=np.float32)
        self.observation_space = spaces.Box(low=0,
                                            high=1000,
                                            shape=(len(self.state), ),
                                            dtype=np.float32)

    def step(self, action):

        self.R1.target_setting = action[0]
        self.R2.target_setting = action[1]
        self.sim.__next__()

        self.state = np.concatenate([
            np.asarray([
                self.St1.depth, self.St2.depth, self.J1.depth,
                self.St1.flooding, self.St2.flooding, self.J1.flooding,
                self.R1.current_setting, self.R2.current_setting
            ]), self.fcst[self.t]
        ])

        if self.t < self.T - 1:
            reward = 0
            done = False
        else:
            reward = -(self.St1.statistics['flooding_volume'] * 100 +
                       self.St2.statistics['flooding_volume'] * 100 +
                       self.J1.statistics['flooding_volume'] * 0.5)
            done = True

        self.t += 1

        info = {}

        return self.state, reward, done, info

    def reset(self):
        self.sim.close()
        self.sim = Simulation(self.input_file)
        self.fcst = np.genfromtxt(self.fcst_file,
                                  delimiter=',')  # read forecast file as array
        self.sim.step_advance(self.control_time_step)  # set control time step
        node_object = Nodes(self.sim)  # init node object
        self.St1 = node_object["St1"]
        self.St2 = node_object["St2"]
        self.J1 = node_object["J1"]
        link_object = Links(self.sim)  # init link object
        self.R1 = link_object["R1"]
        self.R2 = link_object["R2"]
        self.St1.full_depth = self.depth
        self.St2.full_depth = self.depth
        self.sim.start()
        self.t = 1
        if self.sim.current_time == self.sim.start_time:

            self.R1.target_setting = 0.5
            self.R2.target_setting = 0.5

        self.state = np.concatenate([
            np.asarray([
                self.St1.depth, self.St2.depth, self.J1.depth,
                self.St1.flooding, self.St2.flooding, self.J1.flooding,
                self.R1.current_setting, self.R2.current_setting
            ]), self.fcst[self.t]
        ])
        return self.state

    def close(self):
        self.sim.report()
        self.sim.close()
Exemplo n.º 23
0
class StormwaterEnv(gym.Env):
    metadata = {'render.modes': ['human']}

    def __init__(self, R=6, J=4, swmm_inp="data/simple3.inp"):

        super(StormwaterEnv, self).__init__()
        self.total_rewards = []
        self.eps_reward = 0

        self.global_current_step = 0
        self.current_step = 0
        self.control_time_step = 900

        self.swmm_inp = swmm_inp
        self.temp_height = np.zeros(2, dtype='int32')  # St1.depth, St2.depth
        self.temp_valve = np.zeros(
            2, dtype='int32')  # R1.current_setting, R2.current_setting

        self.R = R
        self.J = J

        self.log_dumps = [[]]

    def reset(self):
        # make this dynamic later
        self.swmm_inp = "data/simple3.inp"
        self.sim = Simulation(self.swmm_inp)
        self.sim.step_advance(self.control_time_step)  # set control time step

        self.node_object = Nodes(self.sim)
        self.link_object = Links(self.sim)

        self.total_rewards.append(self.eps_reward)
        self.eps_reward = 0

        self.global_current_step += 1
        self.current_step = 0

        self.done = False

        self.sim.start()

        self.sim_len = self.sim.end_time - self.sim.start_time
        self.T = self.sim_len.total_seconds() // self.control_time_step

        for i in range(1, self.R + 1):
            self.link_object['R' + str(i)].target_setting = random.randrange(1)

        self.settings = [
            self.link_object['R' + str(i)].current_setting
            for i in range(1, self.R + 1)
        ]

        # one for loop would be faster but less readable
        # making new lists all the time is probably bad
        self.depths = [
            self.node_object['St' + str(i)].depth
            for i in range(1, self.R + 1)
        ]
        self.depths.extend([
            self.node_object['J' + str(i)].depth for i in range(2, self.J + 1)
        ])

        self.flooding = [
            self.node_object['St' + str(i)].flooding
            for i in range(1, self.R + 1)
        ]
        self.flooding.extend([
            self.node_object['J' + str(i)].flooding
            for i in range(2, self.J + 1)
        ])

        self.reward = reward_function(self.depths, self.flooding)

        self.eps_reward += self.reward

        return np.asarray(self.settings + self.depths + self.flooding)

        # Take action
        # + Initiate the step in the simulation
        # Make observation / calculate state
        # calculate the reward
        # check if done
        # Do some logging for graphing

    def step(self, action):
        self.current_step += 1  # Decide whether this should be before or after taking actions

        ##### Take Action #####
        for i in range(1, self.R + 1):
            self.link_object['R' + str(i)].target_setting = action[i - 1]

        self.sim.__next__()

        ##### Make Observation #####
        self.settings = [
            self.link_object['R' + str(i)].current_setting
            for i in range(1, self.R + 1)
        ]

        self.depths = [
            self.node_object['St' + str(i)].depth
            for i in range(1, self.R + 1)
        ]
        self.depths.extend([
            self.node_object['J' + str(i)].depth for i in range(2, self.J + 1)
        ])

        self.flooding = [
            self.node_object['St' + str(i)].flooding
            for i in range(1, self.R + 1)
        ]
        self.flooding.extend([
            self.node_object['J' + str(i)].flooding
            for i in range(2, self.J + 1)
        ])

        # one for loop would be faster but less readable  (For the above)
        # making new lists all the time is probably bad
        #   Actually timed this and performed better than changing the elements

        ##### Calculate Reward #####
        self.reward = -np.max(self.flooding) * np.sum(self.flooding)
        self.eps_reward += self.reward

        ##### Check if Done #####
        self.done = False if self.current_step < self.T - 1 else True

        ##### for graphing #####
        if self.current_step == 1:
            # self.log_dumps.append([])
            self.log_dumps[-1] = []
        self.log_dumps[-1].append(
            (self.reward, [self.settings, self.depths,
                           self.flooding], self.current_step))
        return np.asarray(self.settings + self.depths +
                          self.flooding), self.reward, self.done, {
                          }  # {} is debugging information

    def close(self):
        self.sim.report()
        self.sim.close()

    def render(self, mode="human"):
        # This's probably not useful at all at the moment but should be here
        return str(self.settings) + "\n" + str(self.depths) + "\n" + str(
            self.flooding) + "\n"

    def graph(self, location):
        for plot, dump in enumerate(self.log_dumps[-1:]):
            settings, depths, floodings = [[] for i in range(self.R)], [
                [] for i in range(self.R + self.J - 1)
            ], [[] for i in range(self.R + self.J - 1)]
            rewards = []

            for reward, state, timestep in dump:  # timestep should stay local here

                rewards.append(reward)
                setting, depth, flooding = state

                for i, R in enumerate(settings):
                    R.append(setting[i])
                for i, S_depth in enumerate(depths):
                    S_depth.append(depth[i])
                for i, S_flooding in enumerate(floodings):
                    S_flooding.append(flooding[i])

            for i in range(1, self.R + 1):
                plt.subplot(2, 3, i)
                plt.plot(settings[i - 1])
                plt.ylim(0, 1)
                plt.title('R' + str(i))
                plt.ylabel("Valve Opening")
                plt.xlabel("time step")

            plt.tight_layout()
            if (plot == 5):
                plt.savefig(location + "TEST_" + str(timestep) + "_STATES",
                            dpi=300)
            else:
                plt.savefig(location + str(timestep) + "_STATES", dpi=300)

            plt.clf()

            for i in range(1, self.R + 1):
                plt.subplot(2, 3, i)
                plt.plot(depths[i - 1])
                plt.ylim(0, 5)
                plt.title('St' + str(i) + " Depth")
                plt.ylabel("Feet")
                plt.xlabel("time step")

            plt.tight_layout()
            if (plot == 5):
                plt.savefig(location + "TEST_" + str(timestep) + "_DEPTHS",
                            dpi=300)
            else:
                plt.savefig(location + str(timestep) + "_DEPTHS", dpi=300)

            plt.clf()

            for i in range(2, self.J + 1):
                plt.subplot(2, 2, i - 1)
                plt.plot(floodings[self.R + i - 2])
                plt.title('J' + str(i) + " flooding")
                plt.ylabel("Feet")
                plt.xlabel("time step")

            plt.subplot(2, 2, 4)
            plt.bar([0, 1, 2, 3, 4, 5, 6, 7, 8],
                    [sum(floodings[i]) for i in range(len(floodings))],
                    tick_label=[
                        "St1", "St2", "St3", "St4", "St5", "St6", "J2", "J3",
                        "J4"
                    ])
            plt.ylim(0)
            plt.title('total_flooding')
            plt.ylabel("10^3 cubic feet")
            plt.xlabel("time step")

            plt.tight_layout()

            if (plot == 5):
                plt.savefig(location + "TEST_" + str(timestep) + "_FLOODING",
                            dpi=300)
            else:
                plt.savefig(location + str(timestep) + "_FLOODING", dpi=300)

            plt.clf()

            plt.subplot(2, 1, 1)
            plt.plot(rewards)
            # plt.ylim(0, 5)
            plt.title('Rewards')
            plt.ylabel("Reward")
            plt.xlabel("time step")

            plt.subplot(2, 1, 2)
            plt.ylim(-5000, 0)
            plt.plot(self.total_rewards)
            plt.title('Total Rewards')
            plt.ylabel("Reward")
            plt.xlabel("eps")

            plt.tight_layout()

            if (plot == 5):
                plt.savefig(location + "TEST_" + str(timestep) + "_REWARDS",
                            dpi=300)
            else:
                plt.savefig(location + str(timestep) + "_REWARDS", dpi=300)

            plt.clf()
Exemplo n.º 24
0
class BasicEnv(Env):
    def __init__(self,depth=5):
        # initialize simulation
        self.sim = Simulation(swmm_inp)  # read input file
        self.control_time_step = 900  # control time step in seconds
        self.sim.step_advance(self.control_time_step)  # set control time step
        node_object = Nodes(self.sim)  # init node object
        self.St1 = node_object["St1"]
        self.St2 = node_object["St2"]
        self.J3 = node_object["J3"]
        self.depth = depth
        self.St1.full_depth = self.depth
        self.St2.full_depth = self.depth
        
        link_object = Links(self.sim)  # init link object
        self.R1 = link_object["R1"]
        self.R2 = link_object["R2"]
    
        self.sim.start()
        if self.sim.current_time == self.sim.start_time:
            self.R1.target_setting = 0.5
            self.R2.target_setting = 0.5
        sim_len = self.sim.end_time - self.sim.start_time
        self.T = int(sim_len.total_seconds()/self.control_time_step)
        self.t = 1
        #print('T=', self.T)        

        self.state = np.asarray([self.St1.depth, self.St2.depth, self.J3.depth, 
                                  self.St1.flooding, self.St2.flooding, self.J3.flooding])
         
        self.action_space = spaces.Box(low=np.array([0,0]),high=np.array([1,1]), dtype=np.float32)
        self.observation_space = spaces.Box(low=0, high = 1000, shape=(len(self.state),),dtype=np.float32)
        
    def step(self,action):
        
        self.R1.target_setting = action[0]
        self.R2.target_setting = action[1]
        self.sim.__next__()
         
        self.state = np.asarray([self.St1.depth, self.St2.depth, self.J3.depth, 
                                  self.St1.flooding, self.St2.flooding, self.J3.flooding])
        reward = - (self.St1.flooding + self.St2.flooding + self.J3.flooding)
        
        if self.t < self.T-1 :
            done = False
        else:
            done = True
           # self.sim.close()
        
        self.t += 1
        
        info = {}
        
        return self.state, reward, done, info       
    
    def reset(self):
        self.sim.close()
        self.sim = Simulation(swmm_inp)
        self.sim.step_advance(self.control_time_step)  # set control time step
        node_object = Nodes(self.sim)  # init node object
        self.St1 = node_object["St1"]
        self.St2 = node_object["St2"]
        self.J3 = node_object["J3"]        
        link_object = Links(self.sim)  # init link object
        self.R1 = link_object["R1"]
        self.R2 = link_object["R2"]
        self.St1.full_depth = self.depth
        self.St2.full_depth = self.depth
        self.sim.start()
        self.t = 1
        if self.sim.current_time == self.sim.start_time:
            
            self.R1.target_setting = 0.5
            self.R2.target_setting = 0.5
        
        self.state = np.asarray([self.St1.depth, self.St2.depth, self.J3.depth, 
                                  self.St1.flooding, self.St2.flooding, self.J3.flooding])
        return self.state
    
    def close(self):
        self.sim.report()
        self.sim.close()
Exemplo n.º 25
0
class BasicEnv(Env):
    def __init__(self, inp_file, fcst_file):
        # initialize simulation
        self.input_file = inp_file
        self.sim = Simulation(self.input_file)  # read input file
        self.fcst_file = fcst_file
        # self.fcst = np.genfromtxt(self.fcst_file, delimiter=',')  # read forecast file as array
        self.fcst = pd.read_csv(self.fcst_file, index_col="datetime", infer_datetime_format=True, parse_dates=True)
        self.control_time_step = 900  # control time step in seconds
        self.sim.step_advance(self.control_time_step)  # set control time step
        node_object = Nodes(self.sim)  # init node object
        self.St1 = node_object["st1"]
        self.St2 = node_object["st2"]
        self.St3 = node_object["F134101"]

        link_object = Links(self.sim)  # init link object
        self.R1 = link_object["R1"]
        self.R2 = link_object["R2"]
        self.R3 = link_object["R3"]
    
        self.sim.start()
        if self.sim.current_time == self.sim.start_time:
            self.R1.target_setting = 0.5
            self.R2.target_setting = 1
            self.R3.target_setting = 0.5
        sim_len = self.sim.end_time - self.sim.start_time
        self.T = int(sim_len.total_seconds()/self.control_time_step)
        self.t = 1

        current_fcst = self.fcst.iloc[self.fcst.index.get_loc(self.sim.current_time, method='nearest')]
        rain_fcst = sum(current_fcst[:int(len(current_fcst) / 2)])  # total rainfall in forecast
        tide_fcst = np.mean(current_fcst[int(len(current_fcst) / 2):])  # mean tide in forecast
        # self.state = np.concatenate([np.asarray([self.St1.depth, self.St3.depth, self.St1.flooding, self.St3.flooding,
        #                                          self.R1.current_setting, self.R3.current_setting]),
        #                              current_fcst])
        # self.state = np.asarray([self.St1.depth, self.St3.depth, self.St1.flooding, self.St3.flooding,
        #                          self.R1.current_setting, self.R3.current_setting,
        #                          rain_fcst, tide_fcst])
        self.state = np.asarray([self.St1.depth, self.St3.depth, self.St1.flooding, self.St3.flooding,
                                 self.R1.current_setting, self.R3.current_setting,
                                 self.R1.pollut_quality['TSS'], self.R3.pollut_quality['TSS'], rain_fcst, tide_fcst])
        self.action_space = spaces.Box(low=np.array([0, 0]), high=np.array([1, 1]), dtype=np.float32)
        self.observation_space = spaces.Box(low=0, high=1000, shape=(len(self.state),), dtype=np.float32)
        
    def step(self, action):
        self.R1.target_setting = action[0]
        self.R3.target_setting = action[1]
        self.sim.__next__()

        # self.state = np.concatenate([np.asarray([self.St1.depth, self.St3.depth, self.St1.flooding, self.St3.flooding,
        #                                          self.R1.current_setting, self.R3.current_setting]), self.fcst[self.t]])
        current_fcst = self.fcst.iloc[self.fcst.index.get_loc(self.sim.current_time, method='nearest')]
        rain_fcst = sum(current_fcst[:int(len(current_fcst) / 2)])  # total rainfall in forecast
        tide_fcst = np.mean(current_fcst[int(len(current_fcst) / 2):])  # mean tide in forecast
        # self.state = np.asarray([self.St1.depth, self.St3.depth, self.St1.flooding, self.St3.flooding,
        #                          self.R1.current_setting, self.R3.current_setting,
        #                          rain_fcst, tide_fcst])
        self.state = np.asarray([self.St1.depth, self.St3.depth, self.St1.flooding, self.St3.flooding,
                                 self.R1.current_setting, self.R3.current_setting,
                                 self.R1.pollut_quality['TSS'], self.R3.pollut_quality['TSS'], rain_fcst, tide_fcst])

        # # 1 flood and depth reward
        # reward = - (self.St1.flooding + self.St3.flooding + abs(self.St1.depth - 7.5) + abs(self.St3.depth - 3.56))

        # # 2 Conditional reward, no pollutants
        # if rain_fcst > 0:  # check if rainfall forecast is positive
        #     reward = - (self.St1.flooding + self.St3.flooding)  # instead of flood, use abs difference from pond max?
        # else:
        #     reward = - (abs(self.St1.depth - 7.5) + abs(self.St3.depth - 3.56))

        # 3 flood and pollutant reward
        reward = - (self.St1.flooding + self.St3.flooding + abs(self.St1.depth - 7.5) + abs(self.St3.depth - 3.56) +
                    self.R1.pollut_quality['TSS'] + self.R3.pollut_quality['TSS'])

        # # 4 conditional with pollutants reward
        # if np.sum(self.fcst[self.t, :-1]) > 0:  # check if rainfall forecast is positive
        # reward = - (self.St1.flooding + self.St3.flooding + self.R1.pollut_quality + self.R3.pollut_quality)
        # else:
        #     reward = - (abs(self.St1.depth - 7.5) + abs(self.St3.depth - 3.56) +
        #                 self.R1.pollut_quality + self.R3.pollut_quality)

        if self.t < self.T-1:
            done = False
        else:
            done = True
        
        self.t += 1
        
        info = {}
        
        return self.state, reward, done, info       
    
    def reset(self):
        self.sim.close()
        self.sim = Simulation(self.input_file)
        # self.fcst = np.genfromtxt(self.fcst_file, delimiter=',')  # read forecast file as array
        self.fcst = pd.read_csv(self.fcst_file, index_col="datetime", infer_datetime_format=True, parse_dates=True)
        self.sim.step_advance(self.control_time_step)  # set control time step
        node_object = Nodes(self.sim)  # init node object
        self.St1 = node_object["st1"]
        self.St2 = node_object["st2"]
        self.St3 = node_object["F134101"]
        link_object = Links(self.sim)  # init link object
        self.R1 = link_object["R1"]
        self.R2 = link_object["R2"]
        self.R3 = link_object["R3"]
        self.sim.start()
        self.t = 1
        if self.sim.current_time == self.sim.start_time:
            self.R1.target_setting = 0.5
            self.R2.target_setting = 1
            self.R3.target_setting = 0.5

        # self.state = np.concatenate([np.asarray([self.St1.depth, self.St3.depth, self.St1.flooding, self.St3.flooding,
        #                                          self.R1.current_setting, self.R3.current_setting]), self.fcst[self.t]])
        current_fcst = self.fcst.iloc[self.fcst.index.get_loc(self.sim.current_time, method='nearest')]
        rain_fcst = sum(current_fcst[:int(len(current_fcst) / 2)])  # total rainfall in forecast
        tide_fcst = np.mean(current_fcst[int(len(current_fcst) / 2):])  # mean tide in forecast
        # self.state = np.asarray([self.St1.depth, self.St3.depth, self.St1.flooding, self.St3.flooding,
        #                          self.R1.current_setting, self.R3.current_setting,
        #                          rain_fcst, tide_fcst])
        self.state = np.asarray([self.St1.depth, self.St3.depth, self.St1.flooding, self.St3.flooding,
                                 self.R1.current_setting, self.R3.current_setting,
                                 self.R1.pollut_quality['TSS'], self.R3.pollut_quality['TSS'], rain_fcst, tide_fcst])
        return self.state
    
    def close(self):
        self.sim.report()
        self.sim.close()