如何将这些相关索引组织成可以在 Rust 中有效查找的内容?
Posted
技术标签:
【中文标题】如何将这些相关索引组织成可以在 Rust 中有效查找的内容?【英文标题】:How do I organize these related indices into something that can be looked up efficiently in Rust? 【发布时间】:2017-06-22 17:11:12 【问题描述】:背景
在一种称为有限元法的算法中,连续区域被离散为具有一致几何形状的重复部分,在这些部分上基于它们之间的连续性假设形成链接方程。
在这种情况下,我选择将一个形状划分为一个任意网格,现在我在遍历元素时尝试将元素的值连接在一起。这是我正在谈论的那种网格的示例:
指数
有一堆相关的索引:
元素索引(蓝绿色数字),线性,行优先,范围0..ROWS*2
。
节点索引(棕色数字),线性,行优先,范围0..ROWS*COLS
。
局部元素顶点索引(淡紫色编号),按元素逆时针方向,范围0..2
。
空间中实际点的坐标(与元素的结构以及网格的结构一起存储)
问题
为了进入算法的下一步,我需要遍历每个节点并计算一些由局部元素索引索引的值的总和,并将它们存储在另一个矩阵中。例如,如果我在节点 8 上,我的元素查找/访问函数通常是 V(el_index, start_vertex, end_vertex)
,我的输出矩阵是 S(start_node, end_node)
:
S(8,8) = V(el_14, vert_1, vert_1) + V(el_15, vert_1, vert_1) + V(el_04, vert_0, vert_0) + V(el_03, vert_0, vert_0) + V(el_2, vert_2, vert_2) + V(el_13, vert_2, vert_2)
S(8,9) = V(el_15, vert_1, vert_2) + V(el_4, vert_0, vert_2)
等等,对于来自节点 8 的所有连接(蓝绿色线)。(连接是对称的,所以一旦我计算 S(7,8)
,我就不需要计算 S(8,7)
。)
问题是,网格(以及其他所有东西)在运行时都是参数化的,所以哪个节点索引+邻接方向对应哪个元素索引是动态确定的。我需要告诉程序,“获取元素索引,其中vert_x
的节点索引是我当前的节点索引。”这就是告诉程序在V()
中访问哪个元素的指令。
有没有办法在 Rust 中以简单透明的方式关联这些索引?
尝试
-
我尝试以节点矩阵的行步长为模计算一些简单的算术函数,但结果很混乱且难以调试,并且需要进行详细的边界检查。
我尝试创建三个
HashMap
s,以每个三角形元素的不同顶点为键,保存每个顶点的值,但问题是相邻三角形共享顶点编号以及空间坐标。
我考虑过使用多个键对 HashMap
进行键控,但 Rust 文档没有说明使用多个键的 HashMap
。
【问题讨论】:
你是怎么想到这个问题的? 哈哈哈我不明白你的意思。我现在正在为静电学实现它,即拉普拉斯方程。它似乎适用于任何可以定义可处理元素函数的东西,这些元素函数形成一些更大的函数的被积函数。 @bright-star:我很抱歉,但我是部分色盲,我根本不明白你的数字......你有一些用于计算 S(8, 8) 和S(8, 9) 代替?此外,值的范围是多少(元素索引、节点索引、局部元素顶点索引和坐标),在我看来,顶点索引在图中的0..3
中。最后,您是否考虑过通过“空”外层来消除边界检查?
@bright-star:不用担心;如前所述,文字描述可能更容易(不知道是否有盲人开发人员经常这样做,但他们无法访问图像)。
我考虑过使用多个键为 HashMap
设置键,但 Rust 文档没有说明使用多个键的 HashMap
。 元组可以是 @ 987654340@键;会有帮助吗?
【参考方案1】:
我认为这是一种可能的解决方法,但我希望有更好的解决方法:
按照this question将一个HashMap
嵌套在另一个中,节点索引作为第一个键,元素索引作为第二个键/第一个值,元素本身作为第二个值。
所以,迭代可以如下所示:
-
遍历网格节点索引
N
获取所有以N
为第一个键的元素
请注意,顶点索引和(相对)元素索引具有以下模式,具体取决于您从哪里编号:
从矩阵左上角开始的节点索引编号(在这个编程领域中很常见):
| Element (index ordinal) | Vertex |
|-------------------------|--------|
| 0 (min) | 1 |
| 1 | 2 |
| 2 | 1 |
| 3 | 2 |
| 4 | 0 |
| 5 | 0 |
节点索引编号以图片开头,从左下角开始:
| Element (index ordinal) | Vertex |
|-------------------------|--------|
| 0 (min) | 2 |
| 1 | 0 |
| 2 | 0 |
| 3 | 2 |
| 4 | 1 |
| 5 | 1 |
由于您可以像这样硬编码元素的相对顺序,因此使用HashMap<usize, Vec<Element>>
甚至HashMap<usize, [Element; 6]>
可能会更好。
这种方法提出了如何将节点索引与元素索引动态关联的问题。你怎么知道要在HashMap
中插入哪些元素?实现这一点的一种方法是将元素顶点对应的节点也以相同的顺序记录在元素结构中。
此时,您可以在遍历矩阵时计算像 adjacent_elements
这样的列表,并使用上述模式来确定要访问的内容(遗憾的是,通过边界检查)。
【讨论】:
由于生成元素的函数从知道何时生成哪些节点开始(在三角形的情况下,一对元素的“左上/左下”顶点是当前迭代的节点),这可以通过节点索引以相同的方式参数化。这可能又让事情变得过于复杂了。 在迭代的同时动态生成元素,正如之前的评论所暗示的那样太复杂了:元素将被重复生成,因为它们与三个节点相邻。以上是关于如何将这些相关索引组织成可以在 Rust 中有效查找的内容?的主要内容,如果未能解决你的问题,请参考以下文章