Эффективность стекового вычисления выражения для математического парсинга

Я должен записать в академических целях, приложение, которое выводит выражения ввода данных пользователем на печать как: f (x) = 1 - exp (3^ (5*ln (cosx)) + x)

Подход, который я принял решение записать синтаксическому анализатору, должен преобразовать выражение в RPN с алгоритмом Сортировочной станции, рассматривая примитивные функции как "cos" как унарные операторы. Это означает, что функция, записанная выше, была бы преобразована в серии маркеров как:

1, x, cos, ln, 5, *,3, ^, exp, -

Проблема состоит в том, что для графического изображения функции я должен оценить его, много времен, так применяя алгоритм оценки стека для каждого входного значения было бы очень неэффективно. Как я могу решить это? Я должен забыть идею RPN?

7
задан Dave Danuve 10 February 2010 в 19:39
поделиться

7 ответов

Сколько это "МНОГО раз"? Миллион?

Какие функции могут быть введены? Можем ли мы предположить, что они непрерывны?

Вы пробовали измерить, насколько хорошо работает ваш код?

(Извините, начал с вопросов!)

Вы можете попробовать один из двух подходов (или оба), описанных вкратце ниже (возможно, их гораздо больше):

1) Деревья разбора.

Вы можете создать дерево разбора. Затем сделать то, что делает большинство компиляторов для оптимизации выражений, сворачивание констант, устранение общих подвыражений (чего можно достичь, соединяя вместе общие поддеревья выражений и кэшируя результат) и т.д.

Затем вы можете использовать технику ленивой оценки, чтобы избежать целых поддеревьев. Например, если у вас есть дерево

    *
   / \
  A   B

где A оценивается в 0, вы можете полностью избежать оценки B, поскольку вы знаете, что результатом будет 0. В RPN вы потеряете возможность ленивой оценки.

2) Интерполяция

Предполагая, что ваша функция непрерывна, вы можете аппроксимировать ее с высокой степенью точности, используя полиномиальную интерполяцию. Таким образом, вы можете выполнить сложное вычисление функции несколько раз (в зависимости от степени полинома, который вы выбрали), а затем выполнять быстрые полиномиальные вычисления в остальное время.

Для создания начального набора данных вы можете использовать подход 1 или просто использовать RPN, так как вы будете генерировать только несколько значений.

Таким образом, если вы используете интерполяцию, вы можете оставить RPN...

Надеюсь, это поможет!

3
ответ дан 7 December 2019 в 05:22
поделиться

Мне кажется, что в реализации nftw на linux что-то не так.

Я подал сообщение об ошибке, см. здесь

UPDATE : Исправление доступно в репозиториях glibc.

-121--4950489-

Я просто должен был это сделать. Вот как я это сделал.

$('#elementid').fancybox({
   onStart : function() {
      $.post($(this).attr('href'), $('#formid').serialize());
   }
});

Таким образом вы можете отправить форму и вызвать fancybox все в одном кадре. Он отправляет форму ajax style. Кнопка «» Отправить «» должна находиться в тэге < a >.

Надеюсь, что это поможет.

-121--1699600-

Зачем изобретать колесо заново? Вместо этого используйте быстрый язык сценариев. Интеграция чего-то вроде lua в ваш код займет очень мало времени и будет очень быстрой.

Обычно вы можете компилировать выражение байтом, и это должно привести к тому, что код будет выполняться очень быстро, конечно, достаточно быстро для простых 1D графиков.

Я рекомендую lua как быстрый и интегрируется с C/C + + проще, чем любой другой язык сценариев. Еще одним хорошим вариантом был бы питон, но, хотя он более известен, мне было сложнее интегрироваться.

2
ответ дан 7 December 2019 в 05:22
поделиться

В каком смысле неэффективен? Есть машинное время и время программиста. Есть ли стандарт того, насколько быстро он должен работать с определенным уровнем сложности? Что важнее - завершить задание и перейти к следующему (перфекционисты иногда никогда не заканчивают)?

Все эти шаги должны выполняться для каждого входного значения. Да, у вас может быть эвристика, которая сканирует список операций и немного его очищает. Да, вы можете скомпилировать некоторые из них до сборки вместо того, чтобы вызывать +, * и т. Д. Как функции высокого уровня. Вы можете сравнить векторизацию (выполнение всех +, затем всех * и т. Д. С вектором значений) с выполнением всей процедуры для одного значения за раз. Но нужно ли вам это?

Я имею в виду, что, по вашему мнению, произойдет, если вы построите функцию в gnuplot или Mathematica?

0
ответ дан 7 December 2019 в 05:22
поделиться

Почему бы не держать вокруг дерево разбора (я использую "дерево" свободно, в вашем случае это последовательность операций), и соответственно помечать входные переменные? (например, для входов x, y, z и т.д. пометить "x" 0 для обозначения первой входной переменной, "y" 1 для обозначения второй входной переменной и т.д.)

Таким образом, вы можете разобрать выражение один раз, сохранить дерево разбора, взять массив входов и применить дерево разбора для оценки.

Если вы беспокоитесь о производительности шага оценки (по сравнению с шагом разбора), я не думаю, что у вас получится намного лучше, если только вы не займетесь векторизацией (применение дерева разбора к вектору входных данных одновременно) или жестким кодированием операций в фиксированной функции.

1
ответ дан 7 December 2019 в 05:22
поделиться

Как насчет :

Это достаточное условие может быть ослаблено, как обсуждалось ниже в разделе Выборка сигналов без основной полосы частот.

Более поздние утверждения теоремы иногда осторожны, чтобы исключить условие равенства; то есть условие заключается в том, что x (t) не содержит частот, превышающих или равных В; это условие эквивалентно условию Шеннона, за исключением тех случаев, когда функция включает в себя устойчивую синусоидальную составляющую с точной частотой B.

-121-3702229-

У меня есть веб-страница с парой многоагентных симуляций netlogo . Я использую netlogo для преподавания, и я обнаружил, что, как только вы преодолеваете кривую обучения, вы можете разрабатывать симуляции удивительно быстро. То, что займет 80 человеко-часов в других так называемых агентских средах (Jade, Repast, которые действительно в основном являются просто библиотеками программирования), может быть сделано за 2 часов.

С другой стороны, netlogo на самом деле не подходит для моделирования, которое требует огромного количества деталей, например, имитация сети на всем пути от TCP/IP до HTTP. Это просто потребует большого количества кода, независимо от языка программирования, и netlogo в настоящее время отстой, если ваша программа в конечном итоге больше, чем 10 страниц. Сказав это, большинство людей были бы поражены тем, что можно сделать на 10 страницах кода netlogo.

-121--2774053-

Для создания RPN используется алгоритм шунтирования. Затем я «компилирую» RPN в маркированную форму, которая может быть выполнена (интерпретированно) повторно без повторного анализа выражения.

1
ответ дан 7 December 2019 в 05:22
поделиться

Ваша простая интерпретация RPN должна работать нормально, тем более что она содержит

  • математических библиотечных функций, таких как cos , exp и ^ (pow , включая журналы)

  • поиск в таблице символов

Надеюсь, ваша таблица символов (с такими переменными, как x) будет короткой и простой.

Библиотечные функции, скорее всего, отнимут у вас больше всего времени, поэтому, если ваш интерпретатор не написан плохо, это не будет проблемой.

Если, однако, вы действительно хотите ускорить процесс, вы можете перевести выражение в код C, скомпилировать и связать его с DLL на лету и загрузить (занимает около секунды) . Это, плюс мемоизированные версии математических функций, может дать вам лучшую производительность.

P.S. Для синтаксического анализа ваш синтаксис довольно ванильный, поэтому простой парсер с рекурсивным спуском (около страницы кода, O (n) такой же, как маневровая площадка) должен работать нормально. Фактически, вы могли бы просто вычислить результат во время синтаксического анализа (если математические функции занимают большую часть времени), и не беспокоиться о деревьях синтаксического анализа, RPN и т. Д.

0
ответ дан 7 December 2019 в 05:22
поделиться

Майкл Андерсон предложил Lua . Если вы хотите попробовать Lua только для этой задачи, посмотрите мою библиотеку ae .

1
ответ дан 7 December 2019 в 05:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: