Skip to content

Commit

Permalink
created PPData and PPVariable classes
Browse files Browse the repository at this point in the history
  • Loading branch information
pjflux2001 committed Sep 3, 2023
1 parent d342282 commit 85930d2
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 157 deletions.
28 changes: 14 additions & 14 deletions experiments/jupyter/production/kernels.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import taichi as ti
import taichi.math as timath
from polyphy_functions import TypeAliases, StateFlags, SimulationConstants, StateFlags
from polyphy_functions import TypeAliases, PPVariables

@ti.data_oriented
class Kernels:
Expand Down Expand Up @@ -71,30 +71,30 @@ def agent_step(self,sense_distance: TypeAliases.FLOAT_GPU,\
## Generate new mutated angle by perturbing the original
dir_fwd = self.angle_to_dir_2D(angle)
angle_mut = angle
if StateFlags.directional_sampling_distribution == StateFlags.EnumDirectionalSamplingDistribution.DISCRETE:
if PPVariables.directional_sampling_distribution == PPVariables.EnumDirectionalSamplingDistribution.DISCRETE:
angle_mut += (1.0 if ti.random(dtype=TypeAliases.FLOAT_GPU) > 0.5 else -1.0) * sense_angle
elif StateFlags.directional_sampling_distribution == StateFlags.EnumDirectionalSamplingDistribution.CONE:
elif PPVariables.directional_sampling_distribution == PPVariables.EnumDirectionalSamplingDistribution.CONE:
angle_mut += 2.0 * (ti.random(dtype=TypeAliases.FLOAT_GPU) - 0.5) * sense_angle
dir_mut = self.angle_to_dir_2D(angle_mut)

## Generate sensing distance for the agent, constant or probabilistic
agent_sensing_distance = sense_distance
distance_scaling_factor = 1.0
if StateFlags.distance_sampling_distribution == StateFlags.EnumDistanceSamplingDistribution.EXPONENTIAL:
if PPVariables.distance_sampling_distribution == PPVariables.EnumDistanceSamplingDistribution.EXPONENTIAL:
xi = timath.clamp(ti.random(dtype=TypeAliases.FLOAT_GPU), 0.001, 0.999) ## log & pow are unstable in extremes
distance_scaling_factor = -ti.log(xi)
elif StateFlags.distance_sampling_distribution == StateFlags.EnumDistanceSamplingDistribution.MAXWELL_BOLTZMANN:
elif PPVariables.distance_sampling_distribution == PPVariables.EnumDistanceSamplingDistribution.MAXWELL_BOLTZMANN:
xi = timath.clamp(ti.random(dtype=TypeAliases.FLOAT_GPU), 0.001, 0.999) ## log & pow are unstable in extremes
distance_scaling_factor = -0.3033 * ti.log( (ti.pow(xi + 0.005, -0.4) - 0.9974) / 7.326 )
agent_sensing_distance *= distance_scaling_factor

## Fetch deposit to guide the agent
deposit_fwd = 1.0
deposit_mut = 0.0
if StateFlags.deposit_fetching_strategy == StateFlags.EnumDepositFetchingStrategy.NN:
if PPVariables.deposit_fetching_strategy == PPVariables.EnumDepositFetchingStrategy.NN:
deposit_fwd = deposit_field[self.world_to_grid_2D(pos + agent_sensing_distance * dir_fwd, TypeAliases.VEC2f(DOMAIN_MIN), TypeAliases.VEC2f(DOMAIN_MAX), TypeAliases.VEC2i(DEPOSIT_RESOLUTION))][current_deposit_index]
deposit_mut = deposit_field[self.world_to_grid_2D(pos + agent_sensing_distance * dir_mut, TypeAliases.VEC2f(DOMAIN_MIN), TypeAliases.VEC2f(DOMAIN_MAX), TypeAliases.VEC2i(DEPOSIT_RESOLUTION))][current_deposit_index]
elif StateFlags.deposit_fetching_strategy == StateFlags.EnumDepositFetchingStrategy.NN_PERTURBED:
elif PPVariables.deposit_fetching_strategy == PPVariables.EnumDepositFetchingStrategy.NN_PERTURBED:
## Fetches the deposit by perturbing the original position by a small delta
## This provides cheap stochastic filtering instead of multi-fetch filters
field_dd = 2.0 * ti.cast(DOMAIN_SIZE[0], TypeAliases.FLOAT_GPU) / ti.cast(DEPOSIT_RESOLUTION[0], TypeAliases.FLOAT_GPU)
Expand All @@ -105,25 +105,25 @@ def agent_step(self,sense_distance: TypeAliases.FLOAT_GPU,\

## Generate new direction for the agent based on the sampled deposit
angle_new = angle
if StateFlags.directional_mutation_type == StateFlags.EnumDirectionalMutationType.DETERMINISTIC:
angle_new = (SimulationConstants.STEERING_RATE * angle_mut + (1.0-SimulationConstants.STEERING_RATE) * angle) if (deposit_mut > deposit_fwd) else (angle)
elif StateFlags.directional_mutation_type == StateFlags.EnumDirectionalMutationType.PROBABILISTIC:
if PPVariables.directional_mutation_type == PPVariables.EnumDirectionalMutationType.DETERMINISTIC:
angle_new = (STEERING_RATE * angle_mut + (1.0-STEERING_RATE) * angle) if (deposit_mut > deposit_fwd) else (angle)
elif PPVariables.directional_mutation_type == PPVariables.EnumDirectionalMutationType.PROBABILISTIC:
p_remain = ti.pow(deposit_fwd, sampling_exponent)
p_mutate = ti.pow(deposit_mut, sampling_exponent)
mutation_probability = p_mutate / (p_remain + p_mutate)
angle_new = (SimulationConstants.STEERING_RATE * angle_mut + (1.0-SimulationConstants.STEERING_RATE) * angle) if (ti.random(dtype=TypeAliases.FLOAT_GPU) < mutation_probability) else (angle)
angle_new = (STEERING_RATE * angle_mut + (1.0-STEERING_RATE) * angle) if (ti.random(dtype=TypeAliases.FLOAT_GPU) < mutation_probability) else (angle)
dir_new = self.angle_to_dir_2D(angle_new)
pos_new = pos + step_size * distance_scaling_factor * dir_new

## Agent behavior at domain boundaries
if StateFlags.agent_boundary_handling == StateFlags.EnumAgentBoundaryHandling.WRAP:
if PPVariables.agent_boundary_handling == PPVariables.EnumAgentBoundaryHandling.WRAP:
pos_new[0] = self.custom_mod(pos_new[0] - DOMAIN_MIN[0] + DOMAIN_SIZE[0], DOMAIN_SIZE[0]) + DOMAIN_MIN[0]
pos_new[1] = self.custom_mod(pos_new[1] - DOMAIN_MIN[1] + DOMAIN_SIZE[1], DOMAIN_SIZE[1]) + DOMAIN_MIN[1]
elif StateFlags.agent_boundary_handling == StateFlags.EnumAgentBoundaryHandling.REINIT_CENTER:
elif PPVariables.agent_boundary_handling == PPVariables.EnumAgentBoundaryHandling.REINIT_CENTER:
if pos_new[0] <= DOMAIN_MIN[0] or pos_new[0] >= DOMAIN_MAX[0] or pos_new[1] <= DOMAIN_MIN[1] or pos_new[1] >= DOMAIN_MAX[1]:
pos_new[0] = 0.5 * (DOMAIN_MIN[0] + DOMAIN_MAX[0])
pos_new[1] = 0.5 * (DOMAIN_MIN[1] + DOMAIN_MAX[1])
elif StateFlags.agent_boundary_handling == StateFlags.EnumAgentBoundaryHandling.REINIT_RANDOMLY:
elif PPVariables.agent_boundary_handling == PPVariables.EnumAgentBoundaryHandling.REINIT_RANDOMLY:
if pos_new[0] <= DOMAIN_MIN[0] or pos_new[0] >= DOMAIN_MAX[0] or pos_new[1] <= DOMAIN_MIN[1] or pos_new[1] >= DOMAIN_MAX[1]:
pos_new[0] = DOMAIN_MIN[0] + timath.clamp(ti.random(dtype=TypeAliases.FLOAT_GPU), 0.001, 0.999) * DOMAIN_SIZE[0]
pos_new[1] = DOMAIN_MIN[1] + timath.clamp(ti.random(dtype=TypeAliases.FLOAT_GPU), 0.001, 0.999) * DOMAIN_SIZE[1]
Expand Down
12 changes: 6 additions & 6 deletions experiments/jupyter/production/polyphy.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from polyphy_functions import StateFlags, PolyPhyWindow, PostSimulation, SimulationVisuals, DataLoader, FieldVariables, DerivedVariables, Agents, TypeAliases, SimulationConstants
from polyphy_functions import PolyPhyWindow, PostSimulation, SimulationVisuals, FieldVariables, Agents, TypeAliases, PPVariables, PPData
from kernels import Kernels
from numpy.random import default_rng
import taichi as ti
Expand All @@ -8,12 +8,12 @@ def __init__(self):
## Initialize Taichi
ti.init(arch=ti.cpu)
self.rng = default_rng()
self.dataLoaders = DataLoader(self.rng)
self.derivedVariables = DerivedVariables(self.dataLoaders)
self.agents = Agents(self.rng,self.dataLoaders,self.derivedVariables)
self.fieldVariables = FieldVariables(self.dataLoaders,self.derivedVariables)
self.ppData = PPData()
self.ppVariables = PPVariables(self.ppData)
self.agents = Agents(self.rng,self.ppVariables,self.ppData)
self.fieldVariables = FieldVariables(self.ppVariables,self.ppData)
self.k = Kernels()
self.simulationVisuals = SimulationVisuals(self.k,self.dataLoaders,self.derivedVariables,self.agents,self.fieldVariables)
self.simulationVisuals = SimulationVisuals(self.k,self.ppVariables,self.ppData,self.agents,self.fieldVariables)

def start_simulation(self):
PolyPhyWindow(self.k,self.simulationVisuals)
Expand Down
Loading

0 comments on commit 85930d2

Please sign in to comment.