Evolutionary Programming
"Началось это так: В начале была создана Вселенная. Это у многих вызвало крайнее раздражение, и в основном рассматривалось как плохой ход. Многие народы верят, что она была создана каким-нибудь божеством, хотя, к примеру, джадравартиды с Вильтводля VI верят в то, что на самом деле всю Вселенную вычихнуло существо по имени Большой Зеленый Арклохват. Джатравартиды живут в постоянном страхе перед тем, что они называют Пришествием Большого Белого Платка. Это маленькие голубые создания, и у каждого из них пятьдесят рук, так что они -- единственный народ во всей Вселенной, который изобрел дезодорант раньше колеса. Культ Большого Зеленого Арклохвата, однако, не получил большого распространения за пределами системы Вильтводля IV, и поэтому, а также потому, что Вселенная как была, так и остается полна загадок, поиск ответа не прекращается. Например, раса сверхразумных всеразмерных созданий построила себе однажды гигантский суперкомпьютер под названием Глубокомысленный, чтобы он раз и навсегда вычислить Ответ на Главный вопрос Жизни, Вселенной и всего Прочего. Семь с половиной миллионов лет Глубокомысленный считал и рассчитывал, и, наконец, объявил, что нашел ответ: "Сорок два", -- и в результате пришлось строить еще один компьютер, еще больше, чтобы выяснить, какой же вопрос нужно задавать к этому ответу."
Дуглас Адамс. Ресторан на краю Вселенной
Итак я начну тут писать идеи для эволюционного программирования. Буду писать много, не красиво, сбивчиво, прыгая от одного к другому. Такой подход даст возможность развивать идеи для реализации. Я буду описывать что я понимаю под тем, чего хочу достичь и с помощью чего. Параллельно, когда буду видеть, что какие-то идеи будут действующими буду их реализовывать.
Хочу заметить, что то, что я буду делать не будет именно тем, что подразумевает под эволюционным программированием научное сообщество. Так как повторение скорее всего приведёт к заведомо известному конечному результату. Я буду пытаться решить задачу с помощью своих логических выводов от малого к большему.
Задача: создать некую эволюционную систему. Она должна развиваться. Развитие в себе подразумевает поиск и решение задач, условие которых не прописано заранее. Система должна увидеть проблему, искать решение и решение должно со временем становиться все более оптимизированным. Задач должно становиться все больше и система должна решать их все.
Думаю для реализации этого должна существовать среда с некоторыми правилами, например двоичная матрица и в ней должны быть некие сущности, включая саму обучающуюся систему. Система должна иметь хотя бы одно чувство. Например чувство голода. Должен иметь хотя бы один орган чувств. Это будет осязание клеток рядом. А также должна быть возможность выполнять действие - движение.
Для начала реализую матрицу. Выполнять буду в среде, где мне удобно на данный момент. Язык bash, консоль. Сделаю матрицу, размер матрицы изначально должен быть регулируемым и 10х10 в начале вполне хватит.
Создаем файл matrix.sh
Итак, для начала bash не поддерживает многомерные массивы. Придется держать все в одномерном и писать логику переноса двумерного представления в одномерный массив данных.
#!/bin/bash
MAX_X=10MAX_Y=10LENGTH=$(( $MAX_X * $MAX_Y ))echo $LENGTH
Для начала заполним его случайной средой как одномерный массив. Массив в таком случае должен содержать среду и в случайных местах клетки с типом "еда"
Но для начала создадим "Землю":
ENUM_MATRIX_LAND=0filling(){local ifor (( i=1; i <= "$LENGTH"; i++ )); domatrix[$i]="$ENUM_MATRIX_LAND"done}
Теперь нам нужен генератор случайных чисел, не будем же мы вручную наполнять наш дивный мир:
get_random(){local -r probability="$1"local randomrandom=$((1 + RANDOM % probability))echo "$random"}
На входе в него мы имеем параметр probability, который отвечает за диапазон получаемого числа от единицы
Теперь добавим надстройку, возвращающую true или false, в зависимости от входящей вероятности. Будем проверять равен ли random единице и в зависимости от диапазона random сможем регулировать вероятность.
FALSE=0TRUE=1get_probability(){local -r probability="$1"local randomrandom="$(get_random $probability)"if [ "$random" = "1" ]; thenecho $TRUEelseecho $FALSEfi}
filling_type(){local -r type="$1"local -r probability="$2" local outlocal ifor (( i=1; i <= "$LENGTH"; i++ )); doout="$(get_probability $probability)"if [ "$out" = $TRUE ]; thenmatrix[$i]="$type"fidone}
filling_type "$ENUM_MATRIX_FOOD" "$FOOD_PROBABILITY"
Мы уже получили "мир", но не видим его. Давайте сделаем визуализацию. Создадим функцию drawing_matrix, которая будет выводить мир. Вывод сделаем сначала максимально простым, потом будем эту функцию усложнять.
drawing_matrix(){local i
for (( i=1; i <= "$LENGTH"; i++ )); doecho -n "${matrix[$i]}"done}
Давайте посмотрим что мы получили:
./matrix.sh
0000110100000000100110000100110000001000010110000000010100000111011001111110000000000000000010001000
Вот он наш мир, полный чудес и загадок!
Теперь надо бы сохранить наш мир, чтобы мир реальный его случайно не уничтожил
git clone https://vilkovsky@bitbucket.org/vilkovsky/evolutionary_programming.git
git add .
git commit -m "1"
git push
drawing_matrix(){local ilocal x=1for (( i=1; i <= "$LENGTH"; i++ )); doecho -n "${matrix[$i]} "x=$((x+1))if [ "$x" -gt "$MAX_X" ]; thenechox=1fidone}
1 0 0 1 0 0 0 0 0 10 0 1 1 0 1 0 1 0 00 0 0 0 0 0 1 1 0 00 1 0 1 0 1 0 1 0 00 0 1 0 0 1 1 0 0 11 1 0 0 1 0 0 0 0 00 0 1 0 1 0 1 0 0 01 0 0 1 0 0 1 0 0 01 0 1 0 1 0 0 0 0 10 0 0 0 1 0 0 1 0 1
source drawing.lib
FIELD_BORDER_LEFT="|"FIELD_BORDER_TOP="-"drawing_border_top_bottom(){local xecho -n " "for (( x=1; x <= "$MAX_X"; x++ )); doecho -n "$FIELD_BORDER_TOP "doneecho}drawing_matrix(){local ilocal x=1drawing_border_top_bottomfor (( i=1; i <= "$LENGTH"; i++ )); doif [ "$x" = "1" ]; thenecho -n "$FIELD_BORDER_LEFT "fiecho -n "${matrix[$i]} "x=$((x+1))if [ "$x" -gt "$MAX_X" ]; thenecho "$FIELD_BORDER_LEFT"x=1fidonedrawing_border_top_bottom}
source entity.lib
И тут я понял, как мне не будет хватать конструкторов, наследования, объктов с++... Но пока не отвлекаемся от проложенного курса. Тем более у меня есть несколько идей по реализации объектов, но об этом позже. Я уже вижу, как можно усложнить код, сделать все хитро-запутанным, но торопиться не будем.
в entity.lib прописываем единственные нужные на данный момент характеристики:
ENTITY1_X=5
ENTITY1_Y=6
в matrix.sh добавляем существо в enum
ENUM_ENTITY=2
DRAW_ARR["$ENUM_ENTITY"]="Q"
А ведь у него уже есть хвост!
и правим функцию drawing_matrix. Да, ее придется еще долго править, так как все отображение будет именно в ней и к моменту ее вызова все должно быть рассчитано и в ней должно быть все описано. Итак, добавляем в нее наше хвостатое чудище.
drawing_matrix(){local ilocal x=1local ydrawing_border_top_bottomfor (( i=1; i <= "$LENGTH"; i++ )); doy=$((1+$((i/MAX_X))))if [ "$x" = "1" ]; thenecho -n "$FIELD_BORDER_LEFT "fiif [ "$x" = "$ENTITY1_X" ] && [ "$y" = "$ENTITY1_Y" ]; thenecho -n "${DRAW_ARR["$ENUM_ENTITY"]}"elseecho -n "${DRAW_ARR[${matrix[$i]}]}"fiecho -n " "x=$((x+1))if [ "$x" -gt "$MAX_X" ]; thenecho "$FIELD_BORDER_LEFT"x=1fidonedrawing_border_top_bottom}
TIME_INTERVAL=0.1while true; docleardrawing_matrixsleep "$TIME_INTERVAL"done
drawing_border_top_bottom(){local xlocal outputoutput=" "for (( x=1; x <= "$MAX_X"; x++ )); dooutput+="$FIELD_BORDER_TOP "doneoutput+="\n"echo "$output"}drawing_matrix(){local ilocal x=1local ylocal outputoutput=$(drawing_border_top_bottom)for (( i=1; i <= "$LENGTH"; i++ )); doy=$((1+$((i/MAX_X))))if [ "$x" = "1" ]; thenoutput+="$FIELD_BORDER_LEFT "fiif [ "$x" = "$ENTITY1_X" ] && [ "$y" = "$ENTITY1_Y" ]; thenoutput+="${DRAW_ARR["$ENUM_ENTITY"]}"elseoutput+="${DRAW_ARR[${matrix[$i]}]}"fioutput+=" "x=$((x+1))if [ "$x" -gt "$MAX_X" ]; thenoutput+="$FIELD_BORDER_LEFT\n"x=1fidoneoutput+=$(drawing_border_top_bottom)echo -e "$output"}
while true; dooutput="$(clear; drawing_matrix)"echo "$output"sleep "$TIME_INTERVAL"done
TIME_COUNTER=0
while true; dooutput="$(clear; drawing_matrix)"echo "$output"TIME_COUNTER="$((TIME_COUNTER+1))"sleep "$TIME_INTERVAL"done
TIME_COUNTER_TEXT="Counter:"drawing_counter(){local texttext="$TIME_COUNTER_TEXT $TIME_COUNTER"echo "$text"}
drawing_matrix(){local ilocal x=1local ylocal outputoutput=$(drawing_border_top_bottom)output+=" $(drawing_counter)"output+="\n"for (( i=1; i <= "$LENGTH"; i++ )); doy=$((1+$((i/MAX_X))))if [ "$x" = "1" ]; thenoutput+="$FIELD_BORDER_LEFT "fiif [ "$x" = "$ENTITY1_X" ] && [ "$y" = "$ENTITY1_Y" ]; thenoutput+="${DRAW_ARR["$ENUM_ENTITY"]}"elseoutput+="${DRAW_ARR[${matrix[$i]}]}"fioutput+=" "x=$((x+1))if [ "$x" -gt "$MAX_X" ]; thenoutput+="$FIELD_BORDER_LEFT\n"x=1fidoneoutput+=$(drawing_border_top_bottom)echo -e "$output"}
drawing_interface(){local outputoutput="$(drawing_counter)"output+="\n"output+="Entity X: $ENTITY1_X Y: $ENTITY1_Y\n"echo "$output"}
output+="$(drawing_interface)"
check_position(){if [ "$ENTITY1_X" -gt "$MAX_X" ]; thenENTITY1_X="$MAX_X"elif [ "$ENTITY1_X" -lt "$MIN_X" ]; thenENTITY1_X="$MIN_X"fiif [ "$ENTITY1_Y" -gt "$MAX_Y" ]; thenENTITY1_Y="$MAX_Y"elif [ "$ENTITY1_Y" -lt "$MIN_Y" ]; thenENTITY1_Y="$MIN_Y"fi}go_left(){ENTITY1_X="$((ENTITY1_X+1))"check_position}go_right(){ENTITY1_X="$((ENTITY1_X-1))"check_position}go_top(){ENTITY1_Y="$((ENTITY1_Y-1))"check_position}go_bottom(){ENTITY1_Y="$((ENTITY1_Y+1))"check_position}
В ней добавил такие функцииprocessor(){}get_pleasure(){}get_senses(){}get_memory(){}get_act(){}
go_chaotic(){local randrand="$(get_random 4)"case "$rand" in1)go_left;;2)go_right;;3)go_top;;4)go_bottom;;esac}
processor(){get_act}
get_act(){go_chaotic}
check_position(){local -r x="$1"local -r y="$2"local triggertrigger=$TRUEif [ "$x" -gt "$MAX_X" ]; thentrigger="$FALSE"elif [ "$x" -lt "$MIN_X" ]; thentrigger="$FALSE"fiif [ "$y" -gt "$MAX_Y" ]; thentrigger="$FALSE"elif [ "$y" -lt "$MIN_Y" ]; thentrigger="$FALSE"fiecho "$trigger"}go_left(){local xx="$((ENTITY1_X+1))"if [ "$(check_position "$x" "$ENTITY1_Y")" = "$TRUE" ]; thenENTITY1_X="$x"return "$MEMORY_GO_LEFT"elsereturn "$MEMORY_GO_NEVER"fi}go_right(){local xx="$((ENTITY1_X-1))"if [ "$(check_position "$x" "$ENTITY1_Y")" = "$TRUE" ]; thenENTITY1_X="$x"return "$MEMORY_GO_RIGHT"elsereturn "$MEMORY_GO_NEVER"fi}go_top(){local yy="$((ENTITY1_Y-1))"if [ "$(check_position "$ENTITY1_X" "$y")" = "$TRUE" ]; thenENTITY1_Y="$y"return "$MEMORY_GO_TOP"elsereturn "$MEMORY_GO_NEVER"fi}go_bottom(){local yy="$((ENTITY1_Y+1))"if [ "$(check_position "$ENTITY1_X" "$y")" = "$TRUE" ]; thenENTITY1_Y="$y"return "$MEMORY_GO_BOTTOM"elsereturn "$MEMORY_GO_NEVER"fi}go_chaotic(){local randlocal statusrand="$(get_random 4)"case "$rand" in1)go_left; status="$?";;2)go_right; status="$?";;3)go_top; status="$?";;4)go_bottom; status="$?";;esacreturn "$status"}
MEMORY_GO_NEVER=1MEMORY_GO_LEFT=2MEMORY_GO_RIGHT=3MEMORY_GO_TOP=4MEMORY_GO_BOTTOM=5
processor(){local statuslocal memget_act; status="$?"mem="$status"set_memory "$mem"}set_memory(){local -r mem="$1"ENTITY_MEMORY+=($mem)}get_act(){local statusgo_chaotic; status="$?"return "$status"}
ENTITY_ENERGY=100action_entity(){processorconsumption_energy}consumption_energy(){ENTITY_ENERGY="$((ENTITY_ENERGY-1))"}
interaction_with_the_environment(){local zz="$(($(($(($ENTITY1_Y-1))*$MAX_X))+$ENTITY1_X))"if [ "${matrix[$z]}" = "$ENUM_MATRIX_FOOD" ]; thenmatrix[$z]="$ENUM_MATRIX_LAND"ENTITY_ENERGY="$(($ENTITY_ENERGY+100))"fi}
Комментарии
Отправить комментарий