Функциональный программист
12,8
рейтинг
19 ноября 2013 в 17:33

Разработка → Программирование в уравнениях из песочницы

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

Некоторые сложности обнаруживаются в ленивых языках:

fib = 1:1:(zipWith (+) fib (tail fib))


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

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

Но есть язык, в котором уравнения являются важнейшей частью — это Modelica.

model Point
 Real x,y;
equation
end Point;

model Line
 parameter Real len;
 Point p1,p2;
equation
 len = (p1.x-p2.x)^2 + (p1.y-p2.y)^2;
end Line;


Здесь отрезок определяется как координаты концов и длинна, при этом длина и координаты связаны очевидным уравнением.

(К сожалению, source такого языка не знает, а вставить раскрашенный pygment-ом html не получается.)

Естественно, уравнения могут быть объединены в систему:

model Hand
  Point ph,pl;
  parameter Real l1,h1,l2,h2;
  Line ll1(len = l1),lh1(len = h1),ll2(len = l2),lh2(len = h2);
  Real arcl,arch;
  Point p;
equation
  ll1.p1 = pl;
  lh1.p1 = ph;

  ll1.p2.x = pl.x + l1 * arcl;
  lh1.p2.x = ph.x + h1 * arch;

  ll1.p2 = ll2.p1;
  lh1.p2 = lh2.p1;

  p = ll2.p2;
  p = lh2.p2;
end Hand;


Здесь описывается манипулятор, состоящий из четырех соединенных шарнирами реек управляемый двумя сервоприводами.

Как следует из названия, Modelica предназначена для моделирования сложных, гетерогенных систем. Ее реализации есть у знаменитого Вольфрама, производителя САПР (не путать и «чертежными программами») CATIA. Есть также и свободные реализации, такие как OpenModelica.

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

В качестве примера приведу модель очень сложной гибридной электромеханической системы — Гауссгана:

model Gauss
  extends Modelica.Electrical.Analog.Interfaces.OnePort;
  Real x (start = -1);
  Real sp (start = 0);
  Real co;

  Real pw (start = 0);
  Real ke;
  Real se;
  Real pe;
equation
  der(pw) = i*v;
  ke = sp^2/2;
  se = i^2/2;
  pe = pw - ke - se;

  co = (if abs(x) > 0.2 then (abs(x)*(x^(-5))/3.0) else (x/((0.2^5)*3.0)));
  der(sp) = -co * i;
  der(x) = sp;
  der(i) = v + (co * sp);
end Gauss;

model Main
 Modelica.Electrical.Analog.Basic.Ground g;
 Modelica.Electrical.Analog.Sources.ConstantVoltage ps;
 Modelica.Electrical.Analog.Basic.Resistor rps;

 Gauss gun;

equation
 connect(ps.p, g.p);
 connect(ps.p, gun.p);
 connect(ps.n, rps.p);
 connect(rps.n, gun.n);
end Main;


Здесь x — координата снаряда, v — напряжение, i — ток. Для отладки вычисляется полная энергия pe — ее график будет горизонтальной прямой.

Кроме текстового представления программы, в Modelica стандартизовано и графическое (хотя лично я предпочитаю работать с текстом). Для повторного использования кода применяется знакомое многим по ООП наследование. Есть обширные библиотеки по электротехнике, теплотехнике, механике и, даже, биохимии.

Разработчики «Моделик» не расчитывают охватить все одной системой — большинство реализаций допускает комоделирование с помощью Functional Mock-up Interface. При желании этот же интерфейс можно задействовать для взаимодействия с внешним миром, но это пока открытая область.
Михаил Потанин @potan
карма
29,5
рейтинг 12,8
Функциональный программист
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (17)

  • +8
    Извините, но ваш код оформлен несколько странно. Что за говорящие названия ll1, lh1, ll2, lh2? Что такое sp, co? Для модели гаусгана очень хотелось бы увидеть формулы, реализованные в модели — это кратно бы повысило читаемость и понимаемость кода.
    И, мне кажется, Modelica сложно назвать языком программирования, это язык моделирования.
    • +1
      IMHO, грань между программированием и моделированием очень тонкая, если вообще существует. Та же модель может управлять реальным устройством. Или не реальным, а торговать на бирже, например.

      С именованием у меня проблемы. Как придумаю нормальные имена обещаю исправить :-).
      l[lh][12] — это длины реек.
      co — коэфициент зависимости тока через катушку и ускорением снаряда. sp — скорость.

      Гауссган в этой модели ускоряет постоянный магнит. При расстоянии до соленоида большем 0.2 сила притяжения обратно пропорциональна четверной степени (как между двумя диполями). Если растояние становится меньше, сила пропорциональна расстоянию (длине не втянутой части магнита). Катушка подключена к источнику постоянной ЭДС с некоторым внутренним сопротивлением.
      На этой модели был замечен интересный эффект — снаряд отскакивал от катушки, создавая там большую ЭДС, чем у внешнего питания.
  • +1
    Не надо бы, наверное, длиной отрезка называть квадрат его длины…
    • 0
      Ну монотонная функция от фиксированного параметра…
      Эту модель я быстро наборосал, что бы оценить сложность управления таким манипулятором.
  • 0
    Так как на бесконечных последовательностях естественным образом определяется топология, Haskell может решить это уравнение методом проcтых итераций (через оператор неподвижной точки).
    Простите, что? Какая топология? Что за оператор неподвижной точки? Что значит «решить уравнение», если решением является бесконечная последовательность целых чисел?
    • 0
      Топология, на пальцах, это возможность определить, что последовательность объектов сходится к некому новому объекту.
      Пределом последовательности последовательностей будет такая последовательность, которая в каждой позиции отличается только от конечного числа исходных.
      Неподвижной точкой называют решение уравнения x = f(x) по x. Если на множестве допустимых x определена топология, то может повезти и вычисляя f(f(.....f(f(x0))....)) мы будем приближаться в решению уравнения.
      В данном случае для вычисления первых N элементов последовательности f(x) нам достаточно N-1 элемента последовательности x. Тогда выбрав правильную первоначальную (с конечной длиной) последовательность и применяя к ней функцию в цикле, мы будем получать все новые и новые элементы исходной последовательности.

      Хотя обычному программисту это знать не обязательно, только для математического доказательства правильности программ.
      • 0
        Спасибо, но я не хочу «на пальцах». Я хочу строго и формально, ибо Ваше «естественным образом» для меня не очевидно.

        то может повезти и вычисляя f(f(.....f(f(x0))....)) мы будем приближаться в решению уравнения.
        Что значит «приближаться» (Опять же, формально, пожалуйста)? Теорема Банаха о неподвижной точке требует не просто топологического пространства, а полного метрического, да ещё и оператор должен быть сжимающим. Вот в этом случае повезёт, да.

        Так зачем Haskell'у решать это «уравнение», если он ленивый? И что Вы считаете решением? Интуитивно решением считается вся последовательность чисел Фибоначчи, которая немного великовата для хранения. У Haskell'а есть определение, по которому можно генерировать новые элементы списка по мере необходимости. Зачем что-то решать?
        • 0
          Выписать метрику, в котором это отображение будет сжимающим не сложно, но и в рамках данной статьи не интересно.
          Решать надо, потому что определение записано в виде уравнения, а не в виде алгоритма генерации новых элементов. В общем виде такие уравнения решаются с помощью оператора неподвижной точки y f = f (y f).
          • 0
            Чем описание списка fib не алгоритм? По-моему, ясно видно, что первыми двумя элементами являются единицы, а для получения следующих следует вызвать zipWith с соответствующими параметрами.

            Если даже «решать уравнение», то что будет решением такого уравнения?

            И что там с топологией?
            • 0
              А ни чего, что аргументы zipWith зависят от fib?
              • 0
                Ну и пусть себе зависят, хаскель ленив же. Вот тут подробнее расписано.

                И да, Вы упорно уходите от задания топологии (которая якобы вполне етественна) и определения решения уравнения. С чего бы, интересно?
  • 0
    Prolog неплохой язык, жалко, что про него многие забывают или не знают.
    • 0
      Да, классика. Знать его надо хотя бы для общего развития.
      Только на нем с отрицательными утверждениями сложно работать. Сейчас надежда на «программирование в ограничениях».
      • 0
        А что значит «надежда на»?

        Там разве какой-то ступор возникал, или наоборот прорыв?
        • 0
          Значит что многие задачи, для которых хотелось применять Prolog, но в силу особенностей этого языка не получалось, должны хорошо решаться с помощью программирования в ограничениях. Но пока получается не сильно лучше.
  • 0
    Интересно, а можно было бы сделать курс физики в таких моделях? Вот мне в школе физика не давалась хорошо, хоть я и учился в математическом классе и т.п. Но вот переложить задачки по физике в написание таких моделей, потом смотреть результат наверное было бы очень интересно, может быть и помогло бы в понимании. Может ли автора сделать ну хоть один какой-нибудь не совсем тривиальный пример из школьной программы?
    • 0
      Гауссган как такой пример не подойдет?
      Преподавать у меня плохо получалось — объяснить алгебраические типы Haskell школьникам я не смог. Теперь боюсь, что школьникам будет слишком сложно.
      Но попробовать было бы интересно.

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