-
Notifications
You must be signed in to change notification settings - Fork 927
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reimplementation of Continuous Space #2584
Changes from 83 commits
2e47f56
6ef0b13
a8bd211
797e681
2782736
d0b05ec
611af52
85c0bc2
2e31c49
322a50e
aee0ff8
1e15913
85665c5
cdbeb2a
04f66f9
a2d113e
76f3ccd
d8b62b0
c5ad8bb
5695c3b
3a985d8
94963cd
acd0ef0
5b676d0
c8119ed
b7c3914
a08e29b
238d105
07e5da4
1b5b082
c46c890
357bc75
cc4a095
f549eee
4b3bb91
8f04312
416455a
daa9b47
137162b
5ce3d55
96fc316
d6326fd
8d57c62
afe44c3
b7bdd82
0db0a6f
625069c
b56a970
eb5abd6
3e8e535
53ffa30
99bb9de
a1cb4cb
f7bdb8b
e2ae60e
45d5744
cf94c46
c5a53c6
a64ac38
595cef4
6303863
2b8ed2b
4e9a39b
102492a
037bc3b
3a4fa51
06a8c34
73b8777
4f3073b
a23b982
b625e23
ce0c311
21c01ad
c7df9be
c0782ab
6677e03
6f0a46a
36bf20a
7780b3a
c2aa0f2
528aab5
e98eadf
983fbb9
c4de8de
23159bf
0706667
0cbbbb5
4187786
1b8937f
897d62e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,10 +6,10 @@ | |
|
||
import numpy as np | ||
|
||
from mesa import Agent | ||
from mesa.experimental.continuous_space import ContinuousSpaceAgent | ||
|
||
|
||
class Boid(Agent): | ||
class Boid(ContinuousSpaceAgent): | ||
"""A Boid-style flocker agent. | ||
|
||
The agent follows three behaviors to flock: | ||
|
@@ -26,10 +26,12 @@ class Boid(Agent): | |
def __init__( | ||
self, | ||
model, | ||
speed, | ||
direction, | ||
vision, | ||
separation, | ||
space, | ||
position=(0, 0), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wasn't this supposed to be a sequence/array with (like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. position in newstyle is np.typing.ArrayLike, so anything castable to np.array works. The cleaner solution is to make position a positional argument rather than a keyword argument because this avoids the need for a default value. The nice thing of a kwarg, however, is that |
||
speed=1, | ||
direction=(1, 1), | ||
vision=1, | ||
separation=1, | ||
cohere=0.03, | ||
separate=0.015, | ||
match=0.05, | ||
|
@@ -46,7 +48,8 @@ def __init__( | |
separate: Relative importance of avoiding close neighbors (default: 0.015) | ||
match: Relative importance of matching neighbors' directions (default: 0.05) | ||
""" | ||
super().__init__(model) | ||
super().__init__(space, model) | ||
self.position = position | ||
self.speed = speed | ||
self.direction = direction | ||
self.vision = vision | ||
|
@@ -58,47 +61,31 @@ def __init__( | |
|
||
def step(self): | ||
"""Get the Boid's neighbors, compute the new vector, and move accordingly.""" | ||
neighbors = self.model.space.get_neighbors(self.pos, self.vision, True) | ||
neighbors, distances = self.get_neighbors_in_radius(radius=self.vision) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is very clean! |
||
self.neighbors = [n for n in neighbors if n is not self] | ||
|
||
# If no neighbors, maintain current direction | ||
if not self.neighbors: | ||
new_pos = self.pos + self.direction * self.speed | ||
self.model.space.move_agent(self, new_pos) | ||
if not neighbors: | ||
self.position += self.direction * self.speed | ||
return | ||
|
||
# Initialize vectors for the three flocking behaviors | ||
cohere = np.zeros(2) # Cohesion vector | ||
match_vector = np.zeros(2) # Alignment vector | ||
separation_vector = np.zeros(2) # Separation vector | ||
delta = self.space.calculate_difference_vector(self.position, agents=neighbors) | ||
|
||
# Calculate the contribution of each neighbor to the three behaviors | ||
for neighbor in self.neighbors: | ||
heading = self.model.space.get_heading(self.pos, neighbor.pos) | ||
distance = self.model.space.get_distance(self.pos, neighbor.pos) | ||
|
||
# Cohesion - steer towards the average position of neighbors | ||
cohere += heading | ||
|
||
# Separation - avoid getting too close | ||
if distance < self.separation: | ||
separation_vector -= heading | ||
|
||
# Alignment - match neighbors' flying direction | ||
match_vector += neighbor.direction | ||
|
||
# Weight each behavior by its factor and normalize by number of neighbors | ||
n = len(self.neighbors) | ||
cohere = cohere * self.cohere_factor | ||
separation_vector = separation_vector * self.separate_factor | ||
match_vector = match_vector * self.match_factor | ||
cohere_vector = delta.sum(axis=0) * self.cohere_factor | ||
separation_vector = ( | ||
-1 * delta[distances < self.separation].sum(axis=0) * self.separate_factor | ||
) | ||
match_vector = ( | ||
np.asarray([n.direction for n in neighbors]).sum(axis=0) * self.match_factor | ||
) | ||
|
||
# Update direction based on the three behaviors | ||
self.direction += (cohere + separation_vector + match_vector) / n | ||
self.direction += (cohere_vector + separation_vector + match_vector) / len( | ||
neighbors | ||
) | ||
|
||
# Normalize direction vector | ||
self.direction /= np.linalg.norm(self.direction) | ||
|
||
# Move boid | ||
new_pos = self.pos + self.direction * self.speed | ||
self.model.space.move_agent(self, new_pos) | ||
self.position += self.direction * self.speed |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
"""Continuous space support.""" | ||
|
||
from mesa.experimental.continuous_space.continuous_space import ContinuousSpace | ||
from mesa.experimental.continuous_space.continuous_space_agents import ( | ||
ContinuousSpaceAgent, | ||
) | ||
|
||
__all__ = ["ContinuousSpace", "ContinuousSpaceAgent"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's you long term vision on the different Agent types in Mesa? Will each space need their own Agent class?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see a viable alternative at the moment other than having a set of different agent subclasses designed to work with different spaces.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I am understanding correctly, related #2585 (which is an awesome discussion BTW) then if a user has say someone in continouspace and part of network, then their agent would use inheritance to get those particular functions?