Source code for evnrg.simulation.fleet
import numpy as np
import pandas as pd
from .vehicle import Vehicle
from evnrg.common.powertrain import Powertrain
from .eligibility import EligibilityRules
__all__ = [
'Fleet'
]
[docs]class Fleet(object):
"""A collection of vehicles and data connecting them."""
__slots__ = (
'df',
'vehicles',
'size'
)
def __init__(self, df: pd.DataFrame, powertrains: list,
probabilities: list, rules: EligibilityRules):
self.df = df.astype(np.float32, copy=False)
self.vehicles = []
self.size = self.df.values.shape[1]
if isinstance(powertrains, list):
for pt in powertrains:
if not isinstance(pt, Powertrain):
raise TypeError()
trains = powertrains
num_trains = len(powertrains)
num_probs = len(probabilities)
probs = probabilities
if not probabilities:
probs = [float(1.0 / num_trains) for i in range(num_trains)]
elif num_probs < num_trains:
current_sum = sum(probs)
if current_sum < 1:
remaining = num_trains - num_probs
distribution = (1 - current_sum) / remaining
probs.extend([distribution for i in range(remaining)])
else:
trains = powertrains[:num_probs]
elif num_trains < num_probs:
probs = probabilities[:num_trains]
pt_assignments = np.random.choice(
range(num_trains),
size=self.size,
replace=True,
p=np.array(probs)
)
for pt, vid in zip(pt_assignments, range(self.size)):
vehicle = Vehicle(
vid,
trains[pt],
self.df.values[:, vid],
rules
)
self.vehicles.append(vehicle)
@property
def vehicle_ids(self):
return self.df.columns.to_list()
@property
def fleet_ids(self):
return [self.df.columns.get_loc(i) for i in self.df.columns]
[docs] def add_vehicle(self, col_id, pt: Powertrain, rules: EligibilityRules):
if not (col_id in self.vehicle_ids):
raise IndexError()
v = Vehicle(
list(self.df.columns).index[col_id],
self.df[col_id].values,
rules
)
self.vehicles.append(v)
[docs] def assign_powertrains(self, powertrains: list,
probabilities: list, rules: EligibilityRules):
self.vehicles = []
if isinstance(powertrains, list):
for pt in powertrains:
if not isinstance(pt, Powertrain):
raise TypeError()
trains = powertrains
num_trains = len(powertrains)
num_probs = len(probabilities)
probs = probabilities
if not probabilities:
probs = [float(1.0 / num_trains) for i in range(num_trains)]
elif num_probs < num_trains:
current_sum = sum(probs)
if current_sum < 1:
remaining = num_trains - num_probs
distribution = (1 - current_sum) / remaining
probs.extend([distribution for i in range(remaining)])
else:
trains = powertrains[:num_probs]
elif num_trains < num_probs:
probs = probabilities[:num_trains]
pt_assignments = np.random.choice(trains, self.size, True, probs)
for pt, vid in zip(pt_assignments, self.vehicle_ids):
self.add_vehicle(vid, pt)
[docs] def get_powertrain_distribution(self, powertrains: list,
probabilities: list,
rules: EligibilityRules):
self.vehicles = []
if isinstance(powertrains, list):
for pt in powertrains:
if not isinstance(pt, Powertrain):
raise TypeError()
trains = powertrains
num_trains = len(powertrains)
num_probs = len(probabilities)
probs = probabilities
if not probabilities:
probs = [float(1.0 / num_trains) for i in range(num_trains)]
elif num_probs < num_trains:
current_sum = sum(probs)
if current_sum < 1:
remaining = num_trains - num_probs
distribution = (1 - current_sum) / remaining
probs.extend([distribution for i in range(remaining)])
else:
trains = powertrains[:num_probs]
elif num_trains < num_probs:
probs = probabilities[:num_trains]
pt_assignments = np.random.choice(trains, self.size, True, probs)
for pt, vid in zip(pt_assignments, self.vehicle_ids):
self.add_vehicle(vid, pt)