Как стать автором
Обновить
90
0

Пользователь

Отправить сообщение
Текущая ветка обсуждений получилась довольно интересной :-) Спасибо вам за замечания.

Однако, изначально, при написании данной статьи у меня была несколько иная цель — проиллюстрировать на простом примере концепцию ГП, предоставить людям работающий прототип, и поделиться собственными наблюдениями.

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

Относительно пространства поиска, в общем случае, можно заметить что оно бесконечномерное, а также, боюсь, что вопрос о его топологии связан с проблемой разрешимости — со всеми вытекающими отсюда последствиями.
Да, ещё очень удобным является тип данных CODE, который, по сути, предоставляет всю функциональность необходимую для ГП.

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

Например:
map(sin, list(1, 10))



То же самое, в императивном стиле:
for(int i = 1; i < 11; i++) {
   arr[i] = sin(i);
}
return arr;

В некоторм роде вы говорите правильные вещи, но ваш стиль комментирования довольно предвзятый (я имею ввиду выражения «притягивать за уши», «костыли», «мега-теория» и т.п.)

Тем более, вы тоже оперируете далеко не академически точными понятиями и терминами.

Как человек с образованием в данной области (квантовая механика и стат. термодинамика), хочу обратить внимание на то, что вы заблуждаетесь относительно того, что "… физический смысл имеют только некоторые точки пространства состояний, причем заранее неясно, какие..." — физический смысл имеют все точки фазового пространства, и он чётко определяется в терминах классической термодинамики.

Второе замечание, — задачи о которых вы упоминаете довольно легко поддаются сферическо-вакуумному формализму. Поэтому, если вы попытаетесь методами чистой стат. физики, например, рассчитать теплоемкость реального кристалла (какого-нибудь германия), или рассчитать температуру фазового равновесия (даже простой воды), то вы потерпите эпический крах — получите результаты, которые могут на порядки отличатся от реальных измерений (почему? да, как минимум, потому что невозможно аналитически рассчитать интеграл взаимодействия в системе, которая содержит больше одного электрона). А для практических расчётов, всё так же, используются всяческие приближения и эмпирические модели.

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

Последняя аналогия — классическая термодинамика, как область естествознания, полностью построена на эмпирике. Хочу привести цитату А. Эйнштейна* по этому поводу: «Теория производит тем большее впечатление, чем проще ее предпосылки, чем разнообразнее предметы, которые она связывает, и чем шире область её применения. Отсюда глубокое впечатление, которое произвела на меня классическая термодинамика. Это единственная физическая теория общего содержания, относительно которой я убежден, что в рамках применимости ее основных понятий она никогда не будет опровергнута (к особому сведению принципиальных скептиков)» — не замечаете ли аналогии?

* (Цит. по: Кириллин Б. Л., Сычев В. В., Шейндлин А. Е. Техническая термодинамика, 3-е изд. М., 1979, с. 502.)
Конечно, если в базовом наборе есть функция sin — ничто не мешает, в результате мутации поместить в корень синтаксического дерева функцию sin.

Хотя, как вы понимаете, по очень маленькому и монотонному промежутку данных — невозможно однозначно определить функцию. Поэтому, на промежутке по х от -0.5 до 0.5, с одинаковой вероятностью можно получить как линейную, так и синусоидальную зависимость.

Относительно тригонометрических функций, я приводил экмпреримент в данном комментарии: habrahabr.ru/post/163195/#comment_5611389
Ваш вопрос можно рассмотреть в контексте вопроса про экстраполяцию: habrahabr.ru/post/163195/#comment_5610933, на который я дал ответ с примером.

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

Вот пример с асимптотической функцией:

Ищем функцию:
f(x) = 2/x

Исходные данные
# allowed functions are: ADD SUB MUL DIV SQRT POW LN SIN COS
# set which functions to use:

ADD MUL SUB DIV POW SQRT

# looking for:

f(x) - ?

# define training set:

f(-1) = -2
f(-0.9) = -2.222222222
f(-0.8) = -2.5
f(-0.7) = -2.857142857
f(-0.6) = -3.333333333
f(-0.5) = -4
f(-0.4) = -5
f(-0.3) = -6.666666667
f(-0.2) = -10
f(-0.1) = -20
f(0.1) = 20
f(0.2) = 10
f(0.3) = 6.666666667
f(0.4) = 5
f(0.5) = 4
f(0.6) = 3.333333333
f(0.7) = 2.857142857
f(0.8) = 2.5
f(0.9) = 2.222222222
f(1) = 2

threshold = 5



И уже на 10-й итерации получаем ответ:
f(x) = (((-40.187091057457245) / x) * (-0.04967024882881388))

лог эксперимента
Start time is: Fri Dec 21 16:30:21 EET 2012

f(x) = (x + x)
1        1110.6141849372693

f(x) = (x * 5.227087163426092)
2        1032.0300015165594

f(x) = (x * 5.188903230694518)
3        1032.0222453656522

f(x) = ((x + x) * 2.599190101196649)
4        1032.0220755614089
5        1032.0220755614089

f(x) = (((x + x) * (-0.12522500922214785)) * (-20.749626688467036))
6        1032.022006105762
7        1032.022006105762

f(x) = (x * 5.19507279952461)
8        1032.0219777015882

f(x) = (x * sqrt(abs(((-33.321388309286405) / x))))
9        873.1171859876806

f(x) = (((-40.187091057457245) / x) * (-0.04967024882881388))
10       0.004707596212974934

Best function is:
f(x) = (((-40.187091057457245) / x) * (-0.04967024882881388))

End time is: Fri Dec 21 16:30:25 EET 2012

Конечно, можно попытаться втиснуть задачу в рамки конкретного метода аппроксимации, но я акцентирую внимание на автоматическом конструировании модели.

При таком подходе, множество функций можно легко расширить до неаналитических, использовать шаблоны, работать с любым количеством переменных, использовать трансцендентные функции ( habrahabr.ru/post/163195/#comment_5611389 ), можно даже реализовать рекурсивные отношения.

Такой подход позволяет спокойно работать с данными, которые тяжело представить в виде функциональной зависимости. Всё тот же пример — демка 1

Я искал нейронную сеть, которая позволит максимизировать эффективность не отдельно взятого агента, а коллективную эффективность группы агентов в незнакомой среде.

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

Генетическое программирование эффективно использовать в задачах, которые трудно формализировать. Если же задачу формализировать достаточно просто, то можно использовать алгоритм специально разработанный для данной предметной области, но в то же время — приемлемые результаты можно получить и с помощью генетического программирования. Именно это я и продемонстрировал в топике.
С этого-то я и начинал топик: «вместо того, чтобы самостоятельно выбирать алгоритм, разработаем программу, которая способна автоматически генерировать алгоритмы для решения задач».

Конечно, любой частный алгоритм, разработанный для конкретной задачи или модели — будет лучше общего подхода.

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

Относительно сходимости — её нельзя рассматривать отдельно от типа эволюционный стратегии (проще говоря — параметров генетического алгоритма)
Вот пример из личного опыта — конструирование нейронных сетей для оптимального поведения группы агентов:

демка 1
демка 2

При чём, я специально не строил априорных предположений о наилучшей структуре нейронной сети
Этому есть несколько причин:
  • для того чтоб контролировать размер популяции в памяти
  • размер дерева влияет на скорость вычисления соответствующей формулы
  • эмпирически установил, что ограничения на 6-7 уровневую глубину дерева, и правильно подобранного множества базисных функций — должно быть достаточно для конструирования приемлемого решения
  • также, я заметил что в данной задаче, небольшие мутации, в применении к огромным деревьям, не привносят качественно лучшие решения
Опишите, пожалуйста, как с помощью ДПФ можно получить формулу f(x, y, z) = x^2 + 3*x + 2*y + z + 5 из описанного в топике эксперимента?
И совсем непонятно, каким образом ДПФ поможет, например, для автоматического конструирования нейронной сети?
Спасибо
(продолжение предыдущего комментария habrahabr.ru/post/163195/#comment_5611549)

В результате получаем формулу:
f(x) = ((x * (((-13.242522576569776) + (x — (-49.47522269762757))) * x)) — ((x * (-11.740960627643991)) * (x * (-9.048031523291307))))

После преобразований:
f(x) = x^3 — 69 * x^2



лог эксперимента
Start time is: Thu Dec 20 05:42:45 EET 2012

f(x) = (86.57304694845936 * x)
1        6.222169286489249E12

f(x) = (144.6778659232081 * x)
2        6.16902774680368E12

f(x) = (134.17750912815694 * (92.71961934899491 * x))
3        5.590600898187449E11
4        5.590600898187449E11
5        5.590600898187449E11
6        5.590600898187449E11
7        5.590600898187449E11

f(x) = (49.69169866316818 * (x * (x * (-3.1677184236399905))))
8        5.0055596992864105E10
9        5.0055596992864105E10

f(x) = (56.48068300981558 * (((-20.863130437536775) + (x - (-43.12637699374933))) * (x * (-3.7782588026154613))))
10       3.9592261954013157E9

f(x) = (58.19939949943191 * (((-21.597963943138016) + (x - (-45.62170226606368))) * (x * (-3.7782588026154613))))
11       3.545551263086143E9

f(x) = (58.02466439209779 * (((-18.96126891390064) + (x - (-42.781599415004585))) * (x * (-3.7782588026154613))))
12       3.540920767846881E9

f(x) = ((58.10020017491848 * (((-22.278842813066657) + (x - (-46.17416306325414))) * (x * (-3.7782588026154613)))) - 5.536053451302263)
13       3.540491873012355E9

f(x) = ((58.10020017491848 * (((-22.278842813066657) + (x - (-46.17416306325414))) * (x * (-3.7782588026154613)))) - 24.298797251839378)
14       3.5400393139433427E9

f(x) = ((58.10020017491848 * (((-22.278842813066657) + (x - (-46.17416306325414))) * (x * (-3.7782588026154613)))) - 44.48189628414795)
15       3.539557998112941E9

f(x) = ((58.10331852588319 * (((-22.278842813066657) + (x - (-46.17416306325414))) * (x * (-3.7782588026154613)))) - 70.99484460029008)
16       3.5389568059665136E9
17       3.5389568059665136E9

f(x) = ((58.10020017491848 * (((-22.278842813066657) + (x - (-46.17416306325414))) * (x * (-3.7782588026154613)))) - 88.53692878105136)
18       3.5385272071778183E9

f(x) = ((58.10020017491848 * (((-22.278842813066657) + (x - (-46.17416306325414))) * (x * (-3.7782588026154613)))) - 96.92101137795909)
19       3.5383341156489058E9

f(x) = ((58.10020017491848 * (((-22.278842813066657) + (x - (-46.17416306325414))) * (x * (-3.7782588026154613)))) - 105.50430898480867)
20       3.538137455505746E9

f(x) = ((58.10020017491848 * (((-22.278842813066657) + (x - (-46.17416306325414))) * (x * (-3.7782588026154613)))) - 125.68872314958799)
21       3.537679055698119E9

f(x) = ((58.10020017491848 * (((-22.278842813066657) + (x - (-46.17416306325414))) * (x * (-3.7782588026154613)))) - 138.7479712122984)
22       3.5373855115252895E9
23       3.5373855115252895E9
24       3.5373855115252895E9

f(x) = (((-37.26846869977584) * ((x + (x - (-47.687763156745156))) * (x * 2.9419052064299054))) - 176.3754379310957)
25       3.536888676374473E9

f(x) = (((x - (-42.26809684868709)) * (((-22.699862676766646) + (x - (-54.323525268738656))) * (x * 1.2876877679231686))) - ((x * (-13.189341913068064)) * (x * (-9.07445805933937))))
26       3.723766513965906E8

f(x) = ((x * (((-20.77021403281741) + (x - (-56.18018484917877))) * (x * 1.0283534934943348))) - ((x * (-11.462695291605907)) * (x * (-9.07445805933937))))
27       4.193009086099604E7

f(x) = ((x * (((-14.927298962277831) + (x - (-50.217089356831124))) * (x * 0.9988515080579701))) - ((x * (-11.316119006918044)) * (x * (-9.307946228589318))))
28       165047.1068965982

f(x) = ((x * (((-19.126382675050188) + (x - (-50.87926661591404))) * (x * 0.9988515080579701))) - ((x * (-8.677352568505196)) * (x * (-11.734135145640401))))
29       70990.23190410846

f(x) = ((x * (((-16.077554143794146) + (x - (-51.46683847282147))) * (x / 0.9988515080579701))) - ((x * (-11.316119006918044)) * (x * (-9.307946228589318))))
30       66206.62977395783
31       66206.62977395783
32       66206.62977395783

f(x) = ((x * (x * (x + 4.4098695807404145))) - ((x * (-8.78805432781831)) * (x * (-8.466132722703005))))
33       20600.857640909722

f(x) = ((x * (((-16.028672342886313) + (x - (-52.26304159953027))) * x)) - ((x * (-11.740960627643991)) * (x * (-9.048031523291307))))
34       806.193032661867
35       806.193032661867
36       806.193032661867
37       806.193032661867
38       806.193032661867
39       806.193032661867

f(x) = ((x * (((-16.028672342886313) + (x - (-52.26296484877049))) * x)) - ((x * (-11.740960627643991)) * (x * (-9.048031523291307))))
40       738.4432450889834
41       738.4432450889834

f(x) = ((x * (((-16.00645087483127) + x) * x)) - ((x * (-8.100439392530896)) * (x * (-6.665549678910843))))
42       27.826212573181493

f(x) = ((x * (((-13.242522576569776) + (x - (-49.47522269762757))) * x)) - ((x * (-11.740960627643991)) * (x * (-9.048031523291307))))
43       3.528531101472191

Best function is:
f(x) = ((x * (((-13.242522576569776) + (x - (-49.47522269762757))) * x)) - ((x * (-11.740960627643991)) * (x * (-9.048031523291307))))

End time is: Thu Dec 20 05:43:02 EET 2012

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

Например:
Пусть искомая функция будет f(x) = x^3 — 70*(x^2)

Входные данные — будут точки с монотонного интервала [-100… -40]

файл с входными данными
# allowed functions are: ADD SUB MUL DIV SQRT POW LN SIN COS
# set which functions to use:

ADD MUL SUB POW DIV

# looking for:

f(x) - ?

# define training set:

f(-100) = -1700000
f(-90) = -1296000
f(-80) = -960000
f(-70) = -686000
f(-60) = -468000
f(-50) = -300000
f(-40) = -176000

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

  1. Оптимизации, ускоряющие поиск решения:

    • Оптимизация коэффициентов деревьев (без изменения структуры дерева)

    • Добавление случайных деревьев в популяцию, в случае, если генетический алгоритм застрял в локальном минимуме

  2. Оптимизации, что упрощают структуру дерева, на самом деле реализованы из чисто практических соображений, чтоб контролировать расходы памяти
Ваши наблюдения верны: найденные решения могут быть правильными или очень хорошими, но из-за способа построения могут выглядеть довольно громоздко, или содержать мёртвые участки кода. Но вот с Вашими с выводами я не соглашаюсь.

Можно конструировать «простые программы», но во многих случаях это лишь затруднит поиск хорошего решения.

Пример, когда мёртвые участки кода полезны:
представте что мы ищем формулу (1 + (x — 5)^2).
Она может получится в результате мутации дерева с мёртвым участком:
(1 + (x — x)^2) -> (1 + (x — 5)^2)
(небольшое уточнение к графику: в точке x = 0 — асимптота, но так как точка 0 не входила в обучающую выборку, то при построении графика, я её случайно «проскочил»)
Спасибо Вам за идею. Решил проверить — получить формулу для синуса, не имея функции sin.
Для этого создал следующую обучающую выборку (где f(x) — значения синуса x):
sin_as_cos.txt
# allowed functions are: ADD SUB MUL DIV SQRT POW LN SIN COS
# set which functions to use:

ADD SUB MUL DIV SQRT POW COS

# looking for:

f(x) - ?

# define training set:

f(-5) = 0.958924275
f(-4.6) = 0.993691004
f(-4.2) = 0.871575772
f(-3.8) = 0.611857891
f(-3.4) = 0.255541102
f(-3) = -0.141120008
f(-2.6) = -0.515501372
f(-2.2) = -0.808496404
f(-1.8) = -0.973847631
f(-1.4) = -0.98544973
f(-1) = -0.841470985
f(-0.6) = -0.564642473
f(-0.2) = -0.198669331
f(0.2) = 0.198669331
f(0.6) = 0.564642473
f(1) = 0.841470985
f(1.4) = 0.98544973
f(1.8) = 0.973847631
f(2.2) = 0.808496404
f(2.6) = 0.515501372
f(3) = 0.141120008
f(3.4) = -0.255541102
f(3.8) = -0.611857891
f(4.2) = -0.871575772
f(4.6) = -0.993691004

threshold = 0.5



Провёл эксперимент несколько раз. Ниже приведены полученные результаты:

  1. f(x) = cos((((x — 0.20866701892617723) + 0.20909776128069524) + (-1.5658757184422276)))
    После упрощения:
    f(x) = cos(x — 1.56544498)
    а это почти cos(x — pi/2)
    лог эксперимента
    Start time is: Thu Dec 20 02:09:16 EET 2012
    
    f(x) = 0.037473612748792906
    1      13.1066035437915
    2      13.1066035437915
    
    f(x) = 0.03907633650413578
    3      13.106596972914716
    
    f(x) = ((x * (-0.0872113058946149)) + 0.014906325070420667)
    4      12.655025376552377
    
    f(x) = (0.13723422167838573 / x)
    5      12.157457270158343
    6      12.157457270158343
    
    f(x) = (0.13723422167838573 / (x * 1.0913808377181144))
    7      12.152326784266156
    8      12.152326784266156
    
    f(x) = (3.2071455614529727 / (x * 25.114850968636148))
    9      12.152068404736541
    
    f(x) = (3.595526544914747 / ((x * 25.77776235214153) * 1.0913808377181144))
    10      12.152067661286328
    
    f(x) = (0.7306468226024925 / (x + ((3.1952852003281116 / (x * 25.70161792899045)) * 2.623353842188707)))
    11      9.952938064507393
    
    f(x) = (0.7306468226024925 / (x + (((3.1952852003281116 / (14.680761568160436 * x)) * 1.39406585192928) * 1.075844125197815)))
    12      9.952936408450574
    13      9.952936408450574
    14      9.952936408450574
    
    f(x) = cos(((-7.899669176555985) / ((x + (-2.934551771761199)) + 1.2773079814532693)))
    15      5.945158111235378
    16      5.945158111235378
    
    f(x) = cos(((-7.173167456475843) / (((x - 0.20866701892617723) + 0.20909776128069524) + (-1.6400760520463233))))
    17      4.078430742322765
    
    f(x) = cos(((-7.45261054740821) / (((x - 4.329856978342905) + 4.371028455719269) + (-1.6400760520463233))))
    18      2.733571097513842
    
    f(x) = cos((((x - 0.20866701892617723) + 0.20909776128069524) + (-1.5658757184422276)))
    19      3.3949567063295085E-4
    
    Best function is:
    f(x) = cos((((x - 0.20866701892617723) + 0.20909776128069524) + (-1.5658757184422276)))
    
    End time is: Thu Dec 20 02:09:25 EET 2012
    



  2. f(x) = cos(((-1.07016828426169) * ((x / x) * (x + 4.4401611735732125))))
    После упрощения:
    f(x) = cos(-1.07016828426169 * x — 4.75171966) = cos(1.07016828426169 * x + 4.75171966)
    а это почти cos(x + 3*pi/2)
    лог эксперимента
    Start time is: Thu Dec 20 02:11:58 EET 2012
    
    f(x) = 0.030868250151864896
    1      13.107986059245036
    
    f(x) = 0.03767074767874057
    2      13.106595808307668
    
    f(x) = 0.038242426449158984
    3      13.106584363757857
    4      13.106584363757857
    5      13.106584363757857
    6      13.106584363757857
    
    f(x) = (0.1637990150606723 / x)
    7      12.230665733051994
    
    f(x) = (0.13705836621394107 / x)
    8      12.15725800536878
    9      12.15725800536878
    
    f(x) = ((0.1481202255848797 / x) * 0.8684798749213931)
    10      12.152109398402798
    11      12.152109398402798
    
    f(x) = (0.12857591793327128 / x)
    12      12.152103249788755
    
    f(x) = ((0.020376091331116397 / x) * 6.271785421060187)
    13      12.152067673004629
    14      12.152067673004629
    15      12.152067673004629
    16      12.152067673004629
    17      12.152067673004629
    
    f(x) = ((0.46601388716913195 ^ x) * 0.02977298399532957)
    18      11.469845817953859
    
    f(x) = (((-0.38967085673639446) / ((4.404835173431312 ^ x) / ((-0.08138602455387023) / x))) * (-0.09385199865456717))
    19      10.911993456710471
    
    f(x) = (((-0.1439165901739734) / ((4.457965327030093 ^ x) / ((-0.23419484479312658) / x))) * (-0.09385199865456717))
    20      10.844524333414348
    21      10.844524333414348
    
    f(x) = ((0.5666114085540572 / ((0.5348028282775066 ^ x) / (cos((-1.5394326500896378)) / x))) * ((x * (-4.3285907551309215)) - (-9.400020532885092)))
    22      10.587827937080267
    
    f(x) = ((0.1488277396985822 / ((-6.499878077275849) / ((1.667112028884965 ^ x) / ((-3.4574956828857646) / x)))) * ((x * (-4.742415091725814)) - (-17.426395027916122)))
    23      9.845309875059357
    24      9.845309875059357
    25      9.845309875059357
    
    f(x) = ((0.019835272236428114 / ((1.4762453312970956 ^ x) / ((x / x) * (x + 3.322468527485495)))) * ((x / x) * (x + (-1.0677662167272803))))
    26      9.611591802099714
    
    f(x) = (((-0.11842972705153176) / ((x * x) / ((3.1353175097938144 ^ x) / ((-12.711280290000289) / x)))) * ((x * (-3.747429583149386)) - (-13.682941331058357)))
    27      9.441749174052777
    
    f(x) = (((((-3.9985992143686104) / ((-11.860791526742453) / (x / (-12.255149129698886)))) * (-5.083919364763941)) / ((0.9374635931326201 ^ x) / (((x / (-4.24828079172007)) / x) * (x + (-3.7192102312585376))))) * ((x / x) * (x + 3.5489201296979966)))
    28      3.2474458505656605
    29      3.2474458505656605
    
    f(x) = cos(((((0.7891062240951006 / (37.690057096649355 / x)) * (-3.9700337867889055)) / ((2.1459450244373666 ^ x) / ((x / x) * ((-31.82073084338193) + x)))) * ((x / x) * (x + 3.8341848367144498))))
    30      2.751772332932753
    31      2.751772332932753
    32      2.751772332932753
    
    f(x) = cos(((-1.104233492883234) * ((x / x) * (x + 4.176966445681568))))
    33      0.9796598588054801
    
    f(x) = cos((1.0878741299861896 * ((x / x) * (x + 4.407430173983707))))
    34      0.6471346736176921
    
    f(x) = cos(((-1.07016828426169) * ((x / x) * (x + 4.4401611735732125))))
    35      0.39445546562024103
    
    Best function is:
    f(x) = cos(((-1.07016828426169) * ((x / x) * (x + 4.4401611735732125))))
    
    End time is: Thu Dec 20 02:12:29 EET 2012
    



  3. f(x) = cos(((-1.5518824117603933) — ((x * (-22.779793630567173)) * ((0.9905590241810334 ^ x) / 22.778425607844536))))
    Опять получили немного запутанную формулу. Хотя, легко заметить, что (0.9905590241810334 ^ x) это почти (1 ^ x) — а значит никак на результирующую формулу влияет. Затем, можно сократить числитель и знаменатель — 22.779793630567173
    Таким образом, приходим к формуле:
    f(x) = cos(-1.5518824117603933 + x)
    а это почти cos(x — pi/2)
    лог эксперимента
    Start time is: Thu Dec 20 02:14:58 EET 2012
    
    f(x) = (x * (-0.03497647400759352))
    1      12.569697409104204
    
    f(x) = (0.03206375777473447 - (x / 17.859742523423733))
    2      12.45310280520347
    
    f(x) = (0.03206375777473447 / (x / 3.983422951936845))
    3      12.152068113028749
    4      12.152068113028749
    
    f(x) = (0.16410654890797227 - ((2.0299865145513394 ^ x) / 27.160308551872905))
    5      11.458518951142699
    6      11.458518951142699
    
    f(x) = ((-0.08190782796508467) - ((x * 0.3250906200640813) * ((0.5612667000580951 ^ x) / 25.142726236353084)))
    7      10.658531610257057
    
    f(x) = ((-0.1820149022978066) - ((x * 0.09015777715283968) * ((0.4280416776009639 ^ x) / 21.065084851380853)))
    8      10.516453362951314
    
    f(x) = ((-0.01503108962299926) - ((x * (-24.265371409776968)) * (((0.7310665285787377 ^ x) ^ x) / 19.010083617783746)))
    9      5.926306763301507
    
    f(x) = (0.033809751868219884 - ((x * (-22.683745105291987)) * (((0.7310665285787377 ^ x) ^ x) / 17.834566430135432)))
    10      5.855312350773518
    
    f(x) = (0.033809751868219884 - ((x * (-22.683745105291987)) * (((0.7310665285787377 ^ x) ^ x) / 17.79616422156097)))
    11      5.855294223104098
    12      5.855294223104098
    
    f(x) = (0.033809751868219884 - ((x * (-23.19192196847812)) * (((0.717967820948241 ^ x) ^ x) / 17.386188149870783)))
    13      5.836810741669103
    
    f(x) = (0.033809751868219884 - ((x * (-21.669518751123967)) * (((0.717967820948241 ^ x) ^ x) / 16.287254620910687)))
    14      5.836761497328263
    15      5.836761497328263
    
    f(x) = (0.038546517497714206 - ((x * (-21.669518751123967)) * (((0.717967820948241 ^ x) ^ x) / 16.287254620910687)))
    16      5.836229539440452
    17      5.836229539440452
    
    f(x) = (0.03843417466089871 - ((x * (-21.669518751123967)) * (((0.717967820948241 ^ x) ^ x) / 16.287254620910687)))
    18      5.836229167974826
    19      5.836229167974826
    20      5.836229167974826
    21      5.836229167974826
    22      5.836229167974826
    23      5.836229167974826
    24      5.836229167974826
    25      5.836229167974826
    26      5.836229167974826
    27      5.836229167974826
    28      5.836229167974826
    29      5.836229167974826
    30      5.836229167974826
    31      5.836229167974826
    32      5.836229167974826
    33      5.836229167974826
    34      5.836229167974826
    35      5.836229167974826
    36      5.836229167974826
    
    f(x) = (0.03843417466089871 - ((x * (-21.669518751123967)) * (((0.7175444245047398 ^ x) ^ x) / 16.26151878069896)))
    37      5.836200483976189
    38      5.836200483976189
    39      5.836200483976189
    
    f(x) = (0.03843417466089871 - ((x * (-21.669518751123967)) * (((0.7175444245047398 ^ x) ^ x) / 16.262705747349774)))
    40      5.836200268757786
    41      5.836200268757786
    42      5.836200268757786
    43      5.836200268757786
    
    f(x) = (0.03843417466089871 - ((x * (-21.662524193965517)) * (((0.7175444245047398 ^ x) ^ x) / 16.262705747349774)))
    44      5.83620024612793
    45      5.83620024612793
    46      5.83620024612793
    47      5.83620024612793
    
    f(x) = (0.03843417466089871 - ((x * (-21.667776661667226)) * (((0.7175444245047398 ^ x) ^ x) / 16.262705747349774)))
    48      5.836200121399585
    49      5.836200121399585
    
    f(x) = (0.03843417466089871 - ((x * (-21.662524193965517)) * (((0.7175444245047398 ^ x) ^ x) / 16.26141837828798)))
    50      5.8362001114409825
    51      5.8362001114409825
    52      5.8362001114409825
    53      5.8362001114409825
    54      5.8362001114409825
    55      5.8362001114409825
    56      5.8362001114409825
    57      5.8362001114409825
    58      5.8362001114409825
    59      5.8362001114409825
    
    f(x) = (0.03843417466089871 - ((x * (-24.624664221314188)) * (((0.7175444245047398 ^ x) ^ x) / 18.482635204699278)))
    60      5.836200086756856
    61      5.836200086756856
    62      5.836200086756856
    63      5.836200086756856
    64      5.836200086756856
    65      5.836200086756856
    66      5.836200086756856
    67      5.836200086756856
    68      5.836200086756856
    69      5.836200086756856
    70      5.836200086756856
    71      5.836200086756856
    72      5.836200086756856
    
    f(x) = (0.03843417466089871 - ((x * (-23.803425055908484)) * (((0.7175444245047398 ^ x) ^ x) / 17.866721331430185)))
    73      5.836200071940088
    74      5.836200071940088
    75      5.836200071940088
    76      5.836200071940088
    77      5.836200071940088
    
    f(x) = (((x * (-21.727813149886583)) * (((0.444473883735897 ^ x) ^ x) / 25.877440479220724)) - ((x * (-27.869805964415654)) * (((0.7175444245047398 ^ x) ^ x) / 16.054058406243342)))
    78      5.753786607216474
    
    f(x) = cos(((-1.5518824117603933) - ((x * (-22.779793630567173)) * ((0.9905590241810334 ^ x) / 22.778425607844536))))
    79      0.06523396656992454
    
    Best function is:
    f(x) = cos(((-1.5518824117603933) - ((x * (-22.779793630567173)) * ((0.9905590241810334 ^ x) / 22.778425607844536))))
    
    End time is: Thu Dec 20 02:17:52 EET 2012
    



  4. Хотя, один раз всё таки получился полином:
    f(x) = ((-22.66355680142012) / ((15.948637956747325 / (((-2.6050273232187884) / x) — (x * (-0.2602149380973864)))) — (17.992754706738232 / x)))



    лог эксперимента
    Start time is: Thu Dec 20 03:06:30 EET 2012
    
    f(x) = (0.18206317394353455 / x)
    1      12.3306847201965
    2      12.3306847201965
    
    f(x) = (0.13096000716683331 / x)
    3      12.152669766801575
    4      12.152669766801575
    
    f(x) = (0.12762196997306274 / x)
    5      12.152069805558092
    6      12.152069805558092
    7      12.152069805558092
    
    f(x) = (0.3346849273504282 / ((((-22.4152051827909) * x) + 40.960688022849595) / x))
    8      12.148014860354863
    
    f(x) = ((-0.03796031129649258) / (cos(x) / ((-2.9198621819690938) / x)))
    9      11.638011754782829
    10     11.638011754782829
    
    f(x) = ((-20.631874183396533) / (((-9.207249236246206) / x) - (x * 27.91345503131871)))
    11      9.952693006480558
    12      9.952693006480558
    13      9.952693006480558
    
    f(x) = ((-11.825393899136301) / ((27.294600788294975 / ((0.5155794242305176 / x) - (x * 17.31342263836807))) - (x * 20.565965766798282)))
    14      9.888627753702877
    
    f(x) = ((-15.532470172735072) / ((25.778228513107628 / ((0.18734779505625987 / x) - (x * 6.391452889555231))) - (x * 21.629379422632773)))
    15      9.792881118418999
    
    f(x) = ((-11.825393899136301) / ((41.90109261338367 / ((0.46759657320866577 / x) - (x * 15.120516570080058))) - (x * 17.102239047167586)))
    16      9.791571430938934
    
    f(x) = ((-22.66355680142012) / ((15.948637956747325 / (((-2.6050273232187884) / x) - (x * (-0.2602149380973864)))) - (17.992754706738232 / x)))
    17      0.3622781954825648
    
    Best function is:
    f(x) = ((-22.66355680142012) / ((15.948637956747325 / (((-2.6050273232187884) / x) - (x * (-0.2602149380973864)))) - (17.992754706738232 / x)))
    
    End time is: Thu Dec 20 03:06:40 EET 2012
    



Да, с несколькими экстремумами ситуация выглядит немного сложнее.

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

	public double fitness(Expression expression, Context context) {
		double delt = 0;

		for (int x = -10; x < 11; x += 0.5) {
			// искомое значение производной
			double target = (this.f(x + dx) - this.f(x)) / dx;

			context.setVariable("x", x);
			double evolved = expression.eval(context);

			delt += this.sqr(target - evolved);
		}
		return delt;
	}

	// функция, чью производную мы ищем
	private double f(double x) {
		return x * x * x + 10 * x + Math.pow(3, x);
	}


И опять же, для ускорения работы — я рассматривал только небольшой интервал значений x: от -10 до +11
Да, это, большей мерой, результат достигнутый экспериментальным путём.
Один интересный момент, который можно заметить — два синтаксически подобных дерева — могут очень сильно различаться семантически. Хотя, может, это даже лучше, в плане покрытия пространства поиска решений

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность