mesa
mesa copied to clipboard
Voronoi Tesselation based Discrete Space
First version of Voronoi Tesselation based Discrete Space,
described on issue #1895 . This feature allows the user to build a discrete space based on a random sample of points, where neighbors are defined by Delaunay Triangulation.
More specifically, Delaunay Triangulation is a dual-graph representation of the Voronoi Tesselation. Using this algorithm, we can easily find nearest neighbors without delimiting cells edges.
The library chosen for the triangulation algorithm implementation was PyHull, a wrapper of qhull C library, which deals with spatial calculations. The choice was made considering performance, size and usability (SciPy has a similar module but much heavier).
Based on my discussion with @EwoutH on the issue thread, i thought it would be useful to inherit DiscreteSpace class.
class VoronoiGrid(DiscreteSpace):
Example
from mesa import Model
from mesa.experimental.cell_space import VoronoiGrid, CellAgent
class MyAgent(CellAgent):
def __init__(self, unique_id, model):
super().__init__(unique_id, model)
Users can input cells centroids
points = [
[0, 0], [0, 1], [0, 2],
[1, 0], [1, 1], [1, 2],
[2, 0], [2, 1], [2, 2]]
grid = VoronoiGrid(centroids_coordinates=points, capacity=1, random=model.random)
and cells neighborhoods are defined by Delaunay triangulation
agent = MyAgent(1, model)
cell = grid.select_random_empty_cell()
agent.move_to(cell)
print(cell)
print(cell.neighborhood())
Cell([1, 0], [<__main__.MyAgent object at 0x7f2177268450>])
CellCollection({Cell([0, 1], []): [], Cell([1, 1], []): [], Cell([0, 0], []): [], Cell([2, 1], []): [], Cell([2, 0], []): []})
Next Steps
Definitely, next steps involve computing the boundaries of each cell using Voronoi Tesselation. This allow us to define capacity of each cell based on its area/volume.
Thanks, it's a great start! Using DelaunayTri is a smart approach.
I guess move_to
currently move an agent to the cells centroid? While that is logical behavior, I would also like to see an method in which agents are moved to A) the closest point in the cell from their current position and B) a random spot in the cell. This could be a separate PR.
Another thing that it's needed in the long term is a method to check in which cell a point (and thus an agent) is.
@wang-boyu I would also appreciate a review from your mesa-geo expertise.
For the currently functionality, I would like some additional docstring and unittests. Then you can decide if you want to add further functionality to this PR, or merge this first and follow up with new PRs.
Edit: One thought, also for the other maintainers: Would we need separate Discrete and Continuous Voronoi spaces?
Thanks for the PR. I have to say that I'm still a bit confused about why this is based on discrete space, not continuous space (as I mentioned in https://github.com/projectmesa/mesa/issues/1895#issuecomment-2016514829 and https://github.com/projectmesa/mesa/issues/1895#issuecomment-2016521840).
As a concrete example, consider this simple space:
Cell 1 | Cell 2 | Cell 3 |
---|---|---|
O | ? | X |
If it is a Voronoi space, should Cell 2 be split into halves, where left half belongs to agent of type O and right half belongs to agent of type X? How does this work in discrete space?
Apologies, a little late to this discussion, this is really cool @vitorfrois.
As dependencies and keeping Mesa lightweight is a constant struggle, but form a very superficial look is there a reason we wont use networkx (https://networkx.org/documentation/stable/reference/algorithms/voronoi.html) and this has a corresponding example that may work for mesa_geo (https://networkx.org/documentation/stable/auto_examples/geospatial/plot_delaunay.html)?
Let me know what you think/ what I am missing?
@wang-boyu
I have to say that I'm still a bit confused about why this is based on discrete space, not continuous space. How does this work in discrete space?
I'm considering the discrete space for Voronoi Tesselation as a static/non changing graph, where neighbors are obtained by Delaunay Triangulation. As @EwoutH said, it is only a special case for HexGrid where cell are not equally spaced.
I think its more about a choice of implementation where I considered mainly the Cholera example. As I suggested yesterday,
since the result of Delaunay Triangulation is a graph, we can use NetworkGrid to represent it, and in the continuous case, implement in the Mesa Geo using Shapely.
Does that make sense?
@tpike3 thanks for the comment. That's more or less what I'm thinking. In Mesa Geo, we have opportunity to do it better with Shapely
I'm considering the discrete space for Voronoi Tesselation as a static/non changing graph, where neighbors are obtained by Delaunay Triangulation.
Thanks for clarifying. Appreciate it.
Question: Is the Delaunay Triangulation done in continuous space?
Question: Is the Delaunay Triangulation done in continuous space?
Yes, it is
Updates
- Implemented Voronoi from scratch (basically copied a simple already implemented algorithm)
- Now using the regions resulting from Delaunay/Voronoi Triangulation to draw Voronoi cells in JupyterViz. As the cell is an important in voronoi diagram, I added an attribute
cell_coloring_property
toVoronoiGrid
. When drawing the grid, the polygon is drawn withplt.fill(polygon, alpha=cell.properties[space.cell_coloring_property])
, so one can tweak the cell coloring property to adjust the visualization. In the example, the cell coloring property is cases ratio, which give darker shades on cells with more cases. - Altough, could not cover
visualization/components/matplotlib.py
with tests :( - It was simpler and more visual to directly implement Voronoi cells since they were computed anyway, instead of the visualization using NetworkX, mentioned earlier. It is not that performant though
This gives us the example above
Omg, sorry I did not notice the license. I copied like 70% of it's implementation, changing variables, function names and other minor things.
On Sun, Jul 21, 2024, 08:44 rht @.***> wrote:
@.**** commented on this pull request.
In mesa/experimental/cell_space/voronoi.py https://github.com/projectmesa/mesa/pull/2084#discussion_r1685719329:
@@ -0,0 +1,264 @@ +from collections.abc import Sequence +from itertools import combinations +from random import Random
+import numpy as np + +from mesa.experimental.cell_space.cell import Cell +from mesa.experimental.cell_space.discrete_space import DiscreteSpace + + +class Delaunay:
- """
- Class to compute a Delaunay triangulation in 2D
- ref: http://github.com/jmespadero/pyDelaunay2D
How much percentage of the code is based on this GitHub repo? Their license is GPLv3, and we actually can't copy their code because there will be a licensing issue.
— Reply to this email directly, view it on GitHub https://github.com/projectmesa/mesa/pull/2084#pullrequestreview-2190309373, or unsubscribe https://github.com/notifications/unsubscribe-auth/ALBWUBC63DYQCEJC5TPSGOLZNONJHAVCNFSM6AAAAABFAPRYMCVHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMZDCOJQGMYDSMZXGM . You are receiving this because you were mentioned.Message ID: @.***>
There are 2 ways to proceed:
- Use ChatGPT to do code laundry, i.e. ask it to do Delaunay triangulation code. It probably is going to be based on that GPLv3 repo, but you can blame ClosedAI for that instead.
- Use SciPy, but have SciPy to be an optional dependency, only imported when the user needs
VoronoiGrid
I'm more in favor of option 2, because option 1 is rather shady.
Yeah the license issue is a big one. Another (far fetched) option is to contact the maintainer to see if he’s willing to publish on another, more permissive license.
@vitorfrois I would like to try to contact the maintainers. Do you want to write them a message or would you like me to do it?
I can do it tomorrow, then hopefully we can move this forward next week!
I would like to include it in the next 3.0 alpha release.
I reached out Tuesday, hopefully we will get an answer soon: https://github.com/jmespadero/pyDelaunay2D/issues/7
Merged! Congratulations @vitorfrois your first PR is in Mesa - and it's a remarkable one.
Thanks for your effort and patience.
It will be included in the Mesa 3.0.0a3
release later today.