Boids
¶
Installation¶
You will need Python 3.12 or later, and a working JAX installation. For example, you can install JAX with:
In [1]:
Copied!
%pip install -U "jax[cuda]"
%pip install -U "jax[cuda]"
/home/faldor_google_com/dev/cax/.venv/bin/python3: No module named pip
Note: you may need to restart the kernel to use updated packages.
Then, install CAX from PyPi:
In [2]:
Copied!
%pip install -U "cax[examples]"
%pip install -U "cax[examples]"
/home/faldor_google_com/dev/cax/.venv/bin/python3: No module named pip
Note: you may need to restart the kernel to use updated packages.
Import¶
In [3]:
Copied!
import jax
import jax.numpy as jnp
import mediapy
from flax import nnx
from cax.cs.boids import Boids, BoidsPolicy, BoidsState
from cax.utils import render_states
import jax
import jax.numpy as jnp
import mediapy
from flax import nnx
from cax.cs.boids import Boids, BoidsPolicy, BoidsState
from cax.utils import render_states
Configuration¶
In [4]:
Copied!
seed = 0
num_steps = 1024
num_spatial_dims = 2
num_boids = 256
dt = 0.01
acceleration_max = jnp.inf
acceleration_scale = 1.0
perception_radius = 0.1
separation_distance = 0.025
separation_weight = 4.5
alignment_weight = 0.65
cohesion_weight = 0.75
noise_scale = 0.1
key = jax.random.key(seed)
rngs = nnx.Rngs(seed)
seed = 0
num_steps = 1024
num_spatial_dims = 2
num_boids = 256
dt = 0.01
acceleration_max = jnp.inf
acceleration_scale = 1.0
perception_radius = 0.1
separation_distance = 0.025
separation_weight = 4.5
alignment_weight = 0.65
cohesion_weight = 0.75
noise_scale = 0.1
key = jax.random.key(seed)
rngs = nnx.Rngs(seed)
Instantiate system¶
In [5]:
Copied!
boid_policy = BoidsPolicy(
acceleration_max=acceleration_max,
acceleration_scale=acceleration_scale,
perception_radius=perception_radius,
separation_distance=separation_distance,
separation_weight=separation_weight,
alignment_weight=alignment_weight,
cohesion_weight=cohesion_weight,
noise_scale=noise_scale,
rngs=rngs,
)
cs = Boids(
dt=dt,
velocity_half_life=jnp.inf,
boid_policy=boid_policy,
)
boid_policy = BoidsPolicy(
acceleration_max=acceleration_max,
acceleration_scale=acceleration_scale,
perception_radius=perception_radius,
separation_distance=separation_distance,
separation_weight=separation_weight,
alignment_weight=alignment_weight,
cohesion_weight=cohesion_weight,
noise_scale=noise_scale,
rngs=rngs,
)
cs = Boids(
dt=dt,
velocity_half_life=jnp.inf,
boid_policy=boid_policy,
)
Sample initial state¶
In [6]:
Copied!
def sample_state(key):
"""Sample a state with random positions and velocities."""
key_position, key_velocity = jax.random.split(key)
# Position
position = jax.random.uniform(key_position, (num_boids, num_spatial_dims))
# Velocity
velocity = jax.random.uniform(key_velocity, (num_boids, num_spatial_dims))
return BoidsState(position=position, velocity=velocity)
def sample_state(key):
"""Sample a state with random positions and velocities."""
key_position, key_velocity = jax.random.split(key)
# Position
position = jax.random.uniform(key_position, (num_boids, num_spatial_dims))
# Velocity
velocity = jax.random.uniform(key_velocity, (num_boids, num_spatial_dims))
return BoidsState(position=position, velocity=velocity)
Run¶
In [7]:
Copied!
key, subkey = jax.random.split(key)
state_init = sample_state(subkey)
state_final, states = cs(state_init, num_steps=num_steps, return_states=True)
key, subkey = jax.random.split(key)
state_init = sample_state(subkey)
state_final, states = cs(state_init, num_steps=num_steps, return_states=True)
Visualize¶
In [8]:
Copied!
states = jax.tree.map(lambda x, xs: jnp.concatenate([x[None], xs]), state_init, states)
frames = render_states(cs, states, particle_radius=0.01)
mediapy.show_video(frames, fps=int(1 / dt))
states = jax.tree.map(lambda x, xs: jnp.concatenate([x[None], xs]), state_init, states)
frames = render_states(cs, states, particle_radius=0.01)
mediapy.show_video(frames, fps=int(1 / dt))