Как именно должна быть построена такая таблица диспетчеризации?
Скажем, у вас есть граф (сеть), состоящий из n
вершин в цикле:
In[1] := rules =
With[{n = 1000},
Table[ToString@i -> ToString@Mod[i + 1, n],
{i, 0, n - 1}]];
Вы хотите пройти по графу, применив эти правила перезаписи к начальной вершине. Вы можете выполнить один шаг с помощью i /. rules
, но при этом выполняется линейный поиск по rules
, пытаясь найти Rule
с lhs, который соответствует выражению i
. Поэтому применение правил много раз происходит медленно:
In[2] := Nest[# /. rules &, 0, 10000] // AbsoluteTiming
Out[2] = {1.7880482, 0}
Mathematica Dispatch
позволяет нам предварительно вычислить хеш-таблицу, которая превращает линейный поиск в поиск с постоянным временем:
In[3] := dispatch = Dispatch[rules];
Многократное применение таблицы диспетчеризации приводит к получению одинаковых порядков ответов быстрее:
In[4] := Nest[# /. dispatch &, 0, 10000] // AbsoluteTiming
Out[4] = {0.0550031, 0}
В каких случаях такой подход рекомендуется?
Когда:
Вы делаете много переписываний с одним и тем же набором правил перезаписи, и
Набор правил перезаписи содержит не менее 30 правил с постоянными шаблонами lhs, т.е. составленными только из символов, последовательностей и литералов.
Как это действительно работает?
Он просто создает хеш-таблицу с постоянными шаблонами в качестве ключей.
Существуют ли другие способы оптимизации основного цикла?
Наиболее эффективный общий подход - переписать правила на другом языке. В частности, языки семейства ML (SML, OCaml и F #) имеют очень эффективные компиляторы сопоставления с образцом и сборщики мусора, поэтому они могут переписывать термины гораздо быстрее, чем переписчик общего назначения Mathematica.