Mathematica 中稀疏数组的 Outer 有效替代方案?

2024-01-11

假设我有两个非常大的列表 {a1, a2, …} 和 {b1, b2, …},其中所有 ai 和 bj 都是大型稀疏数组。为了提高内存效率,我将每个列表存储为一个综合稀疏数组。

现在我想在所有可能的 ai 和 bj 对上计算某个函数 f,其中每个结果 f[ai, bj] 又是一个稀疏数组。顺便说一句,所有这些稀疏数组都具有相同的维度。

While

Flatten[Outer[f, {a1, a2, ...}, {b1, b2, ...}, 1], 1]

返回所需的结果(原则上)它似乎消耗了过多的内存。尤其重要的是,因为返回值是稀疏数组的列表,而在我感兴趣的情况下,一个综合稀疏数组的效率要高得多。

是否有一种有效的替代方法来替代上述使用Outer?

更具体的例子:

{SparseArray[{{1, 1, 1, 1} -> 1, {2, 2, 2, 2} -> 1}],
 SparseArray[{{1, 1, 1, 2} -> 1, {2, 2, 2, 1} -> 1}],
 SparseArray[{{1, 1, 2, 1} -> 1, {2, 2, 1, 2} -> 1}],
 SparseArray[{{1, 1, 2, 2} -> -1, {2, 2, 1, 1} -> 1}],
 SparseArray[{{1, 2, 1, 1} -> 1, {2, 1, 2, 2} -> 1}],
 SparseArray[{{1, 2, 1, 2} -> 1, {2, 1, 2, 1} -> 1}],
 SparseArray[{{1, 2, 2, 1} -> -1, {2, 1, 1, 2} -> 1}],
 SparseArray[{{1, 2, 2, 2} -> 1, {2, 1, 1, 1} -> 1}]};
ByteCount[%]

list = SparseArray[%%]
ByteCount[%]

Flatten[Outer[Dot, list, list, 1], 1];
ByteCount[%]
list1x2 = SparseArray[%%]
ByteCount[%]

Flatten[Outer[Dot, list1x2, list, 1], 1];
ByteCount[%]
list1x3 = SparseArray[%%]
ByteCount[%]

等等。不仅是原始中间结果Outer(稀疏数组列表)效率极低,Outer计算本身似乎也消耗了太多内存。


我将提出一种相当复杂的解决方案,但只允许使用大约两倍的内存during将最终结果存储为所需的计算SparseArray。为此付出的代价将是执行速度慢得多。

The code

稀疏数组构造/解构API

这是代码。首先,稍微修改一下(以解决高维稀疏数组)稀疏数组构造 - 解构 API,取自这个答案 https://stackoverflow.com/questions/7525782/import-big-files-arrays-with-mathematica/7527064#7527064:

ClearAll[spart, getIC, getJR, getSparseData, getDefaultElement, 
  makeSparseArray];
HoldPattern[spart[SparseArray[s___], p_]] := {s}[[p]];
getIC[s_SparseArray] := spart[s, 4][[2, 1]];
getJR[s_SparseArray] := spart[s, 4][[2, 2]];
getSparseData[s_SparseArray] := spart[s, 4][[3]];
getDefaultElement[s_SparseArray] := spart[s, 3];
makeSparseArray[dims_List, jc_List, ir_List, data_List, defElem_: 0] :=
   SparseArray @@ {Automatic, dims, defElem, {1, {jc, ir}, data}};

迭代器

以下函数生成迭代器。迭代器是封装迭代过程的好方法。

ClearAll[makeTwoListIterator];
makeTwoListIterator[fname_Symbol, a_List, b_List] :=
  With[{indices = Flatten[Outer[List, a, b, 1], 1]},
   With[{len  = Length[indices]},
    Module[{i = 0},
      ClearAll[fname];
      fname[] := With[{ind = ++i}, indices[[ind]] /; ind <= len];
      fname[] := Null;
      fname[n_] := 
        With[{ind = i + 1}, i += n; 
           indices[[ind ;; Min[len, ind + n - 1]]] /; ind <= len];
      fname[n_] := Null;
 ]]];

请注意,我可以更高效地实现上述函数而不是使用更多内存Outer但就我们的目的而言,这不是主要问题。

这是一个更专业的版本,它为二维索引对生成迭代器。

ClearAll[make2DIndexInterator];
make2DIndexInterator[fname_Symbol, i : {iStart_, iEnd_}, j : {jStart_, jEnd_}] :=
   makeTwoListIterator[fname, Range @@ i, Range @@ j];
 make2DIndexInterator[fname_Symbol, ilen_Integer, jlen_Integer] :=
   make2DIndexInterator[fname, {1, ilen}, {1, jlen}];

这是它的工作原理:

In[14]:= 
makeTwoListIterator[next,{a,b,c},{d,e}];
next[]
next[]
next[]

Out[15]= {a,d}
Out[16]= {a,e}
Out[17]= {b,d}

我们还可以使用它来获取批处理结果:

In[18]:= 
makeTwoListIterator[next,{a,b,c},{d,e}];
next[2]
next[2]

Out[19]= {{a,d},{a,e}}
Out[20]= {{b,d},{b,e}}

,我们将使用第二种形式。

SparseArray - 构建函数

该函数将构建一个SparseArray通过获取数据块(也在SparseArray形式)并将它们粘合在一起。它基本上是使用的代码this https://stackoverflow.com/questions/7525782/import-big-files-arrays-with-mathematica/7527064#7527064答案,封装成一个函数。它接受用于生成下一个数据块的代码段,包装在Hold(我也可以让它HoldAll)

Clear[accumulateSparseArray];
accumulateSparseArray[Hold[getDataChunkCode_]] :=
  Module[{start, ic, jr, sparseData, dims, dataChunk},
   start = getDataChunkCode;
   ic = getIC[start];
   jr = getJR[start];
   sparseData = getSparseData[start];
   dims = Dimensions[start];
   While[True, dataChunk = getDataChunkCode;
     If[dataChunk === {}, Break[]];
     ic = Join[ic, Rest@getIC[dataChunk] + Last@ic];
     jr = Join[jr, getJR[dataChunk]];
     sparseData = Join[sparseData, getSparseData[dataChunk]];
     dims[[1]] += First[Dimensions[dataChunk]];
   ];
   makeSparseArray[dims, ic, jr, sparseData]];

把它们放在一起

这个函数是主要函数,将所有功能放在一起:

ClearAll[sparseArrayOuter];
sparseArrayOuter[f_, a_SparseArray, b_SparseArray, chunkSize_: 100] := 
  Module[{next, wrapperF, getDataChunkCode},
    make2DIndexInterator[next, Length@a, Length@b];
    wrapperF[x_List, y_List] := SparseArray[f @@@ Transpose[{x, y}]];
    getDataChunkCode :=
      With[{inds = next[chunkSize]},
         If[inds === Null, Return[{}]];
         wrapperF[a[[#]] & /@ inds[[All, 1]], b[[#]] & /@ inds[[All, -1]]]
      ];
    accumulateSparseArray[Hold[getDataChunkCode]]
  ];

在这里,我们首先生成迭代器,它将为我们提供索引对列表的按需部分,用于提取元素(也SparseArrays)。请注意,我们通常会从两个大输入中提取不止一对元素SparseArray一次 -s,以加快代码速度。我们一次处理多少对由可选的控制chunkSize参数,默认为100。然后我们构建代码来处理这些元素并将结果放回SparseArray,我们使用辅助函数wrapperF。迭代器的使用并不是绝对必要的(可以使用Reap-Sow相反,与其他答案一样),但允许我将迭代逻辑与稀疏数组的通用累积逻辑分离。

基准测试

首先,我们准备大型稀疏数组并测试我们的功能:

In[49]:= 
arr = {SparseArray[{{1,1,1,1}->1,{2,2,2,2}->1}],SparseArray[{{1,1,1,2}->1,{2,2,2,1}->1}],
SparseArray[{{1,1,2,1}->1,{2,2,1,2}->1}],SparseArray[{{1,1,2,2}->-1,{2,2,1,1}->1}],
SparseArray[{{1,2,1,1}->1,{2,1,2,2}->1}],SparseArray[{{1,2,1,2}->1,{2,1,2,1}->1}]};

In[50]:= list=SparseArray[arr]
Out[50]= SparseArray[<12>,{6,2,2,2,2}]

In[51]:= larger = sparseArrayOuter[Dot,list,list]
Out[51]= SparseArray[<72>,{36,2,2,2,2,2,2}]

In[52]:= (large= sparseArrayOuter[Dot,larger,larger])//Timing
Out[52]= {0.047,SparseArray[<2592>,{1296,2,2,2,2,2,2,2,2,2,2}]}

In[53]:= SparseArray[Flatten[Outer[Dot,larger,larger,1],1]]==large
Out[53]= True

In[54]:= MaxMemoryUsed[]
Out[54]= 21347336

现在我们进行功率测试

In[55]:= (huge= sparseArrayOuter[Dot,large,large,2000])//Timing
Out[55]= {114.344,SparseArray[<3359232>,{1679616,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}]}

In[56]:= MaxMemoryUsed[]
Out[56]= 536941120

In[57]:= ByteCount[huge]
Out[57]= 262021120

In[58]:= (huge1 = Flatten[Outer[Dot,large,large,1],1]);//Timing
Out[58]= {8.687,Null}

In[59]:= MaxMemoryUsed[]
Out[59]= 2527281392

对于这个特定的例子,建议的方法比直接使用的内存效率高 5 倍Outer,但慢了大约 15 倍。我不得不调整chunksize参数(默认为100,但是对于上面我使用的2000,以获得最佳速度/内存使用组合)。我的方法仅使用了存储最终结果所需内存两倍的峰值内存。与相比,节省内存的程度Outer- 基于方法将取决于所讨论的稀疏数组。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Mathematica 中稀疏数组的 Outer 有效替代方案? 的相关文章

  • 如何使用 Mathematica 查找 Waldo?

    这周末困扰着我 有什么好方法来解决这些问题沃尔多在哪里 https en wikipedia org wiki Where 27s Wally 3F Wally 北美以外 谜题 使用 Mathematica 图像处理和其他功能 这是我到目前
  • 简化 Mathematica 中的正则表达式

    我最近发现克莱尼代数 http en wikipedia org wiki Kleene algebra用于操作和简化正则表达式 我想知道这是否已内置到 Mathematica 等任何计算软件程序中 如果有一个计算工具来进行大型表达式的并集
  • 将声音导出为 WAV 文件

    我从来没有在 Mma 中过多地使用声音 I have t Sound List Violin SoundNote 6 我怎样才能导出t作为 WAV 文件 当我尝试显而易见的事情时 Export c test wav t I get 在这个旧
  • Mathematica“AppendTo”函数问题

    我是 Mathematica 的新手 在向数据表添加列时遇到了重大故障 我在 Vista 中运行 Mathematica 7 我在RFD上花了很多时间才来这里问 我有一个包含三列五行的数据表 mydata 我正在尝试将两个包含五个元素的列表
  • 交叉联接行为 (SQLServer 2008)

    我一直在尝试找出我的查询的问题 该查询实际上是由 hibernate 从 HQL 生成的 但生成的 SQL 并没有达到我的预期 稍微修改 SQL 会产生正确的结果 但我不确定为什么修改会产生任何差异 原始查询 不返回任何行 select s
  • 在 Mathematica 中使用多个包和引用构建应用程序包

    我正在 Mathematica 中构建一个应用程序包 应用程序包含多个包并引用其他应用程序包 为了设置一切 我使用并遵循了工作台帮助部分的应用程序包说明 该部分也可以在以下位置找到 http reference wolfram com wo
  • 替换 LEFT OUTER JOIN 中返回的空值

    SELECT WO BreakerRail ID indRailType RailType indRailType RailCode WO BreakerRail CreatedPieces WO BreakerRail OutsideSo
  • Mathematica 内部数字格式和精度

    切线相关this https stackoverflow com q 4939616 181759问题 数字格式到底发生了什么 In 1 InputForm 3 12987 10 270 Out 1 3 12987 270 In 2 Inp
  • 在mathematica中使用Input[]输入数据

    我怎样才能在这段代码中使输入命令对话框中的文本像这样 输入 1 元素 输入 2 元素 For k 1 k n k br Input Enter the i element AppendTo x br 确保您的变量匹配 您可以使用Row来构建
  • 左外连接不返回主表中的所有记录

    当我执行左外连接时 我希望在添加连接表之前获取查询将返回的所有记录 但它仅返回与连接表匹配的记录 即 表中不存在 092387 的记录 文档 所以我只想为该记录的 文件名 字段返回 null 我做错了什么 mysql gt select d
  • 在 MathLink 函数中检查中止?

    我刚刚发现这样的MathLink功能为LinkWrite and LinkRead有类似其内部的东西CheckAbort吸收任何中止 并且不会进一步传播它们 这可以很容易地显示为LinkRead link LinkLaunch First
  • 为什么即使仅使用一种规则和一种表达式,Replace 和 ReplaceAll 也会给出不同的结果?

    也许有人可以向我解释为什么Replace给出了不同的答案ReplaceAll 即使我使用一条规则 并且我认为我有一种表达方式 根据文档 ReplaceAll looks at each part of expr tries all the
  • 如何以编程方式访问 Mathematica 8 中有关“Graph”对象的信息?

    我正在尝试访问某个范围内的信息GraphMathematica 8 中的对象 出于某种原因 Part命令似乎不起作用 myGraph是我想要访问的对象 下面的第一行显示 myGraph 其他人的作用是检查它 myGraph myGraph
  • 如何使用 JPA CriteriaBuilder 查询执行外连接?

    我正在使用 JPA 2 0 Hibernate 4 1 0 Final 和 MySQL 5 5 27 我想构造一个 JPA 查询 每行返回两个实体 并且我想执行右外连接 这两个实体是 Entity Table name user uniqu
  • Mathematica:为什么 3D 绘图会记住最后的视点/旋转,即使在再次评估后也是如此?

    我觉得这有点烦人 我制作了一个 3D 绘图 最初它以默认方向出现 然后 我使用鼠标以某种方式旋转它 现在我再次运行该命令 期望获得原始形状 即通过鼠标旋转它之前的原始方向 但相反 它只是给了我与屏幕上相同的绘图 即它似乎保留 记住了该输出单
  • 了解跟踪*

    再会 当试图理解数学使用标准的评估顺序Trace and TraceScan最近开发的命令及其漂亮的视觉表示thread https stackoverflow com questions 5459735 the clearest way
  • 使用 select 操作 mathematica 中的列表

    我已将一些数据导入 Mathematica 中 数据将类似于 0 2 2 3 4 3 5 4 8 4 我想丢弃 x 值小于给定值的所有元素 或者创建一个包含 x 值大于该值的数据的新列表 我假设Select应该做这项工作 但我不知道怎么做
  • 在 Mathematica 中创建具有不同颜色边的图形

    我想创建一个图 图论 其中某些边具有与其他边不同的颜色 这将用于突出显示图中从一个顶点到另一个顶点的路径 以下是一些具有不同颜色边缘的示例http demonstrations wolfram com AGraphTheoryInterpr
  • 为什么使用牛顿法的 FindMaximum 会抱怨找不到足够的函数减少?

    首先 这看起来 来自 ContourPlot 是一个相当简单的最大化问题 为什么使用牛顿法的 FindMaximum 会出现问题 其次 如何摆脱警告 第三 如果我无法摆脱这些警告 我如何判断警告是否有意义 即最大化失败 例如 在下面的代码中
  • Mathematica 作业中不需要的评估:为什么会发生这种情况以及如何在包加载过程中对其进行调试?

    我正在开发一个 大 包 它不再正确加载 这是在我更改一行代码后发生的 当我尝试加载包 需要 时 包开始加载 然后 setdelayed 定义之一 活跃起来 即以某种方式进行评估 被困在之前加载几行的错误捕获例程中 并且包加载中止 使用 ab

随机推荐

  • 防止 UIWebView 内出现烦人的 HTML5 地理位置警报

    每当脚本请求地理位置时 使用HTML5的地理定位 API UIWebView请求使用 iOS 定位服务的权限 这非常烦人 特别是当您加载静态时HTML文件时 它会不断询问每个文件的权限 即使用户已经为应用程序本身授予了此权限 有办法预防吗
  • Datatable:日期/时间排序插件未排序

    我有一个基本的 Spring Boot 应用程序 嵌入式 Tomcat Thymeleaf 模板引擎 我想订购数据表的 1 个日期列 在我的 POJO 中 public String getTimeFormatted DateTimeFor
  • ContentResolver.query() 方法抛出“无效令牌限制”错误

    内部版本号为 RQ1A 201205 003 或更高版本的 Pixel 设备上会出现以下错误 我想知道错误的原因以及如何处理 这是错误还是规格更改 code ContentResolver resolver getContentResolv
  • Visual Studio C++ Link1104无法打开文件MSVCURTD.lib

    我已经在 Visual Studio 2017 社区中打开了一个用 Visual Studio 2012 Express 用 C 编写 制作的项目 当我尝试编译时出现以下错误 LINK1104 无法打开文件 MSVCURTD lib 如果我
  • 重播 GIF 动画/单击时重新加载 GIF

    我有一个很大的 GIF 动画 我让它显示一个加载图标 直到 GIF 加载完毕 加载后就会显示 GIF 效果很好 但我想添加一个 重播 按钮来触发 GIF 重播 重新加载 加载和GIF的代码 HTML div class loading im
  • Linq to Entities 删除

    是否有内置方法可以使用主键通过 Linq to Entities 进行删除 目前的解决方法是创建一个名为DeleteTable的存储过程 表是表名 然后在 C LINQ To Entities 中我只需执行 context DeleteTa
  • 如何在 Appveyor 构建之前运行 VCUpgrade?

    我们分发了一组 Visual Studio 2010 项目文件 用户应该根据自己的口味进行升级 我们的 appveyor yml file http github com weidai11 cryptopp blob master appv
  • R Shiny with Leaflet - 单击后更改标记的颜色

    我正在开发一个闪亮的应用程序 它显示带有标记的传单地图 标记是可点击的 我收集被点击标记的 ID 但我还想更改单击标记的颜色 当标记为蓝色时 它应更改为红色标记 反之亦然 到目前为止 我已经有了跟踪单击的标记的代码 并且可以将 ID 存储在
  • 什么会导致 %5B0%5D 添加到 url

    我试图找出为什么删除过滤器的链接在我的网站上不起作用 似乎是因为链接已更改为包含 5B0 5D 和其他各种字母和数字 并添加了 据我所知 这是序列化函数导致的 还有其他什么可能导致这种情况 或者它绝对是序列化函数吗 它被称为百分比编码 ht
  • 在 netbeans 中运行 Web 应用程序

    我正在使用 netbeans 和 apache tomcat 来运行 Web 应用程序 我不断收到此错误 In place deployment at C WorkingDirectory Projects GreenWheelsProje
  • 从 iTunes Connect 中删除新的应用程序版本

    我在 iTunes Connect 中使用错误的版本号创建了应用程序的新版本 我想删除处于 准备上传 状态的新版本 我该怎么做呢 关于此还有其他问题 但他们没有提供任何答案 适用于已上传二进制文件的版本 或者已过时 我就此向 Apple 提
  • 在 C++ 中提供指针恒定视图的更好方法

    我有一个类必须返回一个constant一些指向软件上层的指针的视图 在内部 指针必须是非常量 因为类需要在内部操作对象 我没有看到任何选项可以在不复制所有指针的情况下向更高级别的客户端提供指针的常量视图 这看起来很浪费 如果我管理数百万个对
  • 如何连接到 TT X_TRADER API 以使用 python 创建自动交易系统?

    我已经在内部开发论坛中多次看到这个问题 因此想提供一个快速示例 说明如何立即在 python 中实现这一点 首先 请注意 我们所做的只是连接到相关的 X TRADER com 对象 因此以下所有内容仍然适用 https www tradin
  • 如何将复选框与文本对齐到屏幕右侧?

    我里面有一个复选框TableRow 我想将复选框和文本对齐到屏幕的右侧 但是当我使用android gravity right 它仅将文本与屏幕右侧对齐 但不与正方形 复选框本身 对齐 它们似乎是单独对齐的 复选框位于屏幕的左侧 文本位于屏
  • 具有不同函数原型的函数查找表

    除了一系列之外 根据用户输入调用指定函数的最佳方法是什么 if and strcmp 例如 p 2 2 gt call func p 2 2 a 8 gt call func a 7 m gt call func m void 我知道制作一
  • 使用 javascript 或 jQuery 隐藏所有带有与数字“0”或自定义值匹配的文本或innerHTML的“a”元素

    我需要隐藏全部 a 带有文本或的元素innerHTML匹配数字 foo 或使用 javascript 或 jQuery 的自定义值 li a href class dir foo a li 我努力了 jQuery document read
  • 为什么Python列表排序后速度变慢?

    在下面的代码中 我创建了两个具有相同值的列表 一个列表未排序 s not 另一个列表已排序 s yes 这些值由 randint 创建 我为每个列表运行一些循环并计时 import random import time for x in r
  • Rails 5 渲染部分并传递数据

    我无法了解数据传递和提供给部分数据的一般方式 例如 我有一个控制器将实例变量传递给呈现部分的模板 static pages controller rb def home feed items current user feed end ho
  • Cobra + Viper Golang 如何测试子命令?

    我正在使用 Go 开发一个网络应用程序 到目前为止一切顺利 但现在我将 Wercker 集成为 CI 工具并开始关心测试 但我的应用程序严重依赖 Cobra Viper 配置 标志 环境变量方案 并且我不知道如何在运行测试套件之前正确初始化
  • Mathematica 中稀疏数组的 Outer 有效替代方案?

    假设我有两个非常大的列表 a1 a2 和 b1 b2 其中所有 ai 和 bj 都是大型稀疏数组 为了提高内存效率 我将每个列表存储为一个综合稀疏数组 现在我想在所有可能的 ai 和 bj 对上计算某个函数 f 其中每个结果 f ai bj