Любой простой вопрос для экспертов Mathematica здесь:
Имея список, скажем
Clear[a, b, c];
data = {a, b, c};
, и я хочу получить обратно все списки длины 1,2,3,...Length[data]
, начиная с начала и доконец, так что я получаю следующее для вышеупомянутого
out = {{a}, {a, b}, {a, b, c}}
Я посмотрел на команды в M, чтобы найти готовую для использования, и я мог (посмотрел на все функции Map и Nest *,но не то чтобы я видел как использовать для этого).Я уверен, что это там, но я не вижу его сейчас.
сейчас я делаю этот глупый цикл Do, чтобы построить его
m=Length[data];
First@Reap[Do[Sow[data[[1;;i]]],{i,1,m}]][[2]]
{{a},{a,b},{a,b,c}}
вопрос в том: есть ли у Mathematicaвстроенная команда для выполнения вышесказанного?
обновление 8 часов утра
Я удалил тесты, которые я выполнил несколько часов назад и буду делать репостих снова скоро.Мне нужно запустить их несколько раз и взять среднее значение, так как это лучший способ сделать этот тест производительности.
обновление 9 утра
Хорошо, я перестал- запустить тесты производительности для всех решений, показанных ниже.8 методов.Для каждого метода я запускаю его 5 раз и получаю среднее значение.Я сделал это для n={1000, 5000, 10000, 15000, 25000, 30000}
, где n - длина исходного списка для обработки.
не может превышать 30000, будет исчерпан оперативной памяти.У меня только 4 ГБ оперативной памяти.
Я сделал небольшую функцию под названием makeTable[n, methods]
, которая генерирует таблицу производительности для конкретных n
.тестовый код приведен ниже (написан быстро, поэтому не самый чистый код, не очень функциональный, как я должен идти :), но он ниже, и любой может его изменить / очистить и т. д. ... если они хотят
заключение: метод Кгулера был самым быстрым, метод Тиса почти одинаков для больших n (30 000), поэтому для всех практических целей может быть методы Тисса и Кгулера могут быть объявлены победителями для большихп?Но поскольку Kguler также является самым быстрым для малых n, он до сих пор получает четкое преимущество.
Опять же, ниже приведен тестовый код для любого, чтобы проверить и запустить, чтобы посмотреть, не мог ли я где-нибудь сделать ошибку.Как правильно предсказал Леонид, метод связанного списка не слишком хорошо подошел для большого n.
Я думаю, что нужно больше тестов, так как только взятие среднего из 5 может быть недостаточно, и другие соображения, которые я мог бы иметьпропущенный.Это не точный тест, просто грубый, чтобы понять.
Я старался не использовать ПК во время выполнения тестов.Я использовал AbsoluteTiming [] для измерения процессора.
Вот снимок экрана сгенерированных таблиц
Вот код теста:
methods = {nasser, wizard1, wizard2, wizard3, kguler, leonid1,
leonid2, thies};
AppendTo[$ContextPath, "Internal`"];
ClearAll[linkedList, leonid2];
SetAttributes[linkedList, HoldAllComplete];
nasser[lst_] := Module[{m = Length[lst]},
First@Reap[Do[Sow[lst[[1 ;; i]]], {i, 1, m}]][[2]]
];
wizard1[lst_] := Module[{},
Take[lst, #] & /@ Range@Length@lst
];
wizard2[lst_] := Module[{},
Table[Take[#, i], {i, Length@#}] & @lst
];
wizard3[lst_] := Module[{},
Rest@FoldList[Append, {}, #] & @lst
];
kguler[lst_] := Module[{},
Reverse@NestList[Most, #, Length[#] - 1] & @lst
];
leonid1[lst_] := Module[{b = Bag[{}]},
Map[(StuffBag[b, #]; BagPart[b, All]) &, lst]
];
leonid2[lst_] := Module[{},
Map[List @@ Flatten[#, Infinity, linkedList] &,
FoldList[linkedList, linkedList[First@lst], Rest@lst]]
];
thies[lst_] :=
Module[{},
Drop[Reverse@
FixedPointList[If[Length[#] > 0, Most, Identity][#] &, lst], 2]
];
makeTable[n_, methods_] :=
Module[{nTests = Length[methods], nTries = 5, i, j, tests, lst},
lst = Table[RandomReal[], {n}];
tests = Table[0, {nTests}, {nTries}];
For[i = 1, i <= nTests, i++,
For[j = 1, j <= nTries, j++,
tests[[i, j]] = First@AbsoluteTiming[methods[[i]][lst] ]
]
];
tbl = Table[{ToString[methods[[i]]], Mean[ tests[[i, All]] ]}, {i,
nTests}] ;
Grid[Join[{{"method", "cpu"}}, tbl],
Frame -> All, FrameStyle -> Directive[Thickness[.005], Gray],
Spacings -> {0.5, 1}
]
];
Теперь, чтобы запустить, сделайте
makeTable[1000, methods]
Предупреждение, не пытайтесь делать что-то более 30000, если у вас есть миллиард ГБ, иначе M может не вернуться.Это случилось со мной, и пришлось перезагрузить компьютер.
обновление 26.12.11 15:30 * * * * * * * * * * Я вижу, что у Thies более новая версия этого алгоритма(Я назвал это thies2 в таблице методов), поэтому я снова все запустил, вот обновленная таблица, я удалил версию связанного списка, поскольку заранее известно, что она не будет быстрой для больших n, и на этот раз язапустить их каждый 10 раз (не 5, как указано выше), а затем взял среднее значение).Я также запустил M заново, используя заводские настройки (перезапустил его, удерживая клавиши Alt-Shift, чтобы на всякий случай все настройки вернулись к исходным настройкам)
вывод пока
Куглер является самым быстрым для меньшего n, то есть n <20000.Для больших n теперь вторая версия Thies быстрее, чем первая версия Thies, и теперь она значительно опережает метод Куглера для больших n.Поздравляем Thies, текущий лидер в этом тесте производительности.Но для практических целей я бы сказал, что методы Thies и Kugler являются самыми быстрыми для больших n, а Kugler остаются самыми быстрыми для меньших n. </p>
Ниже приведены таблицы и обновленный тестовый код под ними.Любой может свободно запускать тесты для себя, на случай, если я что-то упустил.
Текущий код теста:
$MinPrecision = $MachinePrecision;
$MaxPrecision = $MachinePrecision;
methods = {nasser, wizard1, wizard2, wizard3, kguler, leonid, thies1,
thies2};
AppendTo[$ContextPath, "Internal`"];
nasser[lst_] := Module[{m = Length[lst]},
First@Reap[Do[Sow[lst[[1 ;; i]]], {i, 1, m}]][[2]]
];
wizard1[lst_] := Module[{},
Take[lst, #] & /@ Range@Length@lst
];
wizard2[lst_] := Module[{},
Table[Take[#, i], {i, Length@#}] & @lst
];
wizard3[lst_] := Module[{},
Rest@FoldList[Append, {}, #] & @lst
];
kguler[lst_] := Module[{},
Reverse@NestList[Most, #, Length[#] - 1] & @lst
];
leonid[lst_] := Module[{b = Bag[{}]},
Map[(StuffBag[b, #]; BagPart[b, All]) &, lst]
];
thies1[lst_] :=
Module[{},
Drop[Reverse@
FixedPointList[If[Length[#] > 0, Most, Identity][#] &, lst], 2]
];
thies2[lst_] :=
Module[{},
Drop[Reverse@
FixedPointList[If[# =!= {}, Most, Identity][#] &, lst], 2]
];
makeTable[n_Integer, methods_List] :=
Module[{nTests = Length[methods], nTries = 10, i, j, tests, lst},
lst = Table[RandomReal[], {n}];
tests = Table[0, {nTests}, {nTries}];
For[i = 1, i <= nTests, i++,
For[j = 1, j <= nTries, j++,
tests[[i, j]] = First@AbsoluteTiming[methods[[i]][lst] ]
]
];
tbl = Table[{ToString[methods[[i]]], Mean[ tests[[i, All]] ]}, {i,
nTests}] ;
Grid[Join[{{"method", "cpu"}}, tbl],
Frame -> All, FrameStyle -> Directive[Thickness[.005], Gray],
Spacings -> {0.5, 1}
]
];
Для запусканаберите
n=1000
makeTable[n, methods]
Спасибо всем за ответы, я учился у всех.