Исследуем формулу Эйлера как генератор простых чисел.

Cn=n*n+n+41

Напишем код на Python и Forth для проверки количества простых чисел при n = от 0 до 100, 1000, 10000, 50000 и 65000.

Рассмотрим также C=27941 как замену 41, и сделаем вывод что многочлен с таким свободным членом генерирует больше простых чисел.

Код для подсчета количества простых чисел, генерируемое формулой Cn=n*n+n+41 (Cn=n*n+n+27941) на ЯП Forth.

S" lib\include\float2.f" INCLUDED
S" lib\include\facil.f" INCLUDED

: TIME TIME&DATE 2DROP 24 * + 60 * + 60 * + ;

: IS_PRIME ( N -> D )
    DUP 4 < IF DROP 1 EXIT THEN
    DUP 2 MOD 0= IF DROP 2 EXIT THEN
    DUP 0 D>F FSQRT F>D DROP 2 + 3 DO
        DUP I MOD 0= IF DROP I 0 LEAVE THEN
    2 +LOOP IF 1 ELSE THEN
;

: TST 20 0 DO I DUP . IS_PRIME . CR LOOP ;

: EULER ( N K -> )
    0 SWAP ROT 0 DO
        DUP I DUP 1+ * +
        IS_PRIME 1 = IF SWAP 1+ SWAP THEN
    LOOP DROP
;

: MAIN
TIME
    65000 41 EULER . \ код для проверки
TIME SWAP - CR ." ZANYALO " . ." sec" ;

MAIN

Первый параметр n, второй - C=41 или C=27941.

100 41 EULER .
86 Ok
100 27941 EULER .
77 Ok

1000 41 EULER .
581 Ok
1000 27941 EULER .
599 Ok

10000 41 EULER .
4149 Ok
10000 27941 EULER .
4466 Ok

45000 41 EULER .
15571 Ok
45000 27941 EULER .
17075 Ok


Код для работы с беззнаковыми числами на Forth.

S" lib\include\float2.f" INCLUDED
S" lib\include\facil.f" INCLUDED

: TIME TIME&DATE 2DROP 24 * + 60 * + 60 * + ;

: IS_PRIME ( N -> D )
    DUP 4 U< IF DROP 1 EXIT THEN
    DUP 2 UMOD 0= IF DROP 2 EXIT THEN
    DUP 0 D>F FSQRT F>D DROP 2 + 3 DO
        DUP I UMOD 0= IF DROP I 0 LEAVE THEN
    2 +LOOP IF 1 ELSE THEN
;

: TST 20 0 DO I DUP . IS_PRIME . CR LOOP ;

: EULER ( N K -> )
    0 SWAP ROT 0 DO
        DUP I DUP 1+ * +
        IS_PRIME 1 = IF SWAP 1+ SWAP THEN
    LOOP DROP
;

: MAIN
TIME
    50000 27941 EULER . \ код для проверки
TIME SWAP - CR ." ZANYALO " . ." sec" ;

MAIN

Без измерения времени выполнения:

50000 41 EULER .
17071 Ok
50000 27941 EULER .
18776 Ok

65000 41 EULER .
21631 Ok
65000 27941 EULER .
23793 Ok

С измерением времени выполнения:

MAIN \ 50000 27941 EULER
18776
ZANYALO 1 sec Ok

MAIN \ 50000 41 EULER
17071
ZANYALO 0 sec Ok

MAIN \ 65000 27941 EULER
23793
ZANYALO 2 sec Ok

MAIN \ 65000 41 EULER
21631
ZANYALO 2 sec Ok

Только при n=100, формула Эйлера с C=41 генерирует больше простых чисел, чем с C=27941. При n = 1000, 10000, 50000 и 65000 - C=27941 "побеждает", генерирует больше простых чисел.

Forth работает только с 32 битными числами (примерно +/- 2 миллиарда). Квадратный корень из 2**31 грубо 46000 плюс значения остальных членов суммы, то есть можем спокойно прогнать n до 45000. При работе с беззнаковыми числами - квадратный корень из 2**32=65536, а это значит, что можем увеличить диапазон до 65000.


Код на Python проще и понятнее (приведен ниже, сравните сами), но выполняется примерно в 15 раз дольше. Также минусом Forth является отсутствие библиотек для работы с длинными числами.

Код для подсчета количества простых чисел, генерируемое формулой Cn=n*n+n+41 (Cn=n*n+n+27941) на ЯП Python.

import time

def is_prime(n):
    if n%2 == 0:
        return 2
    for i in range(3,int(n**0.5)+1,2):
        if n%i == 0:
            return i
    return 1


def Euler(m,k):
    start_time = time.time()
    c=0
    for i in range(m):
        n=i*(i+1)+k
        if is_prime(n)==1:
            c+=1
    end_time = time.time()
    elapsed_time = end_time - start_time
    print(f"Время выполнения: {elapsed_time:.2f} секунд")
    return c

Euler(100,41)
Время выполнения: 0.00 секунд
86
Euler(100,27941)
Время выполнения: 0.00 секунд
77

Euler(1000,41)
Время выполнения: 0.01 секунд
581
Euler(1000,27941)
Время выполнения: 0.03 секунд
599

Euler(10000,41)
Время выполнения: 0.72 секунд
4149
Euler(10000,27941)
Время выполнения: 0.78 секунд
4466

Euler(45000, 41)
Время выполнения: 15.91 секунд
15571
Euler(45000, 27941)
Время выполнения: 16.98 секунд
17075

Euler(50000, 41)
Время выполнения: 19.69 секунд
17071

Euler(50000, 27941)
Время выполнения: 21.69 секунд
18776

Euler(65000, 41)
Время выполнения: 35.07 секунд
21631

Euler(65000, 27941)
Время выполнения: 38.62 секунд
23793

Euler(100000,41)
Время выполнения: 85.23 секунд
31985
Euler(100000,27941)
Время выполнения: 93.43 секунд
35150

 

Двенадцать новых чисел для формулы Эйлера:

Для 55661 процент простых чисел 19214 / 50000 * 100% = 38.428%
Для 72491 процент простых чисел 19120 / 50000 * 100% = 38.24%

115721 19860 / 50000 * 100 % = 39,72%
136517 19392 / 50000 * 100 % = 38,784%

247757 21203 / 50000 * 100 % = 42,406%
239621 19812 / 50000 * 100 % = 39,624%
206807 19248 / 50000 * 100 % = 38,496%

333491 19576 / 50000 * 100 % = 39,152%
361637 19596 / 50000 * 100 % = 39,192%
383681 19193 / 50000 * 100 % = 38,386%

487451 19035 / 50000 * 100 % = 38,07%
460631 18727 / 50000 * 100 % = 37,454%

 

Euler(10000, 55661)
Время выполнения: 0.80 секунд
4544
Euler(50000, 55661)
Время выполнения: 22.43 секунд
19214

Euler(10000, 72491)
Время выполнения: 0.80 секунд
4533
Euler(50000, 72491)
Время выполнения: 22.15 секунд
19120

По сравнению с 41 и 27941, которые дают результаты:

17071 / 50000 * 100% = 34,142%
18776 / 50000 * 100% = 37,552%

 

Euler(10000, 115721)
Время выполнения: 0.85 секунд
4690
Euler(50000, 115721)
Время выполнения: 23.50 секунд
19860

Euler(10000, 136517)
Время выполнения: 0.83 секунд
4609
Euler(50000, 136517)
Время выполнения: 23.15 секунд
19392

Euler(10000, 247757)
Время выполнения: 0.91 секунд
5027
Euler(50000, 247757)
Время выполнения: 25.15 секунд
21203

Euler(10000, 239621)
Время выполнения: 0.86 секунд
4724
Euler(50000, 239621)
Время выполнения: 23.55 секунд
19812

Euler(10000, 206807)
Время выполнения: 0.83 секунд
4601
Euler(50000, 206807)
Время выполнения: 22.77 секунд
19248

Euler(10000, 333491)
Время выполнения: 0.85 секунд
4668
Euler(50000, 333491)
Время выполнения: 23.26 секунд
19576

Euler(10000, 361637)
Время выполнения: 0.85 секунд
4634
Euler(50000, 361637)
Время выполнения: 23.33 секунд
19596

Euler(10000, 383681)
Время выполнения: 0.84 секунд
4612
Euler(50000, 383681)
Время выполнения: 22.72 секунд
19193

Euler(10000, 487451)
Время выполнения: 0.84 секунд
4537
Euler(50000, 487451)
Время выполнения: 22.47 секунд
19035

Euler(10000, 460631)
Время выполнения: 0.81 секунд
4439
Euler(50000, 460631)
Время выполнения: 22.30 секунд
18727

Плюс еще 26 свободных членов для формулы Эйлера для генерации простых чисел:

10000 595937 EULER .
4978 Ok
50000 595937 EULER .
21081 Ok

10000 579431 EULER .
4589 Ok
50000 579431 EULER .
19288 Ok

10000 601037 EULER .
4604 Ok
50000 601037 EULER .
19341 Ok

10000 701147 EULER .
4712 Ok
50000 701147 EULER .
20013 Ok

10000 771581 EULER .
4669 Ok
50000 771581 EULER .
19520 Ok


10000 765197 EULER .
4666 Ok
50000 765197 EULER .
19787 Ok

10000 722231 EULER .
4609 Ok
50000 722231 EULER .
19539 Ok

10000 878357 EULER .
4510 Ok
50000 878357 EULER .
19133 Ok

10000 1544987 EULER .
4809 Ok
50000 1544987 EULER .
20431 Ok

10000 1974881 EULER .
4643 Ok
50000 1974881 EULER .
19932 Ok

10000 1272851 EULER .
4570 Ok
50000 1272851 EULER .
19428 Ok

10000 1840997 EULER .
4563 Ok
50000 1840997 EULER .
19388 Ok

10000 1000817 EULER .
4556 Ok
50000 1000817 EULER .
19467 Ok

10000 1257911 EULER .
4519 Ok
50000 1257911 EULER .
19169 Ok

10000 1850747 EULER .
4511 Ok
50000 1850747 EULER .
19344 Ok

10000 1426697 EULER .
4495 Ok
50000 1426697 EULER .
19234 Ok

10000 1087211 EULER .
4462 Ok
50000 1087211 EULER .
18909 Ok

10000 2640161 EULER .
4798 Ok
50000 2640161 EULER .
20568 Ok

10000 2367767 EULER .
4767 Ok
50000 2367767 EULER .
20428 Ok

10000 2603297 EULER .
4595 Ok
50000 2603297 EULER .
19605 Ok

10000 2719391 EULER .
4580 Ok
50000 2719391 EULER .
19713 Ok

10000 2094341 EULER .
4564 Ok
50000 2094341 EULER .
19397 Ok

10000 2655671 EULER .
4488 Ok
50000 2655671 EULER .
19153 Ok

10000 2039747 EULER .
4440 Ok
50000 2039747 EULER .
19027 Ok

10000 2567177 EULER .
4435 Ok
50000 2567177 EULER .
19276 Ok

10000 2960381 EULER .
4387 Ok
50000 2960381 EULER .
18881 Ok

AI / ИИ на Форте

Игры на JS

JavaScript (JS) — один из самых популярных языков программирования для создания веб-приложений, включая игры. Вот несколько примеров игр, которые можно создать на JavaScript:

Бросок Мяча под углом к горизонту

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

поиграть

Игра Камень, ножницы, бумага

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

поиграть

Игра Кено

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

поиграть

Игра Кости

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

поиграть

Игра Монетка (орел или решка)

Монетка - это игра, в которой бросают монету и делают ставки на то, какой стороной она упадет - орел или решка. Просто нажмите на картинку Орла или Решки, затем на кнопку "Выбрать".

поиграть

Игра Слот-машина

Нажмите кнопку "Испытать судьбу", чтобы получить символы в случайном порядке. Игрок выигрывает, если выпадает три одинаковые фигуры

поиграть

Игра Виселица

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

поиграть

Игра Угадайка

Знакомая с детства игра. Просто введите число от 1 до 100. Решите математическую задачу: за какое максимальное количество ходов гарантированно можно угадать число.

поиграть

Игра Питон

Игра "Питон" ("Змейка") - это цифровое воплощение простоты и увлекательности. В ней игрок управляет змеей, которая ползет по пиксельному миру в поисках яблок и других фруктов и овощей. С каждым съеденным фруктом змея удлиняется, а игра ускоряется. Это испытание ловкости, стратегии и терпения, где каждое движение может привести к новому рекорду или неожиданному концу. Змея скользит между препятствиями, создавая узоры на экране, напоминающие танец в бесконечном лабиринте. Эта игра - отражение эры ретро-игр, где простые концепции превращаются в часы захватывающего геймплея.

поиграть

Библиотеки и движки для создания игр на JS:

  • Phaser.js: Популярный игровой фреймворк для 2D-игр. Предлагает множество инструментов для создания игр, начиная от управления анимацией и физикой, заканчивая аудио поддержкой и управлением пользователем.
  • Three.js: Используется для создания 3D-графики в браузере, включая сложные игры с трёхмерными мирами.
  • Babylon.js: Еще один мощный фреймворк для разработки 3D-игр и приложений в браузере.
  • p5.js: Библиотека, подходящая для создания интерактивных графических приложений, включая игры.

AI / ИИ на Форте.

Работа с элементарной ИИ на Форте не является сложной задачей. Продемонстрируем это.

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

x1=0 x2=0 y_true=0
x1=0 x2=1 y_true=0
x1=1 x2=0 y_true=0
x1=1 x2=1 y_true=1

Можете заметить, что вводам x1 и x2 сопоставляется их логическое "И".

Подключим библиотеку для работы с вещественными числами.

S" lib/include/float2.f" INCLUDED

Нам понадобятся переменные w1, w2 - веса; b - смещение (сразу инициализируем все три нулями); x1, x2 - входные значения; learning_rate - шаг обучения, для определенности взят за "0.1"; y_true - соответствующее истинное значение из тестовой выборки.

FVARIABLE w1
FVARIABLE w2
FVARIABLE b
0E w1 F!
0E w2 F!
0E b F!
FVARIABLE x1 FVARIABLE x2
FVARIABLE learning_rate
0.1E learning_rate F!
FVARIABLE y_true

Напишем слово моделирующее поведение персептрона (назовем его "P"), которое просто вычисляет выход по формуле:

y_pred = x1*w1+x2*w2+b

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

\ x1 w1 x2 w2 b P - формат вызова слова
: P ( F: x1 w1 x2 w2 b -> F: y_pred ) FSWAP FROT F* F+ FSWAP FROT F* F+ F0< IF 0E ELSE 1E THEN ;

Проверим работу слова на случайных данных:

1E 2E 3E 5E 1000E P F.
1.0000000 Ok

1*2+3*5+1000 = 1017, что явно больше нуля, следовательно, результат работы 1. Персептрон работает корректно.

Самое важное слово производящее тренировку персептрона назван - "T" (от слова Train). Входом служат исходные параметры x1, x2 и соответствующее им истинное значение, а вместо выхода - изменение переменных w1, w2 и b, что обозначено в комментарии стековой нотации буквой "V:" (от слова "VARIABLE").

: T ( F: x1 x2 y_true -> V: w1 w2 b ) \ x1 x2 y_true T - формат вызова слова
    y_true F! \ x1 x2 y_true -> x1 x2
    FOVER x1 F! FDUP x2 F! \ x1 x2 -> x1 x2 x1=x1 x2=x2
    w1 F@ FSWAP w2 F@ b F@ \ x1 x2 -> x1 w1 x2 w2 b
    P \ x1 w1 x2 w2 b -> y_pred
    y_true F@ FSWAP F- \ y_pred -> y_true-y_pred=error
    learning_rate F@ F* \ error -> error*learning_rate

    FDUP x1 F@ F* w1 F@ F+ w1 F! \ error*learning_rate -> error*learning_rate w1=error*learning_rate*x1+w1
    FDUP x2 F@ F* w2 F@ F+ w2 F! \ error*learning_rate -> error*learning_rate w2=error*learning_rate*x2+w2
    b F@ F+ b F! \ error*learning_rate -> b=error*learning_rate+b
    ." Обновленные веса: w1 = " w1 F@ F. ." w2 = " w2 F@ F. ." b = " b F@ F. CR
;

Первая строка - описание слова.
Вторая - сохранение значения "y_true" в одноименной переменной.
Третья, аналогично предыдущей, сохранение значений x1, x2.
Четвертая - получаем значения переменных w1, w2 и b, одновременно выстраиваем их в том порядке, которая соответствует стековой нотации слова "P".
Пятая вызываем "P" (работа которой описана выше).
В шестой считаем ошибку по формуле error = y_true-y_pred.
В седьмой умножаем на шаг обучения, чтобы в
в девятой, десятой и одиннадцатой корректируются значения переменных w1, w2 и b по формулам:

w1=error*learning_rate*x1
w2=error*learning_rate*x2
b=error*learning_rate

Двенадцатая - вывод значения обновленных весов (контрольная информация о работе слова).

Можно протестировать это слово на следующих данных:

0E 0E 0E T
0E 1E 0E T
1E 0E 0E T
1E 1E 1E T

Окончательно можем написать слово "epochs", которая проведет обучение на тестовой выборке.

: epochs ( N -> )
    0 DO
    ." Эпоха " I . CR
    0E 0E 0E T
    0E 1E 0E T
    1E 0E 0E T
    1E 1E 1E T
    CR
    LOOP ;

Она просто прогоняет N раз (количество эпох) обучение на тестовых данных с выводом результатов о проделанной работе.

Запустим его с параметром 10.

10 epochs
Эпоха 0
Обновленные веса: w1 = 0.1000000 w2 = 0.1000000 b = -0.1000000
Обновленные веса: w1 = 0.1000000 w2 = 0.0000000 b = -0.2000000
Обновленные веса: w1 = 0.1000000 w2 = 0.0000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.1000000

Эпоха 1
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.1000000
Обновленные веса: w1 = 0.2000000 w2 = 0.0000000 b = -0.2000000
Обновленные веса: w1 = 0.1000000 w2 = 0.0000000 b = -0.3000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000

Эпоха 2
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000

Эпоха 3
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000

Эпоха 4
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000

Эпоха 5
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000

Эпоха 6
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000

Эпоха 7
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000

Эпоха 8
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000

Эпоха 9
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000
Обновленные веса: w1 = 0.2000000 w2 = 0.1000000 b = -0.2000000

Ok

Обратим внимание, что, начиная с Эпохи 2, веса w1 и w2, а также b не меняются (если предварительно не тестировать работу слова "T", то с Эпохи 3).

Проверим "натренированность" весов и смещения, для чего напишем последнее слово "PREDICT", которая будет предсказывать выход "y".

: PREDICT ( x1 x2 -> y. )
    w1 F@ FSWAP w2 F@ b F@ P F.
;

Работа которого заключается в том, чтобы подготовить параметры для слова "P". Проверим качество тренировки:

0E 0E PREDICT
0.0000000 Ok

0E 1E PREDICT
0.0000000 Ok

1E 0E PREDICT
0.0000000 Ok

1E 1E PREDICT
1.0000000 Ok

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

В слове "T" добавляем три строки преобразующие "x1 x2 y_true" из целочисленного в вещественный формат

: T ( x1 x2 y_true -> V: w1 w2 b ) \ x1 x2 y_true T - формат вызова слова
    ROT S>D D>F
    SWAP S>D D>F
    S>D D>F
    y_true F! \ x1 x2 y_true -> x1 x2
    FOVER x1 F! FDUP x2 F! \ x1 x2 -> x1 x2 x1=x1 x2=x2
    w1 F@ FSWAP w2 F@ b F@ \ x1 x2 -> x1 w1 x2 w2 b
    P \ x1 w1 x2 w2 b -> y_pred
    y_true F@ FSWAP F- \ y_pred -> y_true-y_pred=error
    learning_rate F@ F* \ error -> error*learning_rate

    FDUP x1 F@ F* w1 F@ F+ w1 F! \ error*learning_rate -> error*learning_rate w1=error*learning_rate*x1+w1
    FDUP x2 F@ F* w2 F@ F+ w2 F! \ error*learning_rate -> error*learning_rate w2=error*learning_rate*x2+w2
    b F@ F+ b F! \ error*learning_rate -> b=error*learning_rate+b
    ." Обновленные веса: w1 = " w1 F@ F. ." w2 = " w2 F@ F. ." b = " b F@ F. CR
;

Также изменится "epochs" которое вызывает уже исправленное "T".

: epochs ( N -> )
    0 DO
    ." Эпоха " I . CR
    0 0 0 T
    0 1 0 T
    1 0 0 T
    1 1 1 T
    CR
    LOOP ;

И наконец, в "PREDICT" преобразуем вход "x1 x2" в вещественный, а результат "y." из вещественного (точка в конце обозначает тот факт, что он печатается на экран, а не остается на стеке).

: PREDICT ( x1 x2 -> y. )
    SWAP S>D D>F
    S>D D>F
    w1 F@ FSWAP w2 F@ b F@ P F>D D>S .
;

результат тренировки будет выглядеть так:

0 0 PREDICT
0 Ok
0 1 PREDICT
0 Ok
1 0 PREDICT
0 Ok
1 1 PREDICT
1 Ok

 

 

Логическое "ИЛИ"

Возьмем другую серию данных. Теперь вводам сопоставим их логическое "ИЛИ".

x1=0 x2=0 y_true=0
x1=0 x2=1 y_true=1
x1=1 x2=0 y_true=1
x1=1 x2=1 y_true=1

в коде предыдущего примера изменится только слово:

: epochs ( N -> )
    0 DO
    ." Эпоха " I . CR
    0E 0E 0E T
    0E 1E 1E T
    1E 0E 1E T
    1E 1E 1E T
    CR
    LOOP ;

После обучения, слово PREDICT выдаст следующие результаты:

0E 0E PREDICT
0.0000000 Ok

0E 1E PREDICT
1.0000000 Ok

1E 0E PREDICT
1.0000000 Ok

1E 1E PREDICT
1.0000000 Ok

Проверьте это самостоятельно. Заметим, что с Эпохи 2 коэффициенты перестают меняться.

 


Операция "Исключающее ИЛИ"

Теперь исходные данные будут выглядеть так:

x1=0 x2=0 y_true=0
x1=0 x2=1 y_true=1
x1=1 x2=0 y_true=1
x1=1 x2=1 y_true=0

Аналогично изменится только слово "epochs":

: epochs ( N -> )
    0 DO
    ." Эпоха " I . CR
    0E 0E 0E T
    0E 1E 1E T
    1E 0E 1E T
    1E 1E 0E T
    CR
    LOOP ;

После обучения (тоже 10 эпох), получим:

0E 0E PREDICT
1.0000000 Ok

0E 1E PREDICT
1.0000000 Ok

1E 0E PREDICT
0.0000000 Ok

1E 1E PREDICT
0.0000000 Ok

Что не является правильным результатом. Даже после Эпохи 9 коэффициенты меняются. Можете по экспериментировать самостоятельно с гораздо большим количеством эпох. Результат аналогичный даже после 1000 эпох ("1000 epochs"). Задача "Исключающее ИЛИ" не разрешима на персептроне, необходимо более сложные модели для такой простой операции.

Чтобы получить корректные результаты для каждого примера вводите код заново в новое окно консоли, или инициализируйте переменные заново:

0E w1 F!
0E w2 F!
0E b F!

 


Пример 1 - логическое "И" (окончательный код, можно "копи пастить")

S" lib/include/float2.f" INCLUDED

FVARIABLE w1
FVARIABLE w2
FVARIABLE b
0E w1 F!
0E w2 F!
0E b F!
FVARIABLE x1 FVARIABLE x2
FVARIABLE learning_rate
0.1E learning_rate F!
FVARIABLE y_true

: P ( F: x1 w1 x2 w2 b -> F: y_pred ) FSWAP FROT F* F+ FSWAP FROT F* F+ F0< IF 0E ELSE 1E THEN ;

: T ( F: x1 x2 y_true -> V: w1 w2 b ) \ x1 x2 y_true T - формат вызова слова
y_true F! \ x1 x2 y_true -> x1 x2
FOVER x1 F! FDUP x2 F! \ x1 x2 -> x1 x2 x1=x1 x2=x2
w1 F@ FSWAP w2 F@ b F@ \ x1 x2 -> x1 w1 x2 w2 b
P \ x1 w1 x2 w2 b -> y_pred
y_true F@ FSWAP F- \ y_pred -> y_true-y_pred=error
learning_rate F@ F* \ error -> error*learning_rate

FDUP x1 F@ F* w1 F@ F+ w1 F! \ error*learning_rate -> error*learning_rate w1=error*learning_rate*x1+w1
FDUP x2 F@ F* w2 F@ F+ w2 F! \ error*learning_rate -> error*learning_rate w2=error*learning_rate*x2+w2
b F@ F+ b F! \ error*learning_rate -> b=error*learning_rate+b
." Обновленные веса: w1 = " w1 F@ F. ." w2 = " w2 F@ F. ." b = " b F@ F. CR
;

: epochs ( N -> )
0 DO
." Эпоха " I . CR
0E 0E 0E T
0E 1E 0E T
1E 0E 0E T
1E 1E 1E T
CR
LOOP ;

10 epochs

: PREDICT ( x1 x2 -> y. )
w1 F@ FSWAP w2 F@ b F@ P F.
;

0E 0E PREDICT

0E 1E PREDICT

1E 0E PREDICT

1E 1E PREDICT

 


Пример 2 - логическое "ИЛИ"

S" lib/include/float2.f" INCLUDED

FVARIABLE w1
FVARIABLE w2
FVARIABLE b
0E w1 F!
0E w2 F!
0E b F!
FVARIABLE x1 FVARIABLE x2
FVARIABLE learning_rate
0.1E learning_rate F!
FVARIABLE y_true

: P ( F: x1 w1 x2 w2 b -> F: y_pred ) FSWAP FROT F* F+ FSWAP FROT F* F+ F0< IF 0E ELSE 1E THEN ;

: T ( F: x1 x2 y_true -> V: w1 w2 b ) \ x1 x2 y_true T - формат вызова слова
y_true F! \ x1 x2 y_true -> x1 x2
FOVER x1 F! FDUP x2 F! \ x1 x2 -> x1 x2 x1=x1 x2=x2
w1 F@ FSWAP w2 F@ b F@ \ x1 x2 -> x1 w1 x2 w2 b
P \ x1 w1 x2 w2 b -> y_pred
y_true F@ FSWAP F- \ y_pred -> y_true-y_pred=error
learning_rate F@ F* \ error -> error*learning_rate

FDUP x1 F@ F* w1 F@ F+ w1 F! \ error*learning_rate -> error*learning_rate w1=error*learning_rate*x1+w1
FDUP x2 F@ F* w2 F@ F+ w2 F! \ error*learning_rate -> error*learning_rate w2=error*learning_rate*x2+w2
b F@ F+ b F! \ error*learning_rate -> b=error*learning_rate+b
." Обновленные веса: w1 = " w1 F@ F. ." w2 = " w2 F@ F. ." b = " b F@ F. CR
;

: epochs ( N -> )
0 DO
." Эпоха " I . CR
0E 0E 0E T
0E 1E 1E T
1E 0E 1E T
1E 1E 1E T
CR
LOOP ;

10 epochs

: PREDICT ( x1 x2 -> y. )
w1 F@ FSWAP w2 F@ b F@ P F.
;

0E 0E PREDICT

0E 1E PREDICT

1E 0E PREDICT

1E 1E PREDICT

 


Пример 3 - "Исключающее ИЛИ"

S" lib/include/float2.f" INCLUDED

FVARIABLE w1
FVARIABLE w2
FVARIABLE b
0E w1 F!
0E w2 F!
0E b F!
FVARIABLE x1 FVARIABLE x2
FVARIABLE learning_rate
0.1E learning_rate F!
FVARIABLE y_true

: P ( F: x1 w1 x2 w2 b -> F: y_pred ) FSWAP FROT F* F+ FSWAP FROT F* F+ F0< IF 0E ELSE 1E THEN ;

: T ( F: x1 x2 y_true -> V: w1 w2 b ) \ x1 x2 y_true T - формат вызова слова
y_true F! \ x1 x2 y_true -> x1 x2
FOVER x1 F! FDUP x2 F! \ x1 x2 -> x1 x2 x1=x1 x2=x2
w1 F@ FSWAP w2 F@ b F@ \ x1 x2 -> x1 w1 x2 w2 b
P \ x1 w1 x2 w2 b -> y_pred
y_true F@ FSWAP F- \ y_pred -> y_true-y_pred=error
learning_rate F@ F* \ error -> error*learning_rate

FDUP x1 F@ F* w1 F@ F+ w1 F! \ error*learning_rate -> error*learning_rate w1=error*learning_rate*x1+w1
FDUP x2 F@ F* w2 F@ F+ w2 F! \ error*learning_rate -> error*learning_rate w2=error*learning_rate*x2+w2
b F@ F+ b F! \ error*learning_rate -> b=error*learning_rate+b
." Обновленные веса: w1 = " w1 F@ F. ." w2 = " w2 F@ F. ." b = " b F@ F. CR
;

: epochs ( N -> )
0 DO
." Эпоха " I . CR
0E 0E 0E T
0E 1E 1E T
1E 0E 1E T
1E 1E 0E T
CR
LOOP ;

10 epochs

: PREDICT ( x1 x2 -> y. )
w1 F@ FSWAP w2 F@ b F@ P F.
;

0E 0E PREDICT

0E 1E PREDICT

1E 0E PREDICT

1E 1E PREDICT


Как и было сказано ранее отличие всех трех примеров только в коде слова "epochs".

Шахматы 

Шахматы — это настольная стратегическая игра, которая играется на квадратной доске размером 8x8 клеток. В игре участвуют два игрока, каждый из которых управляет армией из 16 фигур: 1 король, 1 ферзь, 2 ладьи, 2 слона, 2 коня и 8 пешек. Основная цель игры — поставить мат королю противника, то есть создать такую позицию, при которой король соперника не может избежать взятия.

Основные правила и фигуры:

  1. Фигуры и их ходы:

    • Король: Ходит на одну клетку в любом направлении.
    • Ферзь: Ходит на любое количество клеток по горизонтали, вертикали или диагонали.
    • Ладья: Ходит на любое количество клеток по горизонтали или вертикали.
    • Слон: Ходит на любое количество клеток по диагонали.
    • Конь: Ходит буквой "Г" — две клетки в одном направлении и одна в перпендикулярном. Конь — единственная фигура, которая может перепрыгивать через другие фигуры.
    • Пешка: Ходит на одну клетку вперед, но бьет на одну клетку по диагонали. На первом ходе может сделать два шага вперед. Если пешка достигает последнего ряда (8-го или 1-го), она может быть превращена в любую другую фигуру (чаще всего в ферзя).
  2. Цель игры:

    • Шах: Это ситуация, когда король находится под угрозой взятия. Игрок должен устранить угрозу, иначе он проиграет.
    • Шах и мат: Это ситуация, при которой король находится под шахом и не может избежать взятия в следующий ход. Это завершает игру, и игрок, поставивший мат, побеждает.
    • Пат: Это ситуация, при которой игрок, чей ход, не может сделать ни одного допустимого хода, но при этом его король не находится под шахом. Пат приводит к ничьей.
  3. Дополнительные правила:

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

Стратегия и тактика:

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

История и культура:

Шахматы имеют долгую историю, восходящую к Индии VI века, где игра, известная как "чатуранга", была предшественником современных шахмат. Со временем шахматы распространились по всему миру, приобретая популярность в различных культурах.

Сегодня шахматы играют важную роль в культуре и спорте, с миллионами игроков по всему миру и множеством международных турниров, включая престижный матч за звание чемпиона мира. В последние годы интерес к шахматам возрос благодаря доступности онлайн-игр и популярным сериалам, таким как "Ход королевы" (The Queen's Gambit).

8 ферзей

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

Перейдя по ссылке вы увидите все эти варианты на отдельной странице.

Ферзь 8 x 8

Разместить 5 ферзей на шахматной доске размером 5 на 5 возможно 10 способами

Ферзь 5 x 5

Разместить 6 ферзей на шахматной доске размером 6 на 6 возможно 4 способами

Ферзь 6 x 6

Разместить 7 ферзей на шахматной доске размером 7 на 7 возможно 40 способами

Ферзь 7 x 7

Размещение 2, 3, 4 Ферзей на полях соответствующих размеров при аналогичном условии невозможно (тривиальный случай одного ферзя на поле 1 x 1 не рассматриваем).

Разместить 9 ферзей на шахматной доске размером 9 на 9 возможно 352 способами

Ферзь 9 x 9

Разместить 10 ферзей на шахматной доске размером 10 на 10 возможно 726 способами

Ферзь 10 x 10