chore: properly developing

This commit is contained in:
2026-01-28 14:04:57 +01:00
parent fa2aca8b13
commit 83d9bb2552
4 changed files with 92 additions and 0 deletions

48
engine/lib/behavior.py Normal file
View File

@@ -0,0 +1,48 @@
from sim.rl.behavior_loader.models import BehaviorModel, AgentBehaviorModel, aggregate_event_transitions
import pandas as pd
import numpy as np
from .demand import generate_demand
base_dir = "/home/velocitatem/Documents/Projects/PHANTOM/experiments"
human_dir, agent_dir = f"{base_dir}/collected_data/", f"{base_dir}/agents/collected_data/"
def adjust_behavior_to_condition(condition, transition_matrix):
# transition matrix just maps probability of eventA to eventB
# we enhance this that eventA-productI to eventB-productJ... based on the condition of interest
# this is to simulate the impact of demand onto the behavior
# NxN -> (N*(P + 1))x(N*(P + 1)) where P is number of products
new_transitions = transition_matrix.copy()
for col in new_transitions.columns:
for product in range(len(condition)):
# adjust the transition probability based on the demand condition
newname = f"{col}_product{product}"
new_transitions[newname] = new_transitions[col] * (condition[product] / np.sum(condition))
for row in transition_matrix.index:
for product in range(len(condition)):
newname = f"{row}_product{product}"
new_transitions.loc[newname] = new_transitions.loc[row] * (condition[product] / np.sum(condition))
return new_transitions.fillna(0.0)
def sample_behavior(condition, human=True, max_len=40):
model = BehaviorModel(human_dir) if human else AgentBehaviorModel(agent_dir)
mdp = model.build_MDP()
raw_events = aggregate_event_transitions(mdp) # this gets us transtition between events (blind to products or prices)
# staet: {state: p} is raw_events we needc a matrix a pivot table
events_pivot = pd.DataFrame(raw_events).fillna(0.0)
# now adjust the transition matrix based on the condition to get a more informed transition matrix
adjusted_transitions = adjust_behavior_to_condition(condition, events_pivot)
trajectory = [np.random.choice(adjusted_transitions.index)]
while len(trajectory) < max_len or 'checkout' in trajectory[-1]:
probs = adjusted_transitions.loc[trajectory[-1]].values
sample = np.random.choice(adjusted_transitions.columns, p=probs/np.sum(probs) if np.sum(probs) > 0 else None)
trajectory.append(sample)
return trajectory
if __name__ == "__main__":
t=sample_behavior(generate_demand(np.array([10,20,30])), human=True)
print(t)
t=sample_behavior(generate_demand(np.array([10,20,30])), human=False)
print(t)

40
engine/lib/demand.py Normal file
View File

@@ -0,0 +1,40 @@
import numpy as np
def generate_demand(prices):
# assumption 1: each product has an intrinsic valuation drawn from a normal distribution centered at 50
product_valuations = np.random.normal(loc=50.0, scale=10.0, size=len(prices))
# assumption 2: demand decreases as price increases, following a simple linear model
demand = np.maximum(0, product_valuations - prices) # demand cannot be negative
demand = demand / np.sum(demand) * 100 # normalize to total demand of 1000 units so demand output is within [0, 100]
return demand
def estimate_demand(trajectories):
demand_estimate = {}
for traj in trajectories:
for event in traj:
if 'view_product' in event:
product_id = int(event.split('_')[-1].replace('product', ''))
demand_estimate[product_id] = demand_estimate.get(product_id, 0) + 1
total_views = sum(demand_estimate.values())
for product_id in demand_estimate:
demand_estimate[product_id] = (demand_estimate[product_id] / total_views) * 100 # normalize to percentage
return demand_estimate
# Example usage
if __name__ == "__main__":
np.random.seed(42)
prices = np.array([20.0, 35.0, 50.0, 65.0])
demand = generate_demand(prices)
print("Generated Demand:", demand)
from .behavior import sample_behavior
N, alphat =200, 0.1
trajectories = []
for _ in range(int(N*(1 - alphat))):
trajectories.append(sample_behavior(demand, human=True))
for _ in range(int(N*alphat)):
trajectories.append(sample_behavior(demand, human=False))
demand_estimate = estimate_demand(trajectories)
print("Estimated Demand from Behavior:", demand_estimate)
delta = {k: demand_estimate.get(k, 0) - demand[i] for i, k in enumerate(range(len(prices)))}
delta = np.mean([np.abs(v) for v in delta.values()])
print("Demand Delta:", delta)

0
engine/main.py Normal file
View File

View File

@@ -226,6 +226,7 @@ if __name__ == "__main__":
agent_model = AgentBehaviorModel(agent_dir) agent_model = AgentBehaviorModel(agent_dir)
agent_mdp = agent_model.build_MDP() agent_mdp = agent_model.build_MDP()
print(agent_mdp)
print(f"AGENT... Built MDP: {agent_mdp['num_states']} states, " print(f"AGENT... Built MDP: {agent_mdp['num_states']} states, "
f"{sum(len(t) for t in agent_mdp['transitions'].values())} transitions") f"{sum(len(t) for t in agent_mdp['transitions'].values())} transitions")
if not agent_mdp['states']: if not agent_mdp['states']:
@@ -234,6 +235,9 @@ if __name__ == "__main__":
human_evt = aggregate_event_transitions(human_mdp) human_evt = aggregate_event_transitions(human_mdp)
agent_evt = aggregate_event_transitions(agent_mdp) agent_evt = aggregate_event_transitions(agent_mdp)
print(agent_evt)
common = set(human_evt.keys()) & set(agent_evt.keys()) common = set(human_evt.keys()) & set(agent_evt.keys())
if not common: if not common: