动态生成n维超立方体m面列表的算法

2024-01-01

我正在尝试设计一种算法,给定n, m, and vertices (where n= 超立方体的维数,m= 我们尝试生成的面的尺寸,以及vertices is an ordered中的顶点列表n维超立方体),返回表示 m 面的顶点数组的数组n维超立方体 https://en.wikipedia.org/wiki/Hypercube.

这可能是一种令人困惑的措辞方式,所以这里有一些例子:

假设我们想要获取立方体(3 维超立方体)中的边数组(1 面)。如果我们假设vertices是立方体中顶点的二进制表示的有序数组(即[[0, 0, 0], [0, 0, 1], [0, 1, 0], ..., [1, 1, 1]]), 我们会有:

> getMFaces(1, 3, vertices)
> [
    [[0, 0, 0], [0, 0, 1]],
    [[0, 1, 0], [0, 1, 1]],
    [[0, 0, 0], [0, 1, 0]],
    [[0, 0, 1], [0, 1, 1]],
    [[1, 0, 0], [1, 0, 1]],
    [[1, 1, 0], [1, 1, 1]],
    [[1, 0, 0], [1, 1, 0]],
    [[1, 0, 1], [1, 1, 1]],
    [[0, 0, 0], [1, 0, 0]],
    [[0, 0, 1], [1, 0, 1]],
    [[0, 1, 0], [1, 1, 0]],
    [[0, 1, 1], [1, 1, 1]]
  ]

二维超立方体(面)中的边将给出:

> getMFaces(1, 2, vertices)
> [
    [[0, 0], [0, 1]],
    [[1, 0], [1, 1]],
    [[0, 0], [1, 0]],
    [[0, 1], [1, 1]]
  ]

立方体中的面(2 个面)将给出:

> getMFaces(2, 3, vertices)
> [
    [[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1]],
    [[1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]],
    [[0, 0, 0], [0, 0, 1], [1, 0, 0], [1, 0, 1]],
    [[0, 1, 0], [0, 1, 1], [1, 1, 0], [1, 1, 1]],
    [[0, 0, 0], [0, 1, 0], [1, 0, 0], [1, 1, 0]],
    [[0, 0, 1], [0, 1, 1], [1, 0, 1], [1, 1, 1]],
  ]

请注意,面不是边数组的数组,而是表示面的顶点的数组。对于 cel 和任何其他 n 面也是如此,即 n 面由长度表示2^n顶点数组。

使用汉明距离

一种解决方案(我目前正在使用)是使用汉明距离 https://en.wikipedia.org/wiki/Hamming_distance顶点的二进制表示之间的比较以确定它们是否是 m 面的一部分。如果组合2^m顶点完全不同m位,然后它们形成一个 m 面。

例如,[0, 0, 0] and [0, 0, 1]形成一条边(1-面),因为它们相差 1 位。

[0, 0, 0], [0, 0, 1], [0, 1, 0], and [0, 1, 1]形成一个面(2-face),因为它们相差 2 位(即所有三个顶点共享 1 位)。

我的算法生成了以下列表m-通过递归构建顶点组合来构建面。每次将顶点添加到组合中时,都会检查组合中所有顶点之间的汉明距离。如果汉明距离 >m,该组合将被忽略,否则我们将继续构建该组合,直到它包含2^m顶点。如果是的话,汉明距离恰好是m,它将被添加到m- 面孔列表。这将持续下去,直到检查完所有组合为止。

该算法的问题在于效率极低。需要检查的组合数量随着维度呈指数级增长n超立方体的增加。一旦我开始构建维度 9 及以上的 m 面列表,算法将需要 30 秒、1 分钟、5 分钟等才能完成。

寻找模式

我想,因为提供的顶点数组总是有序的,所以一定有某种模式形成为n and/or m增加。使用这种模式,我应该能够想出一种不依赖于构建组合的新算法。

为了可视化之间的关系n and m,我将有序的顶点放入电子表格中,并在单元格中着色以表示 m 面。我首先只查看边缘:

我立刻注意到一些模式

  • n顶点索引之间不同大小的间隙
  • The i差距是2^i

然后我注意到维度的边缘列表n基于维度的边缘列表构建n-1递归地。这是有道理的,因为 n-超立方体几何结构是基于 n-1-超立方体几何结构构建的。

使用递归

我重新排列了我的电子表格并制作了表格n = 1..4 and m = 1..3:

m = 1适用于尺寸 1 - 4

Here, v表示顶点的有序数组,a表示输出的 m 面数组,每一列代表一个 m 面,彩色轮廓显示与较低维度的 m 面列表的关系(与较低维度的递归关系)。

黑色方块中的数字代表顶点的索引v.

我能够使用我注意到的模式推导出以下递归算法(其中m = 1是脸部的尺寸,n是超立方体的维数)。它不生成顶点数组,而是生成索引数组i代表的是i顶点:

generateEdges(n) {    // m is always 1 here since we're only producing edges
  if (n === 1) {
    return [[0, 1]];
  } else {
    // we start with the edges from the previous dimension
    const prev = generateEdges(n-1);
    // we duplicate these edges and add 2^(n-1) to each index
    const curr = prev.map(edge => edge.map(i => i + 2**(n-1)));
    
    const next = [];
    // we only care about the prev.length - 2**(n-2) indexes
    // since these are the new edges added in the previous dimension
    for (let i = prev.length - 2**(n-2); i < prev.length; i++) {
      // we form new edges by combining index [i][0] and [i][1] of prev and curr
      next.push([prev[i][0], curr[i][0]]);
      next.push([prev[i][1], curr[i][1]]);
    }

    // finally, we combine all 3 to get our new edge list
    return [...prev, ...curr, ...next];
  }
}

该算法成功地生成了维度的边列表n and is much比必须检查所有可能的顶点组合(如使用汉明距离时的情况)更有效。

缺点是该算法会生成索引,因此您必须随后将索引映射到实际顶点。它几乎立即生成维度高达 14 或 15 的边缘列表。

然后我做了床单m = 2 and m = 3(面孔和细胞)看看我是否可以绘制任何类型的连接并扩展我的递归算法以适用于所有人ms:

m = 2适用于尺寸 1 - 4

m = 3适用于尺寸 1 - 4

这就是我被困住的地方

我可以看出有某种模式贯穿于所有ms,我只是对精确定位并将其转化为算法的任务感到不知所措。

我可以告诉你m- 面孔列表m > 1以与我提供的递归算法类似的方式构建m = 1,我只是无法弄清楚需要添加什么。

对于这篇又长又令人困惑的帖子,我深表歉意。正如您可能从我对可视化的需求中看出的那样,我不太擅长线性代数,因此可能有一些明显的数学原理或我遗漏的东西。

对此算法的任何想法或帮助将不胜感激。我试图使其尽可能高效——也许使用循环实现它会比递归更有效,但我只是想在尝试提高效率之前获得一个工作算法。

由于这是我的第一篇文章,我不能 100% 确定我是否在正确的位置发布了这个问题,所以如果我在错误的论坛中,请告诉我。我可以看到这类问题可能更适合更多以算法或数学为中心的论坛,所以请告诉我是否有更好的地方可以发布此问题!

Update

对于任何想知道的人,这是我使用中描述的逻辑编写的函数马特·蒂默曼的回答 https://stackoverflow.com/a/71256888/12264298:

// Utility function that converts a decimal number to a padded binary string
const getBinaryStr = (n, padding = 0) => (new Array(padding).fill("0").join("") + (n >>> 0).toString(2)).slice(-padding);

// Utility function that inserts a character into index ind of string str
const insertIntoStr = (char, str, ind) => `${str.slice(0, ind)}${char}${str.slice(ind)}`;

// Utility function that gets all n-length combinations of elements in arr
const getCombinations = (n, arr) => (arr.length === n) ? [arr] : (n === 0) ? [[]] : [...getCombinations(n-1, arr.slice(1), true).map(c => [arr[0], ...c]), ...getCombinations(n, arr.slice(1), true)];

// Returns a list of m-faces of an n-dimensional hypercube
const generateMFaces = (m, n) => {
    if (m > n) return [];

    // An m-face has m free bits and n - m fixed bits
    const free = m;
    const fixed = n - m;

    // Generate all combinations of n - m fixed bit indices
    const fixedIndices = getCombinations(fixed, Object.keys(new Array(n).fill(true)));

    const faces = [];
    // Select the indexes to fix
    for (let i = 0; i < fixedIndices.length; i++) {
        // Count in binary over the fixed bits
        for (let j = 0; j < 2**(n - m); j++) {
            const fixedBits = getBinaryStr(j, fixed);
            const face = [];
            // Count in binary over the free bits
            for (let k = 0; k < 2**m; k++) {
                let bitCode = getBinaryStr(k, free);
                // Insert fixed bits into their propper indexes
                for (let h = 0; h < fixed; h++) {
                    bitCode = insertIntoStr(fixedBits[h], bitCode, parseInt(fixedIndices[i][h]));
                }
                face.push(bitCode);
            }
            faces.push(face);
        }
    }
    return faces;
}

console.log(generateMFaces(1, 2));
console.log(generateMFaces(2, 3));
console.log(generateMFaces(3, 3));
console.log(generateMFaces(4, 3));
console.log(generateMFaces(4, 8).length);
console.log(generateMFaces(3, 12).length);

Every m-sized subset of the n dimensions is an "orientation" with those m dimensions "free". For each orientation, you can generate a face by generating all 2m combinations of the m coordinates in the m free dimensions, while holding the coordinates for the other dimensions fixed. Each of the 2n-m combinations of coordinates for the other dimensions is the "position" of a different face.

The number of orientations is C(n,m) = n!/m!(n-m)!, so you should end up with C(n,m) * 2n-m faces overall.

The number of edges in a cube, for example = C(3,1) * 22 = 3 * 4 = 12.

立方体的面数为 C(3,2) * 2 = 3 * 2 = 6。

生成所有面孔并不太困难:

  • For each orientation, determine the free and fixed dimensions
    • Count in binary using the fixed dimensions to find all the face positions
      • 对于每个面,在自由维度上进行二进制计数以生成其顶点。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

动态生成n维超立方体m面列表的算法 的相关文章

随机推荐

  • C语言中如何连接两个字符串?

    如何添加两个字符串 I tried name derp herp 但我得到一个错误 表达式必须具有整型或枚举类型 C 不支持其他一些语言所具有的字符串 C中的字符串只是一个指向数组的指针char由第一个空字符终止 C中没有字符串连接运算符
  • 以太坊 Solidity 中的划分

    我正在创建一个发行代币的合约 我希望持有代币的账户能够检查他们拥有的所有代币所占的百分比 我知道以太坊还没有实现浮点数 我应该怎么办 在客户端而不是在 Solidity 中执行该计算可能是最好的 最低的 Gas 成本并且实施起来很简单 如果
  • 无法将 ndarray 转换为 Tensor 或 TensorFlow 模型中出现运算错误

    我正在 TensorFlow 中实现 Wasserstein DCGAN 运行此行时会发生错误 train image sess run image batch 处理这个异常会抛出另一个异常 Fetch argument array 0 0
  • 用自身初始化 C++ const 变量

    刚才我遇到了以下类型的错误 include
  • BeagleBone Black 无法识别 USB 蓝牙适配器

    我正在尝试弄清楚如何让 USB 蓝牙适配器与我的 BeagleBone Black 配合使用 我尝试了一些不同的方法但没有成功 但看到其他人的帖子似乎取得了一些成功 我已经尝试过此处记录的过程 http www michaelhleonar
  • JMS:我们可以在 OnMessage() 中从队列中获取多条消息而不提交或回滚吗

    我正在使用 JMS 客户端 它从远程服务器接收 JMS 消息 我正在客户端的 onMessage 方法中监听 JMS 消息 我面临的问题是 即使我定期在客户端消费消息 消息也会在服务器端累积 我根据在客户端进行的处理发送 rollback
  • /usr/bin/ld:搜索 foo 时跳过不兼容的 foo.so

    我使用的是 Ubuntu 13 10 64 位 在编译 vlfeat 库的 python 包装器时遇到以下错误 g o vlfeat so vl aib o vl generic o vl hikmeans o vl ikmeans o v
  • PHP 套接字与流

    我认为 php 套接字和 php 流是相互重叠的 我已经成功地使用套接字或流制作了一个 CLI PHP 聊天客户端和一个服务器 这里有一些说明性的代码行 使用套接字 main socket socket create AF INET SOC
  • PowerShell 通用集合

    我一直在 PowerShell 中推进 NET 框架 但遇到了一些我不明白的问题 这工作正常 foo New Object System Collections Generic Dictionary 2 System String Syst
  • set_form_data POST 中的转义参数

    这是最奇怪的事情 当我添加 in set form data value被解释为value 在服务器端 当我删除 dontescape 的值被解释为file 3a 2f 2f 2fpath 2fto 到底发生了什么 我不希望任何东西被转义
  • Bender.js:“bender server run”命令打开目录中的bender.js配置文件,而不是启动bender.js服务器

    我是bender js 的新手 我正在尝试运行示例项目 https github com benderjs benderjs example project https github com benderjs benderjs exampl
  • 平衡数组子区间中元素数量的算法?

    假设您有一个包含 4 种不同类型元素的数组 1 1 2 3 1 2 2 3 3 4 4 1 我想找到导致每个元素数量相等且元素总数最大的最长子区间 在这种情况下 它将是 1 1 2 3 1 2 2 3 3 因为这会导致 3 个二 3 个三和
  • 打印机通讯捕获

    如果我需要将其发布到其他地方 请告诉我 我们有一些正在重写的旧软件 它使用专有打印机的打印机驱动程序 我需要重写软件绕过打印驱动程序并直接进入打印机 我确实有打印机通信的规格 这很好 但我想做的是监视与打印机的通信以查看其内容 来自我重写的
  • 迭代强类型泛型 List 的最佳方法是什么?

    在 C NET 和 VB NET 中迭代强类型泛型列表的最佳方法是什么 For C foreach ObjectType objectItem in objectTypeList do some stuff VB NET 的答案来自紫蚂蚁
  • 便携式WAMP包?

    无论如何 我可以在 Windows 7 计算机上的 USB 上使用 PHP mySQL apache phpmyadmin 吗 询问的原因是我没有足够的权限在计算机上安装像 XAMPP 这样的软件包 并且我想测试一些 php 代码文件 谢谢
  • 使用网络摄像头跟踪手势

    我想开发一个程序 使用网络摄像头跟踪四种颜色 并将其放在我双手的食指和拇指上 根据我手的手势 计算机将解释这些手势并执行命令 例如 如果我打开一个网站 我所要做的就是用手指捏一下 网页就会缩放 我希望获得 stackoverflow 社区的
  • 如何根据对象以角度选择表格行?

    大家好 我有一个场景 我真的很困惑如何弄清楚 场景是我有 1 垫料台 即角料台 2 以及一个详细信息视图 根据表中特定行的单击显示详细信息 3 对象列表作为数据源 我在行的单击事件上传递对象 并将对象传递到详细信息视图 并且现在显示该特定行
  • iOS 错误“嵌入式二进制文件未使用与父应用程序相同的证书进行签名”

    这是我在 IOS 应用程序开发中的第一步 我面临着一些我无法解决的问题 error Embedded binary is not signed with the same certificate as the parent app Veri
  • 如何防止元素内的分栏?

    考虑以下 HTML div class x ul li Number one li li Number two li li Number three li li Number four is a bit longer li li Numbe
  • 动态生成n维超立方体m面列表的算法

    我正在尝试设计一种算法 给定n m and vertices where n 超立方体的维数 m 我们尝试生成的面的尺寸 以及vertices is an ordered中的顶点列表n维超立方体 返回表示 m 面的顶点数组的数组n维超立方体