Pull to refresh
2
0
Send message
Ваш стиль задач и формулировок похож на задачи с codility.com, только там больше упор на данные+алгоритмы и оценки сложности.

А задача про отвесную скалу видимо тестирует готовность к разговору в духе «что вы называете решением и о чем еще умолчали в условии»?
виртуально жму руку. Тоже пытался использовать LaTeX для необычных задач (верстка художественных книг, попытка следовать всем стандартам отечественной типографики) и тоже натыкался на принципиальные ограничения, вроде локальной оптимизации плохостей в масштабе одной страницы, а не всего документа.
Признаюсь честно, по ссылке еще не ходил, но на всякий случай: было бы здорово к коллективной работе привинтить latexdiff.
В данном случае доверие абсолютное (близкий родственник), но картины мира/степень конформизма отличаются, убедить ее на войну с привлечением прокуратуры будет очень сложно. Но спасибо за идею. Если не лень, подскажите как найти норму, по которой налоговая должна по первому требованию закрывать.

Сначала вся отчетность была сдаваема вовремя, но когда пришел закрывать ИП, мне сказали «ну, камеральная проверка, ну, полтора месяца, ну а потом… » (в сумме месяца три набралось). Говорили причем не тетки за стойкой, которые процедуру понимают только в терминах, заданных начальством, а грустные опытные дамы из их back office, к которым я набравшись наглости пробрался, вопреки тамошней субординации. От меня тетки ничего не хотели, так что пришлось поверить. За давностью лет уже плохо помню детали.
Увы, живу не в России, сходить в прокуратуру физически не смогу. Забыл уточнить, доверенное лицо — главбух в достаточно крупной бюджетной конторе, человек со стажем и опытом, как общаться с тетками из налоговой знает. Но тут проблема не только неадекватности налоговой, несданная отчетность копится сама собой, стоит не закрыть ИП сразу. А каждая такая не вовремя данная бумага увеличивает неадекватный ответ системы.
Вы видимо в параллельном мире живете. В налоговой Центрального района города Красноярска такой фокус не пройдет. Будете пешком туда ходить как на работу, увы.
Проблема например в том, что закрыть ИП — отдельная песня с припевом. Это не в пять минут делается, зато бывают жизненные обстоятельства, при которых хочется ИП закрыть быстро.

Мой пример: был зарегистрирован как ИП в Красноярске, но решил уехать из города. За несколько месяцев до отъезда сунулся в налоговую и понял, что банально не успею пройти все круги ада до отъезда. Затем лет пять это ИП за мной числилось, копилась несданная отчетность + отчисления в пенсионный фонд. В конце концов доверенное лицо от моего имени закрывало ИП в течение года. Ибо: камеральные проверки (ЛОЛЧТО?), заполнение отчетности по УСН в какой-то наколенно-писаной программе, которую распространяют на CD/дискетах тетеньки в налоговой, и попробуй заполни анкеты в этой программе не той версии, и тому подобный бред.

Нет, лучше уведомительная процедура и возможность работать без создания дополнительных бюрократических сущностей.
И этот аргумент хорош. Не будешь же все возможные мотивы перечислять :)
Ага. Так если это студенческий интерес, можно пойти дальше и сделать исследовательский проект: сравнить производительность/границы применимости вашего кода на Хаскеле с более стандартными средами типа singular, macaulay2 и пакетами из Maple/Mathematica. Зачем: вам — возможность сказать в своем CV
— я изучил такие-то среды, знаю как работают,
— может даже статью тиснуть,
а кроме того такое сравнение представляет интерес для людей из computer algebra сообщества: там постоянно нужно посчитать что-то большое, на что ресурсов не хватает, и у математиков есть предрассудок (частично обоснованный), что если машина за 5 минут не посчитала, то и смысла возиться нет. Часто возникает мысль «вот взял бы нормальный язык программирования вместо этого DSL внутри Maple и посчиталось бы в разы быстрее», но мало кто пробовал и еще меньше людей о своем опыте рассказывало.
Понимаю, что этот вопрос к данному посту скорее оффтопик и виртуально пожимаю руку за самоотверженность, но все же вопрос задам: чем было продиктовано решение реализовывать вычисления самостоятельно и не пользоваться готовым (singular, macaulay2 etc)?

На всякий случай — я вполне понимаю аргумент «пробовали, было слишком медленно/памяти не хватило», самому приходилось идти нестандартными путями.
Да, но компиллятор и этого не может, у него задача совсем другая.

Кроме того, задача символьного интегрирования в общем случае не решена (да и как его определить, общий случай), и решение для каждого класса подинтегральных выражений строится по-разному. Нужно сперва определиться с классом подинтегральных функций, затем смотреть, решена эта задача в том или ином пакете.
Вы пожалуйста определитесь: спрашивать, или минусовать.
Если я правильно понял ваше затруднение с рядами Тейлора/Лорана в том смысле, что вы на бегу не увидели, умеет ли ginac дифференцировать, эта ссылка может помочь: www.ginac.de/tutorial/Symbolic-differentiation.html
Не смогу сейчас детально прокомментировать Ev3, сам с ним разбирался полдня. Первые четыре ссылки и правда только на парсеры готовых выражений, но зато они (по крайней мере некоторые) решают задачу «дано фиксированное выражение, быстро и много раз посчитай значение в точке». Можно символьные манипуляции проводить одним движком, а вычисление — другим. Согласен, выглядит странно — но другого готового решения я не знаю.

Чур меня, вот предлагать использовать Maple для этой задачи я точно не собирался. Его я использовал лишь как пример того, что задача счета N-й производной — одно из базовых свойств почти любого движка компьютерной алгебры.

В общем и целом, вы написали именно ту схему решения, которую я предлагал — я рад, что по крайней мере есть общее понимание. Необходимость подставок предопределена взаимозависимостью двух численных задач, от них никуда не уйти в сопряженных задачах (adjoint problems). Решение топикстартера тоже подразумевает подстановку исходной функции в ее производную, когда выполняется f += (update) c переменной f типа Derivable.

Что можно улучшить? Можно продифференцировать выражение один раз, объявить это одним символьным объектом, а в diff1 и diff2 заниматься только подстановками, причем сразу подставив значение неизменяемых констант (например, dx), до interpreter.evalute(). Так получится сократить объем выполняемого байт-кода в горячем цикле.

Вы вольны принимать решения о дизайне вашего кода. Моей задачей было рассказать об альтернативном решении. Считаете, что так вы больше рискуете — ну, ок, ваше решение. Мне же кажется, что так вы явно отделяете сущности и пишете код более близким к его математическому смыслу. Тем оно и удобнее, и безопаснее в смысле адаптации к новым задачам.
компиллятор выполнит это вычисление, нет проблем. Как насчет интеграла от функции?
Еще раз подчеркиваю, что весь мой код с interpreter условный, потому что нужно сперва определиться с инструментарием, затем четко ему следовать. Я вам накидал ссылок — вы почитали, определились?

Вы правы в том, что нужно как-то явно объявить зависимость от a. Способ такого объявления зависит от движка.

Вторую производную вы тут посчитаете так:
... diff((k*dx-f(a)*f(a))*dx,a,a)...

(сейчас использую аналог синтаксиса Maple, в общем случае зависит от движка)
Да, достаточно будет одного вызова вида

interpreter.evaluate(
 "foo = (x,y)->piecewise(x*x-y, x < y, y*y -x, x>=y);" +
 "bar = (x,c)->sin(x / c) * c / x;" +
 "foo(x, Q * x / 2)/bar(x / t, c)");


для задания аналитической функции, которая у вас заняла 12 строк, включая объявления С++ функций.
Так вы бы с задачи начали — и этого разговора могло б не произойти.

И вторая производная там же есть, и все, что надо. И, как верно Mrrl написал ниже, добавить код для вычисления второй производной элементарных функций достаточно просто. Ну или воспользоваться Derivable<Derivable >, что еще проще

Итак, вы согласились с необходимостью рефакторинга.

— композиция функций и другие естественные
конструкции
С этим разобрались.


Нет, не разобрались. Как насчет естественной конструкции посчитать интеграл от функции? Если такая задача встанет, вам придется добавлять код численного интегрирования. В предлагаемом подходе — изменить формулу один раз.

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


Да, это возможный сценарий — исправить формулу в одном месте. С другой стороны, объект символьного движка копируем — зачем в двух местах держать одну и ту же формулу?

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


Если вы об этом примере

Derivable foo(Derivable x, Derivable y) {
    if (x < y) return x * x - y;
    else return y * y - x;
}

Derivable bar(Derivable x, Derivable c) {
    return sin(x / c) * c / x;
}

Derivable f(Derivable x, Derivable  Q, Derivable t) {
    Derivable u = foo(x, Q * x / 2);
    Derivable v = bar(x / t, constants::c); // скорость света
    return u / v;
}

// Вызывать так:
// Derivable f0 = f(Derivable::IndependendVariable(x0), Q, t)


то ответом будет: символьный движок позволяет записать несколько символьных выражений за одну «сессию» + поддерживать кусочно определенные функции. Так вы еще и от С++ синтаксического сахара избавитесь в виде функций foo и bar.

Наконец, вы не видите разницы между

interpreter.evaluate("cos(x^2)+x^3-sqrt(x)", "x = 1");

и
xd = Derivable::IndependendVariable(x);
return cos(xd * xd) + xd*xd*xd - sqrt(xd);


А как насчет
interpreter.evaluate("int(cos(x^2)+x^3-sqrt(x),0,y", "y = 1");

? Имеется ввиду интеграл с переменным верхним пределом.
в моем исходном комментарии я задавался вопросом о том, какова постановка задачи: и математически, и с точки зрения дизайна кода. Я до сих пор четкого ответа не услышал, мне три комментатора сейчас отвечают так, словно я эту постановку задачи уже слышал, но не принял к сведению.

Если задача стоит «есть много готового кода, надо один раз добавить фичу», то все что я тут пишу, разумеется, нерелевантно. Если перед вами задача периодически добавлять математический функционал, причем функционал может быть сколь угодно сложным, то предлагаемый мной класс решений по крайней мере стоит рассмотреть. Вы в посте писали про сложное моделирование, это и послужило для меня мотивацией.

Основное достоинство символьного пакета не только в том что он есть, но и в том, что он заведомо реализует продвинутый математический функционал, который вам реализовывать вручную очень дорого. Это оправдывает его использование, если есть потребность в таком функционале. А вот есть потребность или нет — опять возвращаемся к постановке задачи, которую вы явно и не описали.
если функция исходно задается аналитически, то добавить вычисление второй производной — одна строчка. Если аналитической формы нет — тогда увы. Собственно, ради этого я с самого начала спрашивал математическую постановку задачи. Без нее неясно, есть у вас неаналитически заданные функции или нет.

На последний вопрос — ответ да. Байт-код, вычисляющий вторую производную будет инкапсулирован в объекте symbolic_iteration ровно так же, как и байт-код, вычисляющий первую производную. Вам только предстоит поменять строчное представление формулы, передаваемой символьному движку.

Information

Rating
Does not participate
Location
Великобритания
Works in
Date of birth
Registered
Activity