toruseo / UXsim

Vehicular traffic flow simulator in road network, written in pure Python
https://toruseo.jp/UXsim/docs/
MIT License
130 stars 59 forks source link

Full support for Areas #102

Open EwoutH opened 2 months ago

EwoutH commented 2 months ago

Currently there is initial support for Areas in UXsim, with two methods:

However, I think the concept of Areas (with some nodes in each) is a very interesting construct worth developing further. What I would find useful:

Required capabilities

EwoutH commented 2 months ago

@toruseo just let me know what your thoughts are on this idea, I would probably build it anyway, the question is if you would like this integrated into UXsim.

toruseo commented 2 months ago

I think there are several possible implementations depending on the specific purposes. I am not sure if it should be implemented as a standard function of UXsim.

One of the simplest way would be something like this:

EwoutH commented 2 months ago

I'm trying some things, both inside and outside of UXsim.

Currently, adddemand_area2area requests a centroid coordinates (x, y) and a radius for both the origin and destination. I would like being able to specify this area myself, as a geometry / polygon. I see two options here:

Anyway I think while a circular radius is not unreasonable, it's oddly specific in the adddemand_area2area function, and it would be useful to either make it more flexible or to add other methods that complement it. Then the centerpoint-radius method could be just one way to construct areas.

However, once you have dealt with demand, you want to do some other things like gather statistics, track vehicles, etc. That's why the concept of areas seemed useful to implement more broadly in UXsim for me.

So what I'm leaning towards is an area being a collection of nodes, and adding a helper function for creating/updating that collection of nodes in different ways, including centerpoint-radius method and forming from geospatial areas like in a GeoDataFrame.

So I think we're roughly aligned on an area being a set of nodes. The question is now on how to implement that elegantly and efficiently.

Curious on your thoughts!

EwoutH commented 2 months ago

One other thought: In Mesa we have the concept of an Agent and an AgentSet, which is a collection of Agents. I feel we need something similar here, with an Area and an AreaSet.

The most flexible (and OOP) way might be to make both a class, and than keep some sort of collection/iterable of Areas in the AreaSet.

However, that might be severe overkill and maybe not that performant.

Another thought was to keep Areas in a array like structure, so that operations can be applied vectorized over them. Each row is an Area with certain properties. Then we can perform operations on either the whole area or a specific row.

Each Area would need to keep a list of nodes however, and lists in Arrays are not always nice to work with in my experience.

@quaquel, since we did something similar with the AgentSet and you love data structures, if you have any thoughts on this case, I would appreciate them!

toruseo commented 2 months ago

Thanks for your thoughts. I see, I agree that creating demand based on set of nodes and calculating stats between nodes are useful for general purposes. They can be implemented similar to adddemand_area2area and Analyzer.od_to_pandas.

I will design these functions with list-like arguments to receive "set of nodes", as I think it is the simplest and most general way. I believe other data formats can be easily transformed to list. If you know simpler and elegant approach, let me know!

Also calculating stats of a particular set of vehicles would be useful. I will try too.

EwoutH commented 2 months ago

Thanks! I'm happy to work on this, so let me know if you would like me to do any part or want any help on any part. Also feel free to open a (draft) PR early, so we can follow development and you can get early feedback.

EwoutH commented 2 months ago

@toruseo do you think you will be able to give this a shot relatively soon? Otherwise I would like to try drafting an implementation.

toruseo commented 2 months ago

I have implemented World.adddemand_nodes2nodes, World.areas2areas_to_pandas, etc. An "area" is defined as a list of nodes, and these functions take a list of "area" as their arguments.

For the use cases, plz see https://github.com/toruseo/UXsim/blob/1df485a23e58e4a4baf3d7d301f01f1a2b3775ed/tests/test_other_functions.py#L459-L513

Any operations for areas such as https://github.com/toruseo/UXsim/pull/106 's get_random_node_in_area() or any other GIS-related operations can be defined to the list. I think this allows flexible and general operations.

toruseo commented 2 months ago

@EwoutH BTW, Node, Link, and Vehicle have attribute parameter whose value can be set by addNode(..., attribute=42) etc. These parameters are not used by simulation and specifically designed for users' convenience. This would be helpful for your purpose to define the area of each node.

Also, I want to make the Utilities submodule as a code base for custom utilities for specific purposes. Plz feel free to submit your utility code here. For example, a function for "select nodes by polygon" that you suggested earlier would be very useful.

EwoutH commented 2 months ago

Thanks a lot for all this work! I will look into it and get back to you.