def __init__(self, current_battery_percentage=100.0, battery_capacity=5.0, charging_rate=1.0): #super(Battery, self).__init__() self.current_battery_percentage = current_battery_percentage self.battery_capacity = battery_capacity self.charging_rate = charging_rate self.mean_battery = 50 self.variance_battery = 0 # self.min_mean_battery = 999999.9 # self.max_mean_battery = -999999.9 # self.min_variance_battery = 999999.9 # self.max_variance_battery = -999999.9 self.mean_battery_bounds = Bounds() self.variance_battery_bounds = Bounds(reset_count=300)
def __init__(self, centroids): self.centroids = centroids Centroid.centroids = centroids Bounds(centroids) Border.reset() # starting over each frame Centroid.reset() # starting over each frame l = len(Centroid.centroids) for n1 in range(1, len(Centroid.centroids)): print '%i/%i' % (n1, l) c1 = Centroid.centroids[n1] # dist-sort, & break when c1 in enclosed others = DistSort(c1, [Centroid.centroids[n2] for n2 in range(n1)]) B = [] for c2 in others: b = Border(c1, c2) for bb in B: if bb.nIntersects < 2: i = b.validate_BorderBorderIntersectPoint(bb) if i and b.nIntersects == 2: break B.append(b) if {bb.nIntersects for bb in B} == {2}: break for c in Centroid.centroids: if not c.isClosed: c.addCornerVert()
def __init__(self, loads = None): if loads is None: loads = [] self.loads = loads self.num_loads = 0 self.current_demand = 0.0 self.demands = [] # self.min_demand = 999999.0 # self.max_demand = 0.0 self.demand_bounds = Bounds()
def __init__(self, sourceID = None, capacity = 10000.0, current_price = 0.0, with_agent = False, look_ahead = 1): super().__init__() if sourceID is None: sourceID = Source.num_sources self.sourceID = sourceID self.supply_capacity = capacity # MW self.current_price = current_price self.prices = [] self.with_agent = with_agent self.look_ahead = look_ahead self.price_bounds = Bounds() # self.min_price = 100000.0 # self.future_max = 0.0 # self.future_min = 999999.9 # self.update_count = 0 # self.max_price = 0.0 self.dumb_load_range = DemandRange(0.0,0.0) Source.num_sources +=1
def __init__(self, demand_ranges = None, batteryParams = None, loadID = None, with_agent=False, look_ahead = 1): if loadID is None: loadID = Load.num_loads Load.num_loads += 1 if demand_ranges is None: #Because http://docs.python-guide.org/en/latest/writing/gotchas/ if self.RANDOMIZE_DEMANDS: demand_ranges = [[DemandRange.default_lower_bound,DemandRange.default_upper_bound]] * 288 else: demand_ranges = [] with open(self.csv_input_file, 'r') as csv_file: reader = csv.reader(csv_file) for line in reader: try: _demands = None # ignore initial lines of csv file if line[0].startswith("#") or len(line)<2: next(reader) continue except IndexError: _demands = [[float(val) for val in value] for value in reader] # [0] is lower bounds, [1] is upper bounds print(len(_demands), len(_demands[0]), len(_demands[1])) if _demands is None or len(_demands) != 2 or len(_demands[0]) != 288 or len(_demands[1]) != 288: raise AssertionError("Expected timestep size of 5 mins. Data doesn't match.") for i in range(len(_demands[0])): demand_ranges.append([_demands[0][i], _demands[1][i]]) if batteryParams is None: batteryParams = {} self.demand_ranges = [] for demand_range in demand_ranges: self.demand_ranges.append(DemandRange(float(demand_range[0]), float(demand_range[1]))) self.battery = Battery(**batteryParams) self.demands = list() self.loadID = loadID self.with_agent = with_agent self.costs = list() self.look_ahead = look_ahead self.demand_bounds = Bounds()
class Battery(object): """ Member Variables CurrentBatteryPercentage - FLOAT value from 0 to 100 Battery Capacity - Total energy it can store - FLOAT value in kWh Update Battery Percentage - takes current energy demand and suitably updates battery percentage Charging rate kW Member functions Getters and Setters and Constructor """ HISTORY_FACTOR = .999 # as ln(.9)/ln(.01) ~= 44 def __init__(self, current_battery_percentage=100.0, battery_capacity=5.0, charging_rate=1.0): #super(Battery, self).__init__() self.current_battery_percentage = current_battery_percentage self.battery_capacity = battery_capacity self.charging_rate = charging_rate self.mean_battery = 50 self.variance_battery = 0 # self.min_mean_battery = 999999.9 # self.max_mean_battery = -999999.9 # self.min_variance_battery = 999999.9 # self.max_variance_battery = -999999.9 self.mean_battery_bounds = Bounds() self.variance_battery_bounds = Bounds(reset_count=300) def get_battery_bounds(self): return [ self.mean_battery_bounds.get_bounds(), self.variance_battery_bounds.get_bounds() ] def update_battery_bounds(self, mean, var): # self.min_mean_battery = min(mean, self.min_mean_battery) # self.max_mean_battery = max(mean, self.max_mean_battery) # self.min_variance_battery = min(var, self.min_variance_battery) # self.max_variance_battery = max(var, self.max_variance_battery) self.mean_battery_bounds.update_bounds(mean) self.variance_battery_bounds.update_bounds(math.pow(var, 0.5)) def get_current_battery_percentage(self): return self.current_battery_percentage def set_current_battery_percentage(self, current_battery_percentage): self.current_battery_percentage = min( 100, max(0, current_battery_percentage)) self.mean_battery += (1 - self.HISTORY_FACTOR) * ( current_battery_percentage - self.mean_battery) self.variance_battery += (1 - self.HISTORY_FACTOR) * ( (current_battery_percentage - self.mean_battery)**2 - self.variance_battery) self.update_battery_bounds(self.mean_battery, self.variance_battery) def update_battery_percentage(self, energy_demand): self.current_battery_percentage -= ( (energy_demand / self.battery_capacity) * 100) def get_battery_capacity(self): return self.battery_capacity def get_charging_rate(self): return self.charging_rate def set_charging_rate(self, charging_rate): self.charging_rate = charging_rate def get_battery_reward_factor(self): return 0.5 / (1 + math.exp( (-self.current_battery_percentage + 40) / 10)) + 1 def get_mean_battery(self): return self.mean_battery def get_variance_battery(self): return math.pow(self.variance_battery, 0.5)
class Source(DemandManager): num_sources = 0 action_space = [0,1,2,3,4] base_pricing_constant = 10.0 action_price_map = {0:1.0, 1:0.7, 2:0.3, 3:1.5, 4: 2.5} no_agent_action = 0 def __init__(self, sourceID = None, capacity = 10000.0, current_price = 0.0, with_agent = False, look_ahead = 1): super().__init__() if sourceID is None: sourceID = Source.num_sources self.sourceID = sourceID self.supply_capacity = capacity # MW self.current_price = current_price self.prices = [] self.with_agent = with_agent self.look_ahead = look_ahead self.price_bounds = Bounds() # self.min_price = 100000.0 # self.future_max = 0.0 # self.future_min = 999999.9 # self.update_count = 0 # self.max_price = 0.0 self.dumb_load_range = DemandRange(0.0,0.0) Source.num_sources +=1 def reset_day(self): super().reset_day(self.look_ahead) if len(self.prices)>0: self.current_price = self.prices[-1] self.prices = get_last_k(self.prices, self.look_ahead) def step(self, action=None): if action is None: action = Source.no_agent_action # if not self.with_agent: # action = Source.no_agent_action if action not in Source.action_space: raise AssertionError("Not a valid action") self.prices.append(self.calculate_base_price() * 1.0 * Source.action_price_map.get(action)) # print('priced %f times original price with action %d' % (Source.action_price_map[action], action)) self.current_price = self.prices[-1] self.price_bounds.update_bounds(self.current_price) self.demand_bounds.update_bounds(self.current_demand) return self.get_previous_price() * super().get_current_demand() def calculate_base_price(self): if self.get_current_demand()< 0.9*self.supply_capacity: return Source.base_pricing_constant * super().get_previous_demand() / self.num_loads else: return 1 * Source.base_pricing_constant * super().get_previous_demand() / self.num_loads def set_look_ahead(self, look_ahead): self.look_ahead = look_ahead def get_look_ahead(self): return self.look_ahead def get_prices(self): return self.prices def get_current_price(self): return self.current_price def get_previous_price(self): if len(self.prices)<2: return 0.0 else: return self.prices[-2] def is_with_agent(self): return self.with_agent def get_supply_capacity(self): return self.supply_capacity def add_load(self,loadID): flag = super().add_load(loadID) if flag: print('Load %d successfully linked to source %d' % (loadID, self.sourceID)) else: print('Load %d already handled by source %d' % (loadID, self.sourceID)) def remove_load(self, loadID): flag = super().remove_load(loadID) if flag: print('Load %d successfully removed from source %d' % (loadID, self.sourceID)) else: print('Load %d is not handled by source %d' % (loadID, self.sourceID)) def sample_action(self): return Source.action_space[randint(0,len(Source.action_space))] # def update_price_bounds(self,price): # if not price <= 0: # self.future_min = min(self.future_min, price) # self.future_max = max(self.future_max, price) # self.update_count+=1 # if self.update_count+1 % 1000 == 0: # self.update_count = 0 # self.min_price = self.future_min # self.max_price = self.future_max # self.future_max = 0.0 # self.future_min = 99999.9 # # def get_price_bounds(self): # return [self.min_price, self.max_price] def add_dumb_load_range(self, lowerbound, upperbound): self.dumb_load_range.set_lower_bound(self.dumb_load_range.get_lower_bound()+lowerbound) self.dumb_load_range.set_upper_bound(self.dumb_load_range.get_upper_bound()+upperbound) def remove_dumb_load_range(self, lowerbound, upperbound): self.dumb_load_range.set_lower_bound(self.dumb_load_range.get_lower_bound()-lowerbound) self.dumb_load_range.set_upper_bound(self.dumb_load_range.get_upper_bound()-upperbound) def add_dumb_loads(self,n=None, ranges = None): if n is None: for demandrange in ranges: self.add_dumb_load_range(demandrange[0], demandrange[1]) self.num_loads+=len(ranges) return if ranges is None: ranges = [[DemandRange.default_lower_bound, DemandRange.default_upper_bound]] numranges = len(ranges) for i in range(n): if i < numranges: self.add_dumb_load_range(ranges[i][0], ranges[i][1]) else: self.add_dumb_load_range(ranges[-1][0], ranges[-1][1]) self.num_loads += n
def addDigit(self, unit, lowerBound, upperBound): # assert type(unit) is FloatType, "unit is not a float" + str(unit) self.digits[unit] = Bounds(lowerBound, upperBound)
class Load(object): """ Member Variables Demand ranges throughout the day (Array of DemandRange objects) Battery Object DailyDemandCurve - stores demand generated so far during the day LoadID WithAgent - boolean indicating presence of agent Member Functions Getters and Setters and Constructor GenerateDemandAndUpdateCurve(action) ResetDay() CalculateReward() Daily demand analytics and visualization functions Time of day - value from 0 to 287 (5 min intervals for 24 hours) Actions 0-SB,SC 1-SC 2-BC """ # global num_loads num_loads = 0 default_timestep_size = 5.0 action_space = [0,1,2] no_agent_action = 1 RANDOMIZE_DEMANDS = True csv_input_file = "household_demand_2.csv" THRESHOLD = 5 def __init__(self, demand_ranges = None, batteryParams = None, loadID = None, with_agent=False, look_ahead = 1): if loadID is None: loadID = Load.num_loads Load.num_loads += 1 if demand_ranges is None: #Because http://docs.python-guide.org/en/latest/writing/gotchas/ if self.RANDOMIZE_DEMANDS: demand_ranges = [[DemandRange.default_lower_bound,DemandRange.default_upper_bound]] * 288 else: demand_ranges = [] with open(self.csv_input_file, 'r') as csv_file: reader = csv.reader(csv_file) for line in reader: try: _demands = None # ignore initial lines of csv file if line[0].startswith("#") or len(line)<2: next(reader) continue except IndexError: _demands = [[float(val) for val in value] for value in reader] # [0] is lower bounds, [1] is upper bounds print(len(_demands), len(_demands[0]), len(_demands[1])) if _demands is None or len(_demands) != 2 or len(_demands[0]) != 288 or len(_demands[1]) != 288: raise AssertionError("Expected timestep size of 5 mins. Data doesn't match.") for i in range(len(_demands[0])): demand_ranges.append([_demands[0][i], _demands[1][i]]) if batteryParams is None: batteryParams = {} self.demand_ranges = [] for demand_range in demand_ranges: self.demand_ranges.append(DemandRange(float(demand_range[0]), float(demand_range[1]))) self.battery = Battery(**batteryParams) self.demands = list() self.loadID = loadID self.with_agent = with_agent self.costs = list() self.look_ahead = look_ahead self.demand_bounds = Bounds() # self.min_demand = 999999.0 # self.max_demand = 0.0 # for key in params: # setattr(self,key,params[key]) def step(self, timestep, timestep_size= default_timestep_size, action=None): """timestep_size is in minutes""" # if not self.with_agent: # action = Load.no_agent_action if action is None: action = Load.no_agent_action if action not in Load.action_space: raise AssertionError("Not a valid action") timestep = normalize_timestep(timestep, timestep_size, Load.default_timestep_size) penalty_factor = 0 if action == 0: #checks self.demands.append(self.demand_ranges[timestep].generate_demand()) battery_percentage_increase = ((self.battery.get_charging_rate()*(timestep_size/60.0))/self.battery.get_battery_capacity()) * 100.0 new_battery_percentage_increase = min(battery_percentage_increase, 100.0 - self.battery.get_current_battery_percentage()) self.battery.set_current_battery_percentage(self.battery.get_current_battery_percentage()+new_battery_percentage_increase) self.demand_bounds.update_bounds(self.demands[-1]) penalty_factor = 5*(battery_percentage_increase-new_battery_percentage_increase)/battery_percentage_increase # if self.battery.current_battery_percentage >100.0- self.THRESHOLD: # penalty_factor = 5 * (self.THRESHOLD + self.battery.current_battery_percentage - 100.0) / self.THRESHOLD return [self.demands[-1], (self.battery.get_battery_capacity() * new_battery_percentage_increase/100)*60 / timestep_size, penalty_factor] elif action == 1: #checks self.demands.append(self.demand_ranges[timestep].generate_demand()) self.demand_bounds.update_bounds(self.demands[-1]) return [self.demands[-1], 0, penalty_factor] elif action == 2: #checks self.demands.append(self.demand_ranges[timestep].generate_demand()) battery_percentage_decrease = ((self.demands[-1]*(timestep_size/60.0))/self.battery.get_battery_capacity()) * 100.0 new_battery_percentage_decrease = min(battery_percentage_decrease, self.battery.get_current_battery_percentage()) self.battery.set_current_battery_percentage(self.battery.get_current_battery_percentage() - new_battery_percentage_decrease) # controllable = battery_percentage_decrease* self.battery.get_battery_capacity()*60/ (timestep_size*100) uncontrollable = - new_battery_percentage_decrease* self.battery.get_battery_capacity()*60/ (timestep_size*100) # self.demands.append((battery_percentage_decrease - new_battery_percentage_decrease) * self.battery.get_battery_capacity()*60/ (timestep_size*100)) self.demand_bounds.update_bounds(self.demands[-1]) penalty_factor = 5*(battery_percentage_decrease-new_battery_percentage_decrease)/battery_percentage_decrease # if self.battery.current_battery_percentage < self.THRESHOLD: # penalty_factor = 5 * (self.THRESHOLD - self.battery.current_battery_percentage) / self.THRESHOLD return [self.demands[-1], uncontrollable,penalty_factor] # *2 is penalty for discharging battery to 0% else: raise AssertionError("I don't know why this is happening") # def update_demand_bounds(self, demand): # if not demand <= 0: # self.min_demand = min(self.min_demand, demand) # self.max_demand = max(self.max_demand, demand) # # def get_demand_bounds(self): # return [self.min_demand, self.max_demand] def get_demand_ranges(self): return self.demand_ranges def get_battery(self): return self.battery def get_demands(self): return self.demands def get_loadID(self): return self.loadID def is_with_agent(self): return self.with_agent def get_costs(self): return self.get_costs def set_demand_ranges(self, demand_ranges): self.demand_ranges = demand_ranges def set_battery(self, battery): self.battery = battery def set_loadID(self, loadID): self.loadID = loadID def set_demands(self, demands): self.demands = demands def set_with_agent(self, with_agent): self.with_agent = with_agent def set_costs(self, costs): self.costs = costs def reset_day(self, battery_reset = False): self.demands = get_last_k(self.demands, self.look_ahead) self.costs = get_last_k(self.costs, self.look_ahead) if battery_reset is True: self.battery.set_current_battery_percentage(100*random()) elif isinstance(battery_reset,int) or isinstance(battery_reset, float): self.battery.set_current_battery_percentage(battery_reset) def set_look_ahead(self, look_ahead): self.look_ahead = look_ahead def get_look_ahead(self): return self.look_ahead def sample_action(self): return Load.action_space[randint(0,len(Load.action_space))]