I'm converting a Monte Carlo simulation of certain random geometries from Python to Rust. The freedom I had in Python allowed me to be somewhat sloppy about storing references to other objects all throughout my code, but this seems to be trickier to implement in Rust.
In my current Python implementation, the main object is a Geometry
. It contains a dictionary of Vertex
es with a unique ID (the ID is also its lookup key in the dictionary) and a dictionary of Triangle
s (same scenario as for Vertex
). Every Triangle
contains a list of three Vertex
es (no dictionary this time, here it's an ordered list), and every Vertex
contains a dictionary of all the Triangle
s that it appears in (again indexed by the Triangle
's unique ID).
This leads to a whole lot of cross-references, but it does make it very easy to find things. For example, it is straightforward to find all the neighbouring Vertex
es of a specific Vertex
by simply looping through all the Triangle
s it appears in and collecting all the Vertex
es that are contained in these Triangle
s.
For convenience, here is a summary of the data structures:
class Geometry(object):
def __init__(self):
self.vertices = {}
self.triangles = {}
class Vertex(object):
counter = 0
def __init__(self):
self.index = Vertex.counter
Vertex.counter += 1
self.triangles = {}
class Triangle(object):
counter = 0
def __init__(self, vertices):
self.index = Triangle.counter
Triangle.counter += 1
self.vertices = vertices # list of length 3
In Rust, this will not work because of the ownership model. The most straightforward alternative I could come up with would be to give the Geometry
object a member HashMap
of Vertex
es and Triangle
s, just like in my Python code (again indexed by ID). The Vertex
and Triangle
objects would then contain a vector/array of the IDs of their 'members'. This ID can then be used to find the appropriate object in the HashMap
.
For example, if a certain Triangle
contains the Vertex
es with IDs 1, 2, and 3, I could set the variable 'vertices' in the Triangle
object to the array [1,2,3]
. However, in order to actually work with the Vertex
objects afterwards, I'd have to subsequently look up the object in the HashMap
. This would lead to a lot of repetition all throughout the code. Furthermore, since the Triangle
and Vertex
structs are not aware of the struct Geometry
, it will be impossible to add a method to either Triangle
or Vertex
that will encapsulate this process - after all, they cannot access the appropriate HashMap
.
I've been thinking about a way of making this work with borrows, so that the Triangle
and Vertex
objects can in fact store a reference to one another. However, my experience with Rust is severely lacking, so I'm not getting very far. Some initial naive approaches always ran into problems with lifetimes and I'm even starting to doubt whether my current setup is workable at all in the Rust paradigm.
All feedback on any part of my question would be very welcome. Ideally I'm looking for a concrete suggestion on how to implement something along my line of thinking, but if you get the idea that I should rethink my entire approach, then I'd also be very happy to hear that.