diff --git a/.idea/EVCH_OM.iml b/.idea/EVCH_OM.iml
index 2c80e12..c6c7ca6 100644
--- a/.idea/EVCH_OM.iml
+++ b/.idea/EVCH_OM.iml
@@ -4,7 +4,7 @@
-
+
\ No newline at end of file
diff --git a/Operations/NonLinearAlgorithms.py b/Operations/NonLinearAlgorithms.py
index 2436ed6..4a29a53 100644
--- a/Operations/NonLinearAlgorithms.py
+++ b/Operations/NonLinearAlgorithms.py
@@ -1,9 +1,85 @@
# # First party modules
-from pyoptsparse import SLSQP, Optimization, pyOpt_objective
+# from pyoptsparse import SLSQP, Optimization, pyOpt_objective
import numpy as np
from Environment.helper.configuration.configuration import Configuration
+from scipy.optimize import minimize
+import numpy as np
+
+
+def nonlinear_pricing(vehicles_list, electricity_cost, PV, base_load, sim_time,
+ p_0=np.zeros(24) + 0.2, smart_charging=True):
+ BIG_T = 24
+ delta_time = 60
+ vehicle_range = range(len(vehicles_list))
+ time_range = range(BIG_T)
+
+ # Extract data from vehicles
+ A, De, T, beta, D = [], [], [], [], []
+ for v in vehicles_list:
+ A.append(int(v.arrival_period / delta_time))
+ De.append(int(v.departure_period / delta_time))
+ T.append(int(v.park_duration / 60))
+ beta.append(v.utility_beta)
+ D.append(v.energy_requested)
+
+ peak_penalty = Configuration.instance().peak_cost
+ peak_threshold = Configuration.instance().peak_threshold
+
+ def obj(x):
+ alpha = x[:BIG_T]
+ if Configuration.instance().dynamic_fix_term_pricing:
+ p_0_vec = x[BIG_T:2 * BIG_T]
+ else:
+ p_0_vec = p_0
+ p_star = x[-1] if smart_charging else 0
+
+ cost = 0
+ for i in vehicle_range:
+ for t in time_range:
+ if A[i] <= t <= De[i]:
+ charge = ((2 * beta[i] * D[i] - p_0_vec[t]) * T[i]) / (2 * (beta[i] * T[i] + alpha[t]))
+ cost += (p_0_vec[t] + alpha[t] * charge / T[i]) * charge
+ cost += electricity_cost[t] * charge
+ if smart_charging:
+ cost += p_star * peak_penalty
+ return cost
+
+ constraints = []
+
+ if smart_charging:
+ def peak_constraint(x):
+ alpha = x[:BIG_T]
+ p_0_vec = x[BIG_T:2 * BIG_T] if Configuration.instance().dynamic_fix_term_pricing else p_0
+ p_star = x[-1]
+ con = []
+ for t in time_range:
+ total_charging = 0
+ for i in vehicle_range:
+ if A[i] <= t <= De[i]:
+ charge = ((2 * beta[i] * D[i] - p_0_vec[A[i]]) * T[i]) / (2 * (beta[i] * T[i] + alpha[A[i]]))
+ total_charging += charge / T[i]
+ con.append(total_charging + base_load[t] - PV[t] - p_star - peak_threshold)
+ return np.array(con)
+ constraints.append({'type': 'ineq', 'fun': lambda x: -peak_constraint(x)})
+
+ # Initial guess and bounds
+ n_var = BIG_T + BIG_T + (1 if smart_charging else 0)
+ x0 = np.concatenate([np.full(BIG_T, 0.2), np.full(BIG_T, 0.3)])
+ if smart_charging:
+ x0 = np.concatenate([x0, [20]])
+
+ bounds = [(0, 0.5)] * BIG_T # alpha bounds
+ if Configuration.instance().dynamic_fix_term_pricing:
+ bounds += [(0, 1)] * BIG_T # p_0 bounds
+ if smart_charging:
+ bounds += [(0, 1200)] # p_star
+
+ result = minimize(obj, x0, method='SLSQP', bounds=bounds, constraints=constraints, options={'disp': True})
+ return result
+
+# For this model you need to install pyoptsparse
# def nonlinear_pricing(vehicles_list,electricity_cost, PV, base_load, sim_time, p_0=np.zeros(24) + 0.2, smart_charging=False):
# # rst begin objfunc
@@ -168,266 +244,260 @@
# return (sol.xStar)
-def nonlinear_pricing(
- vehicles_list,
- electricity_cost,
- PV,
- base_load,
- sim_time,
- p_0=np.zeros(24) + 0.2,
- smart_charging=True,
-):
- # rst begin objfunc
- vehicle_range = range(len(vehicles_list))
- peak_charge_penalty = Configuration.instance().peak_cost
- beta = [vehicle.utility_beta for vehicle in vehicles_list]
- D = [vehicle.energy_requested for vehicle in vehicles_list]
- T = np.zeros(len(vehicles_list))
- A = np.zeros(len(vehicles_list))
- De = np.zeros(len(vehicles_list))
- delta_time = 60
- BIG_T = 24
- time_range = range(BIG_T)
- AB = {} # np.full((len(vehicles_list), len(time_range)), 1)
- U = {}
- C = {}
- print(PV)
- print(base_load)
- for t in time_range:
- hour = int((t % 24))
- C[t] = electricity_cost[hour]
- for i in vehicle_range:
- # SOC[i.id] = i.energy_charged
- A[i] = int(vehicles_list[i].arrival_period / delta_time)
- beta[i] = vehicles_list[i].utility_beta
- D[i] = vehicles_list[i].energy_requested
- De[i] = int(vehicles_list[i].departure_period / delta_time)
- T[i] = int(vehicles_list[i].park_duration / 60)
-
- for t in time_range:
- if A[i] <= t <= De[i]:
- U[i, t] = 1
- else:
- U[i, t] = 0
- for t in time_range:
- if A[i] == t:
- AB[i, t] = 1
- else:
- AB[i, t] = 0
-
- # T = [vehicle.energy_requested for vehicle in vehicles_list]
- def objfunc(xdict):
- x = np.full((len(vehicle_range), len(time_range)), 0)
- if Configuration.instance().capacity_pricing:
- alpha = xdict["alpha"]
- else:
- alpha = np.zeros(BIG_T) + 0
- if Configuration.instance().dynamic_fix_term_pricing:
- p_0 = xdict["p_0"]
- else:
- p_0 = (
- np.zeros(BIG_T)
- + Configuration.instance().instance().price_parameters[0]
- )
- if smart_charging:
- # y = xdict['y'].reshape(len(vehicle_range), len(time_range))
- p_star = xdict["p_star"]
- # pv_usage = xdict['pv_usage']
- # for i in vehicle_range:
- # for t in time_range:
- # x[i, t] = ((2 * beta[i] * D[i] - p_0[t]) * T[i] * AB[i, t]) / (2 * (beta[i] * T[i] + alpha[t]))
- # if x[i, t] != 0:
- # print(np.sum(x))
- funcs = {}
-
- energy_charged = 0
- funcs["obj"] = 0
-
- for t in time_range:
- # if smart_charging:
- # funcs["obj"] -= pv_usage[t] * electricity_cost[t]
- for i in vehicle_range:
-
- # power = x[i, t]/T[i]
-
- # funcs["obj"] -= (p_0[t] -0.15 + alpha[t] * power) * x[i, t]
- # -np.sum(np.array(electricity_cost)*y[i, :]))
- if not smart_charging:
- if (
- Configuration.instance().dynamic_fix_term_pricing
- and not Configuration.instance().capacity_pricing
- ):
- funcs["obj"] -= (p_0[t] - 0.15) * (
- (2 * beta[i] * D[i] - p_0[t]) * AB[i, t] / (2 * beta[i])
- )
- (2 * beta[i] * D[i] - p_0[t]) * AB[i, t] / (2 * beta[i])
- else:
- funcs["obj"] -= (
- p_0[t]
- - 0.15
- + alpha[t]
- * (
- ((2 * beta[i] * D[i] - p_0[t]) * T[i] * AB[i, t])
- / (2 * (beta[i] * T[i] + alpha[t]))
- )
- / T[i]
- ) * (
- ((2 * beta[i] * D[i] - p_0[t]) * T[i] * AB[i, t])
- / (2 * (beta[i] * T[i] + alpha[t]))
- )
-
- else:
-
- funcs["obj"] -= (
- p_0[t]
- + alpha[t]
- * (
- ((2 * beta[i] * D[i] - p_0[t]) * T[i] * AB[i, t])
- / (2 * (beta[i] * T[i] + alpha[t]))
- )
- / T[i]
- ) * (
- ((2 * beta[i] * D[i] - p_0[t]) * T[i] * AB[i, t])
- / (2 * (beta[i] * T[i] + alpha[t]))
- ) - electricity_cost[
- t
- ] * (
- (
- (
- ((2 * beta[i] * D[i] - p_0[int(A[i])]) * T[i])
- / (2 * (beta[i] * T[i] + alpha[int(A[i])]))
- )
- / T[i]
- * U[i, t]
- )
- )
-
- energy_charged += ((2 * beta[i] * D[i] - p_0[t]) * T[i] * AB[i, t]) / (
- 2 * (beta[i] * T[i] + alpha[t])
- )
- if smart_charging:
- funcs["obj"] -= -p_star * peak_charge_penalty
- if not smart_charging:
- conval = [0] * BIG_T
- for t in time_range:
- conval[t] = alpha[t] + p_0[t]
- funcs["con"] = conval
- if smart_charging:
- # conval = [0] * BIG_T * len(vehicle_range)
- # for i in vehicle_range:
- # for t in time_range:
- # conval[i*BIG_T+t] = y[i,t]-U[i,t]*50
- # funcs["con1"] = conval
- # conval = [0] * len(vehicle_range)
- # for i in vehicle_range:
- # conval[i] = np.sum(y[i,:]) - ((2 * beta[i] * D[i] - p_0[int(A[i])]) * T[i]) / (2 * (beta[i] * T[i] + alpha[int(A[i])]))
- # funcs["con2"] = conval
- conval = [0] * BIG_T
- for t in time_range:
- total_charging = 0
- for i in vehicle_range:
- total_charging += (
- ((2 * beta[i] * D[i] - p_0[int(A[i])]) * T[i])
- * U[i, t]
- / (2 * (beta[i] * T[i] + alpha[int(A[i])]))
- ) / T[i]
- conval[t] = (
- total_charging
- + base_load[t]
- - PV[t]
- - p_star
- - Configuration.instance().peak_threshold
- )
- funcs["con3"] = conval
-
- # conval = [0] * BIG_T
- # for t in time_range:
- # total_charging = 0
- # for i in vehicle_range:
- # total_charging += (((2 * beta[i] * D[i] - p_0[int(A[i])])
- # * T[i]) * U[i, t] / (2 * (beta[i] * T[i] + alpha[int(A[i])]))) / T[i]
- # conval[t] = total_charging + base_load[t] - pv_usage[t]
- # funcs["con4"] = conval
- #
- # conval = [0] * BIG_T
- # for t in time_range:
- # conval[t] = PV[t] - pv_usage[t]
- # funcs["con5"] = conval
- fail = False
- if smart_charging:
- print(energy_charged, funcs["obj"], p_star)
-
- return funcs, fail
-
- # rst begin optProb
- # Optimization Object
- optProb = Optimization("TP037 Constraint Problem", objfunc)
-
- # rst begin addVar
- # Design Variables
- optProb.addVarGroup(
- "alpha",
- BIG_T,
- "c",
- lower=np.zeros(BIG_T),
- upper=np.zeros(BIG_T) + 0.5,
- value=0.2,
- )
- if Configuration.instance().dynamic_fix_term_pricing:
- optProb.addVarGroup(
- "p_0",
- BIG_T,
- "c",
- lower=np.zeros(BIG_T),
- upper=np.zeros(BIG_T) + 1,
- value=0.3,
- )
- if smart_charging:
- # optProb.addVarGroup("y", BIG_T*len(vehicles_list), "c", lower=np.zeros(BIG_T*len(vehicles_list)),
- # upper=np.zeros(BIG_T*len(vehicles_list)) + 50, value=1)
- optProb.addVar(name="p_star", varType="c", lower=0, upper=1200, value=20)
- # optProb.addVarGroup("pv_usage", BIG_T, "c", lower=np.zeros(BIG_T), upper=np.zeros(BIG_T) + 1000, value=0)
-
- # rst begin addCon
- # Constraints
- if not smart_charging:
- optProb.addConGroup("con", BIG_T, lower=0)
- if smart_charging:
- # optProb.addConGroup("con1", BIG_T*len(vehicles_list), upper=0)
- # optProb.addConGroup("con2", len(vehicles_list), lower=0)
- optProb.addConGroup("con3", BIG_T, upper=0)
- # optProb.addConGroup("con4", BIG_T, lower=0)
- # optProb.addConGroup("con5", BIG_T, lower=0)
-
- # rst begin addObj
- # Objective
- optProb.addObj("obj")
-
- # rst begin print
- # Check optimization problem
- # print(optProb)
-
- # rst begin OPT
- # Optimizer
- optOptions = {"IPRINT": -1}
- opt = SLSQP(options=optOptions)
+# def nonlinear_pricing(
+# vehicles_list,
+# electricity_cost,
+# PV,
+# base_load,
+# sim_time,
+# p_0=np.zeros(24) + 0.2,
+# smart_charging=True,
+# ):
+# # rst begin objfunc
+# vehicle_range = range(len(vehicles_list))
+# peak_charge_penalty = Configuration.instance().peak_cost
+# beta = [vehicle.utility_beta for vehicle in vehicles_list]
+# D = [vehicle.energy_requested for vehicle in vehicles_list]
+# T = np.zeros(len(vehicles_list))
+# A = np.zeros(len(vehicles_list))
+# De = np.zeros(len(vehicles_list))
+# delta_time = 60
+# BIG_T = 24
+# time_range = range(BIG_T)
+# AB = {} # np.full((len(vehicles_list), len(time_range)), 1)
+# U = {}
+# C = {}
+# print(PV)
+# print(base_load)
+# for t in time_range:
+# hour = int((t % 24))
+# C[t] = electricity_cost[hour]
+# for i in vehicle_range:
+# # SOC[i.id] = i.energy_charged
+# A[i] = int(vehicles_list[i].arrival_period / delta_time)
+# beta[i] = vehicles_list[i].utility_beta
+# D[i] = vehicles_list[i].energy_requested
+# De[i] = int(vehicles_list[i].departure_period / delta_time)
+# T[i] = int(vehicles_list[i].park_duration / 60)
+#
+# for t in time_range:
+# if A[i] <= t <= De[i]:
+# U[i, t] = 1
+# else:
+# U[i, t] = 0
+# for t in time_range:
+# if A[i] == t:
+# AB[i, t] = 1
+# else:
+# AB[i, t] = 0
+#
+# # T = [vehicle.energy_requested for vehicle in vehicles_list]
+# def objfunc(xdict):
+# x = np.full((len(vehicle_range), len(time_range)), 0)
+# if Configuration.instance().capacity_pricing:
+# alpha = xdict["alpha"]
+# else:
+# alpha = np.zeros(BIG_T) + 0
+# if Configuration.instance().dynamic_fix_term_pricing:
+# p_0 = xdict["p_0"]
+# else:
+# p_0 = (
+# np.zeros(BIG_T)
+# + Configuration.instance().instance().price_parameters[0]
+# )
+# if smart_charging:
+# # y = xdict['y'].reshape(len(vehicle_range), len(time_range))
+# p_star = xdict["p_star"]
+# # pv_usage = xdict['pv_usage']
+# # for i in vehicle_range:
+# # for t in time_range:
+# # x[i, t] = ((2 * beta[i] * D[i] - p_0[t]) * T[i] * AB[i, t]) / (2 * (beta[i] * T[i] + alpha[t]))
+# # if x[i, t] != 0:
+# # print(np.sum(x))
+# funcs = {}
+#
+# energy_charged = 0
+# funcs["obj"] = 0
+#
+# for t in time_range:
+# # if smart_charging:
+# # funcs["obj"] -= pv_usage[t] * electricity_cost[t]
+# for i in vehicle_range:
+#
+# # power = x[i, t]/T[i]
+#
+# # funcs["obj"] -= (p_0[t] -0.15 + alpha[t] * power) * x[i, t]
+# # -np.sum(np.array(electricity_cost)*y[i, :]))
+# if not smart_charging:
+# if (
+# Configuration.instance().dynamic_fix_term_pricing
+# and not Configuration.instance().capacity_pricing
+# ):
+# funcs["obj"] -= (p_0[t] - 0.15) * (
+# (2 * beta[i] * D[i] - p_0[t]) * AB[i, t] / (2 * beta[i])
+# )
+# (2 * beta[i] * D[i] - p_0[t]) * AB[i, t] / (2 * beta[i])
+# else:
+# funcs["obj"] -= (
+# p_0[t]
+# - 0.15
+# + alpha[t]
+# * (
+# ((2 * beta[i] * D[i] - p_0[t]) * T[i] * AB[i, t])
+# / (2 * (beta[i] * T[i] + alpha[t]))
+# )
+# / T[i]
+# ) * (
+# ((2 * beta[i] * D[i] - p_0[t]) * T[i] * AB[i, t])
+# / (2 * (beta[i] * T[i] + alpha[t]))
+# )
+#
+# else:
+#
+# funcs["obj"] -= (
+# p_0[t]
+# + alpha[t]
+# * (
+# ((2 * beta[i] * D[i] - p_0[t]) * T[i] * AB[i, t])
+# / (2 * (beta[i] * T[i] + alpha[t]))
+# )
+# / T[i]
+# ) * (
+# ((2 * beta[i] * D[i] - p_0[t]) * T[i] * AB[i, t])
+# / (2 * (beta[i] * T[i] + alpha[t]))
+# ) - electricity_cost[
+# t
+# ] * (
+# (
+# (
+# ((2 * beta[i] * D[i] - p_0[int(A[i])]) * T[i])
+# / (2 * (beta[i] * T[i] + alpha[int(A[i])]))
+# )
+# / T[i]
+# * U[i, t]
+# )
+# )
+#
+# energy_charged += ((2 * beta[i] * D[i] - p_0[t]) * T[i] * AB[i, t]) / (
+# 2 * (beta[i] * T[i] + alpha[t])
+# )
+# if smart_charging:
+# funcs["obj"] -= -p_star * peak_charge_penalty
+# if not smart_charging:
+# conval = [0] * BIG_T
+# for t in time_range:
+# conval[t] = alpha[t] + p_0[t]
+# funcs["con"] = conval
+# if smart_charging:
+# # conval = [0] * BIG_T * len(vehicle_range)
+# # for i in vehicle_range:
+# # for t in time_range:
+# # conval[i*BIG_T+t] = y[i,t]-U[i,t]*50
+# # funcs["con1"] = conval
+# # conval = [0] * len(vehicle_range)
+# # for i in vehicle_range:
+# # conval[i] = np.sum(y[i,:]) - ((2 * beta[i] * D[i] - p_0[int(A[i])]) * T[i]) / (2 * (beta[i] * T[i] + alpha[int(A[i])]))
+# # funcs["con2"] = conval
+# conval = [0] * BIG_T
+# for t in time_range:
+# total_charging = 0
+# for i in vehicle_range:
+# total_charging += (
+# ((2 * beta[i] * D[i] - p_0[int(A[i])]) * T[i])
+# * U[i, t]
+# / (2 * (beta[i] * T[i] + alpha[int(A[i])]))
+# ) / T[i]
+# conval[t] = (
+# total_charging
+# + base_load[t]
+# - PV[t]
+# - p_star
+# - Configuration.instance().peak_threshold
+# )
+# funcs["con3"] = conval
+#
+# # conval = [0] * BIG_T
+# # for t in time_range:
+# # total_charging = 0
+# # for i in vehicle_range:
+# # total_charging += (((2 * beta[i] * D[i] - p_0[int(A[i])])
+# # * T[i]) * U[i, t] / (2 * (beta[i] * T[i] + alpha[int(A[i])]))) / T[i]
+# # conval[t] = total_charging + base_load[t] - pv_usage[t]
+# # funcs["con4"] = conval
+# #
+# # conval = [0] * BIG_T
+# # for t in time_range:
+# # conval[t] = PV[t] - pv_usage[t]
+# # funcs["con5"] = conval
+# fail = False
+# if smart_charging:
+# print(energy_charged, funcs["obj"], p_star)
+#
+# return funcs, fail
+#
+# # rst begin optProb
+# # Optimization Object
+# optProb = Optimization("TP037 Constraint Problem", objfunc)
+#
+# # rst begin addVar
+# # Design Variables
+# optProb.addVarGroup(
+# "alpha",
+# BIG_T,
+# "c",
+# lower=np.zeros(BIG_T),
+# upper=np.zeros(BIG_T) + 0.5,
+# value=0.2,
+# )
+# if Configuration.instance().dynamic_fix_term_pricing:
+# optProb.addVarGroup(
+# "p_0",
+# BIG_T,
+# "c",
+# lower=np.zeros(BIG_T),
+# upper=np.zeros(BIG_T) + 1,
+# value=0.3,
+# )
+# if smart_charging:
+# # optProb.addVarGroup("y", BIG_T*len(vehicles_list), "c", lower=np.zeros(BIG_T*len(vehicles_list)),
+# # upper=np.zeros(BIG_T*len(vehicles_list)) + 50, value=1)
+# optProb.addVar(name="p_star", varType="c", lower=0, upper=1200, value=20)
+# # optProb.addVarGroup("pv_usage", BIG_T, "c", lower=np.zeros(BIG_T), upper=np.zeros(BIG_T) + 1000, value=0)
+#
+# # rst begin addCon
+# # Constraints
+# if not smart_charging:
+# optProb.addConGroup("con", BIG_T, lower=0)
+# if smart_charging:
+# # optProb.addConGroup("con1", BIG_T*len(vehicles_list), upper=0)
+# # optProb.addConGroup("con2", len(vehicles_list), lower=0)
+# optProb.addConGroup("con3", BIG_T, upper=0)
+# # optProb.addConGroup("con4", BIG_T, lower=0)
+# # optProb.addConGroup("con5", BIG_T, lower=0)
+#
+# # rst begin addObj
+# # Objective
+# optProb.addObj("obj")
+#
+# # rst begin print
+# # Check optimization problem
+# # print(optProb)
+#
+# # rst begin OPT
+# # Optimizer
+# optOptions = {"IPRINT": -1}
+# opt = SLSQP(options=optOptions)
+#
+# # rst begin solve
+# # Solve
+# sol = opt(optProb, sens="FD")
+#
+# # rst begin check
+# # Check Solution
+# print(sol.objectives["obj"])
+# # print(sol)
+# return sol.xStar
- # rst begin solve
- # Solve
- sol = opt(optProb, sens="FD")
- # rst begin check
- # Check Solution
- print(sol.objectives["obj"])
- # print(sol)
- return sol.xStar
-# print(ev_decision_making())
-# import numpy as np
-# from scipy.optimize import minimize, rosen
-# def rosen_func(x):
-# return sum(100*(x[1:] - x[:-1]**2)**2 + (1-x[:-1])**(-1))
-# x0 = np.array([1.3,0.7, 0.8, 1.9, 1.2])
-# res = minimize(rosen, x0, method='SLSQP', options={'xatol':1e-8, 'disp': True,'full_output': True,})
-# print(res)
diff --git a/Operations/operator.py b/Operations/operator.py
index 0935035..e8b53fc 100644
--- a/Operations/operator.py
+++ b/Operations/operator.py
@@ -330,61 +330,57 @@ def get_charging_schedules_and_prices(self, charging_strategy, mode):
"""
first_scheduling = False
while True:
- if charging_strategy == "perfect_info":
- if first_scheduling == False:
+ if charging_strategy in ["perfect_info", "perfect_info_with_storage"]:
+ def schedule_charging(strategy):
self.get_exp_free_grid_capacity()
- connected_vehicles = [
- x for x in self.requests if x.mode is None and x.ev == 1
- ]
- integrate_algos.perfect_info_charging_routing(
- vehicles=connected_vehicles,
- charging_stations=self.chargers,
- env=self.env,
- grid_capacity=self.free_grid_capa_actual,
- electricity_cost=self.electricity_tariff,
- baseload=self.base_load_list,
- sim_time=self.sim_time,
- generation=self.generation_list,
- )
+ connected_vehicles = [x for x in self.requests if x.mode is None and x.ev == 1]
+
+ if strategy == "perfect_info":
+ integrate_algos.perfect_info_charging_routing(
+ vehicles=connected_vehicles,
+ charging_stations=self.chargers,
+ env=self.env,
+ grid_capacity=self.free_grid_capa_actual,
+ electricity_cost=self.electricity_tariff,
+ baseload=self.base_load_list,
+ sim_time=self.sim_time,
+ generation=self.generation_list,
+ )
+ elif strategy == "perfect_info_with_storage" and connected_vehicles:
+ integrate_algos.perfect_info_charging_routing_storage(
+ vehicles=connected_vehicles,
+ charging_stations=self.chargers,
+ env=self.env,
+ grid_capacity=self.free_grid_capa_actual,
+ electricity_cost=self.electricity_tariff,
+ sim_time=self.sim_time,
+ storage=self.electric_storage,
+ baseload=self.baseload_list,
+ )
+
+ if not first_scheduling:
+ schedule_charging(charging_strategy)
first_scheduling = True
- hour = int((self.env.now) / 60)
+
+ hour = int((self.env.now % 1440) / 60) if charging_strategy == "perfect_info_with_storage" else int(
+ self.env.now / 60)
+
for request in self.requests:
if request.ev == 1:
request.charging_power = request.charge_schedule[hour]
- if charging_strategy == "perfect_info_with_storage":
- if first_scheduling == False:
- self.get_exp_free_grid_capacity()
- connected_vehicles = [
- x for x in self.requests if x.mode is None and x.ev == 1
- ]
- if len(connected_vehicles) > 0:
- integrate_algos.perfect_info_charging_routing_storage(
- vehicles=connected_vehicles,
- charging_stations=self.chargers,
- env=self.env,
- grid_capacity=self.free_grid_capa_actual,
- electricity_cost=self.electricity_tariff,
- sim_time=self.sim_time,
- storage=self.electric_storage,
- baseload=self.baseload_list,
- )
- first_scheduling = True
- hour = int((self.env.now % 1440) / 60)
- for request in self.requests:
- if request.ev == 1:
- request.charging_power = request.charge_schedule[hour]
- if self.storage_object.max_capacity_kWh > 0:
- storage_power = self.electric_storage.charge_schedule[hour]
- if storage_power >= 0:
- self.electric_storage.charge_yn = 1
- self.electric_storage.discharge_yn = 0
- self.electric_storage.discharging_power = 0
- self.electric_storage.charging_power = storage_power
- else:
- self.electric_storage.charge_yn = 0
- self.electric_storage.discharge_yn = 1
- self.electric_storage.discharging_power = storage_power
- self.electric_storage.charging_power = 0
+
+ if charging_strategy == "perfect_info_with_storage" and self.storage_object.max_capacity_kWh > 0:
+ storage_power = self.electric_storage.charge_schedule[hour]
+ if storage_power >= 0:
+ self.electric_storage.charge_yn = 1
+ self.electric_storage.discharge_yn = 0
+ self.electric_storage.discharging_power = 0
+ self.electric_storage.charging_power = storage_power
+ else:
+ self.electric_storage.charge_yn = 0
+ self.electric_storage.discharge_yn = 1
+ self.electric_storage.discharging_power = storage_power
+ self.electric_storage.charging_power = 0
if self.charging_hub.dynamic_pricing:
self.get_exp_free_grid_capacity()
@@ -418,10 +414,6 @@ def get_charging_schedules_and_prices(self, charging_strategy, mode):
/ max(self.electricity_tariff)
* Configuration.instance().max_price_ToU
)
- # print(self.pricing_parameters[0])
- # for i in range(len(self.price_pairs[:,1])):
- # self.price_pairs[i,1] = Configuration.instance().prices[i]
- # self.pricing_parameters[1] = 0.002 + ((23 - hour) / 600)
if self.pricing_mode == "perfect_info":
if Configuration.instance().dynamic_fix_term_pricing:
self.pricing_parameters[1] = self.price_schedules[1][hour]
@@ -445,11 +437,6 @@ def get_charging_schedules_and_prices(self, charging_strategy, mode):
]
)
- # if len([x for x in self.requests if
- # x.mode == 'Connected']) > 0: # only execute if there are connected vehicles
-
- # Charging algos that DO NOT require foresight
-
if charging_strategy == "uncontrolled":
connected_vehicles = [x for x in self.requests if x.mode == "Connected"]
charge_algos.uncontrolled(
diff --git a/Preferences/EV_user_decision_making.py b/Preferences/EV_user_decision_making.py
index 1866c00..b98b770 100644
--- a/Preferences/EV_user_decision_making.py
+++ b/Preferences/EV_user_decision_making.py
@@ -1,63 +1,116 @@
# First party modules
-from pyoptsparse import SLSQP, Optimization
+# from pyoptsparse import SLSQP, Optimization
from Environment.helper.configuration.configuration import Configuration
power_degree = Configuration.instance().degree_of_power_in_price_function
+from scipy.optimize import minimize
+import numpy as np
+
def ev_decision_making(
- p_0=0.2, alpha=0.1, p_p=1 / 60, max_power=50, beta_0=0.6, beta_1=0.2, D=10, T=300
+ p_0=0.2, alpha=0.1, p_p=1 / 60, max_power=50,
+ beta_0=0.6, beta_1=0.2, D=10, T=300, power_degree=1
):
- # rst begin objfunc
- def objfunc(xdict):
- x = xdict["xvars"]
- funcs = {}
-
- funcs["obj"] = (
- x[0] * (p_0 + alpha * (x[0] / x[1] * 60) ** power_degree)
- + p_p * x[1]
- + beta_0 * (D - x[0]) ** 2
- + beta_1 * ((T - x[1]) / 60) ** 2
- )
- conval = [0] * 1
- conval[0] = x[0] / x[1] * 60
- funcs["con"] = conval
- fail = False
+ """
+ Solve the EV decision-making optimization using scipy.optimize.minimize.
+ """
- return funcs, fail
+ # Objective function
+ def objective(x):
+ energy = x[0] # x[0] = total energy charged
+ duration = x[1] # x[1] = charging duration in minutes
+ power = energy / duration * 60 # convert to kW
+
+ return (
+ energy * (p_0 + alpha * (power ** power_degree)) +
+ p_p * duration +
+ beta_0 * (D - energy) ** 2 +
+ beta_1 * ((T - duration) / 60) ** 2
+ )
- # rst begin optProb
- # Optimization Object
- optProb = Optimization("TP037 Constraint Problem", objfunc)
+ # Constraint: average charging power <= max_power
+ def power_constraint(x):
+ energy = x[0]
+ duration = x[1]
+ return max_power - (energy / duration * 60)
- # rst begin addVar
- # Design Variables
- optProb.addVarGroup("xvars", 2, "c", lower=[0, 15], upper=[D, T], value=1)
+ # Initial guess (can be improved)
+ x0 = [1, 15]
- # rst begin addCon
- # Constraints
- optProb.addConGroup("con", 1, lower=0, upper=max_power)
+ # Bounds: energy between 0 and D, duration between 15 and T
+ bounds = [(0, D), (15, T)]
- # rst begin addObj
- # Objective
- optProb.addObj("obj")
+ # Constraint dictionary for SLSQP
+ constraints = [
+ {'type': 'ineq', 'fun': power_constraint} # <= max_power
+ ]
- # rst begin print
- # Check optimization problem
- # print(optProb)
+ # Solve the optimization problem
+ result = minimize(objective, x0, bounds=bounds, constraints=constraints, method='SLSQP')
- # rst begin OPT
- # Optimizer
- optOptions = {"IPRINT": -1}
- opt = SLSQP(options=optOptions)
+ if result.success:
+ print("Optimal solution found:", result.x)
+ else:
+ print("Optimization failed:", result.message)
- # rst begin solve
- # Solve
- sol = opt(optProb, sens="FD")
+ return result.x
- # rst begin check
- # Check Solution
- # print(sol)
+# For this model you need to install pyoptsparse
- return sol.xStar
+# def ev_decision_making(
+# p_0=0.2, alpha=0.1, p_p=1 / 60, max_power=50, beta_0=0.6, beta_1=0.2, D=10, T=300
+# ):
+# # rst begin objfunc
+# def objfunc(xdict):
+# x = xdict["xvars"]
+# funcs = {}
+#
+# funcs["obj"] = (
+# x[0] * (p_0 + alpha * (x[0] / x[1] * 60) ** power_degree)
+# + p_p * x[1]
+# + beta_0 * (D - x[0]) ** 2
+# + beta_1 * ((T - x[1]) / 60) ** 2
+# )
+# conval = [0] * 1
+# conval[0] = x[0] / x[1] * 60
+# funcs["con"] = conval
+# fail = False
+#
+# return funcs, fail
+#
+# # rst begin optProb
+# # Optimization Object
+# optProb = Optimization("TP037 Constraint Problem", objfunc)
+#
+# # rst begin addVar
+# # Design Variables
+# optProb.addVarGroup("xvars", 2, "c", lower=[0, 15], upper=[D, T], value=1)
+#
+# # rst begin addCon
+# # Constraints
+# optProb.addConGroup("con", 1, lower=0, upper=max_power)
+#
+# # rst begin addObj
+# # Objective
+# optProb.addObj("obj")
+#
+# # rst begin print
+# # Check optimization problem
+# # print(optProb)
+#
+# # rst begin OPT
+# # Optimizer
+# optOptions = {"IPRINT": -1}
+# opt = SLSQP(options=optOptions)
+#
+# # rst begin solve
+# # Solve
+# sol = opt(optProb, sens="FD")
+#
+# # rst begin check
+# # Check Solution
+# # print(sol)
+#
+# return sol.xStar
\ No newline at end of file
diff --git a/Utilities/sim_input_processing.py b/Utilities/sim_input_processing.py
index ad5243f..a6260b2 100644
--- a/Utilities/sim_input_processing.py
+++ b/Utilities/sim_input_processing.py
@@ -405,7 +405,7 @@ def get_sim_charging_requests(
parking_charging_preferences.reset_index(inplace=True, drop=True)
lg.warning(
- f"Simulation will be run for the following days: {parking_charging_preferences["EntryDate"].unique()}"
+ f"Simulation will be run for the following days: {parking_charging_preferences['EntryDate'].unique()}"
, extra={"clazz": "", "oid": ""}
)
diff --git a/poetry.lock b/poetry.lock
deleted file mode 100644
index 0151110..0000000
--- a/poetry.lock
+++ /dev/null
@@ -1,178 +0,0 @@
-# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand.
-
-[[package]]
-name = "black"
-version = "25.1.0"
-description = "The uncompromising code formatter."
-optional = false
-python-versions = ">=3.9"
-files = [
- {file = "black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32"},
- {file = "black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da"},
- {file = "black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7"},
- {file = "black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9"},
- {file = "black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0"},
- {file = "black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299"},
- {file = "black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096"},
- {file = "black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2"},
- {file = "black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b"},
- {file = "black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc"},
- {file = "black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f"},
- {file = "black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba"},
- {file = "black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f"},
- {file = "black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3"},
- {file = "black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171"},
- {file = "black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18"},
- {file = "black-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0"},
- {file = "black-25.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f"},
- {file = "black-25.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e"},
- {file = "black-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355"},
- {file = "black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717"},
- {file = "black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666"},
-]
-
-[package.dependencies]
-click = ">=8.0.0"
-mypy-extensions = ">=0.4.3"
-packaging = ">=22.0"
-pathspec = ">=0.9.0"
-platformdirs = ">=2"
-tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
-typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""}
-
-[package.extras]
-colorama = ["colorama (>=0.4.3)"]
-d = ["aiohttp (>=3.10)"]
-jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
-uvloop = ["uvloop (>=0.15.2)"]
-
-[[package]]
-name = "click"
-version = "8.1.8"
-description = "Composable command line interface toolkit"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"},
- {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"},
-]
-
-[package.dependencies]
-colorama = {version = "*", markers = "platform_system == \"Windows\""}
-
-[[package]]
-name = "colorama"
-version = "0.4.6"
-description = "Cross-platform colored terminal text."
-optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
-files = [
- {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
- {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
-]
-
-[[package]]
-name = "mypy-extensions"
-version = "1.0.0"
-description = "Type system extensions for programs checked with the mypy type checker."
-optional = false
-python-versions = ">=3.5"
-files = [
- {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
- {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
-]
-
-[[package]]
-name = "packaging"
-version = "24.2"
-description = "Core utilities for Python packages"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"},
- {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"},
-]
-
-[[package]]
-name = "pathspec"
-version = "0.12.1"
-description = "Utility library for gitignore style pattern matching of file paths."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
- {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
-]
-
-[[package]]
-name = "platformdirs"
-version = "4.3.6"
-description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"},
- {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"},
-]
-
-[package.extras]
-docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"]
-test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"]
-type = ["mypy (>=1.11.2)"]
-
-[[package]]
-name = "tomli"
-version = "2.2.1"
-description = "A lil' TOML parser"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"},
- {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"},
- {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"},
- {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"},
- {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"},
- {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"},
- {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"},
- {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"},
- {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"},
- {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"},
- {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"},
- {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"},
- {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"},
- {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"},
- {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"},
- {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"},
- {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"},
- {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"},
- {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"},
- {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"},
- {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"},
- {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"},
- {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"},
- {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"},
- {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"},
- {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"},
- {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"},
- {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"},
- {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"},
- {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"},
- {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"},
- {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"},
-]
-
-[[package]]
-name = "typing-extensions"
-version = "4.12.2"
-description = "Backported and Experimental Type Hints for Python 3.8+"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
- {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
-]
-
-[metadata]
-lock-version = "2.0"
-python-versions = "^3.9"
-content-hash = "3701634a6006e2a3475df449f118c31bb178b550bcafd351e3cda3093351071b"
diff --git a/pyproject.toml b/pyproject.toml
deleted file mode 100644
index 0e8f40a..0000000
--- a/pyproject.toml
+++ /dev/null
@@ -1,17 +0,0 @@
-[tool.poetry]
-name = "evch-om"
-version = "0.1.0"
-description = ""
-authors = ["raminahadi "]
-readme = "README.md"
-
-[tool.poetry.dependencies]
-python = "^3.9"
-
-
-[tool.poetry.group.dev.dependencies]
-black = "^25.1.0"
-
-[build-system]
-requires = ["poetry-core"]
-build-backend = "poetry.core.masonry.api"
diff --git a/requirements.uv.txt b/requirements.uv.txt
new file mode 100644
index 0000000..50917b3
--- /dev/null
+++ b/requirements.uv.txt
@@ -0,0 +1,37 @@
+cloudpickle==3.1.1
+contourpy==1.3.0
+cycler==0.12.1
+docplex==2.29.241
+filelock==3.18.0
+fonttools==4.57.0
+fsspec==2025.3.2
+gym==0.26.2
+gym-notices==0.0.8
+importlib-metadata==8.6.1
+importlib-resources==6.5.2
+jinja2==3.1.6
+joblib==1.4.2
+kiwisolver==1.4.7
+markupsafe==3.0.2
+matplotlib==3.9.4
+mpmath==1.3.0
+networkx==3.2.1
+nn-builder==0.0.12
+numpy==1.26.4
+packaging==24.2
+pandas==2.2.3
+pillow==11.2.1
+pyparsing==3.2.3
+python-dateutil==2.9.0.post0
+pytz==2025.2
+scikit-learn==1.6.1
+scipy==1.13.1
+seaborn==0.13.2
+simpy==4.1.1
+six==1.17.0
+sympy==1.13.3
+threadpoolctl==3.6.0
+torch==2.2.2
+typing-extensions==4.13.2
+tzdata==2025.2
+zipp==3.21.0