Программисты, программы и искусственный интеллект::Журнал СА 4.2007
www.samag.ru
     
Поиск   
              
 www.samag.ru    Web  0 товаров , сумма 0 руб.
E-mail
Пароль  
 Запомнить меня
Регистрация | Забыли пароль?
Журнал "Системный администратор"
Журнал «БИТ»
Наука и технологии
Подписка
Где купить
Авторам
Рекламодателям
Магазин
Архив номеров
Вакансии
Контакты
   

  Опросы

Какие курсы вы бы выбрали для себя?  

Очные
Онлайновые
Платные
Бесплатные
Я и так все знаю

 Читать далее...

1001 и 1 книга  
20.12.2019г.
Просмотров: 5397
Комментарии: 0
Dr.Web: всё под контролем

 Читать далее...

04.12.2019г.
Просмотров: 6594
Комментарии: 0
Особенности сертификаций по этичному хакингу

 Читать далее...

28.05.2019г.
Просмотров: 7877
Комментарии: 2
Анализ вредоносных программ

 Читать далее...

28.05.2019г.
Просмотров: 8168
Комментарии: 1
Микросервисы и контейнеры Docker

 Читать далее...

28.05.2019г.
Просмотров: 7165
Комментарии: 0
Django 2 в примерах

 Читать далее...

Друзья сайта  

Форум системных администраторов  

sysadmins.ru

 Программисты, программы и искусственный интеллект

Архив номеров / 2007 / Выпуск №4 (53) / Программисты, программы и искусственный интеллект

Рубрика: Программирование /  Программирование

Алексей Мичурин

Программисты, программы и искусственный интеллект

Боюсь, – проговорил он наконец, – что Вопрос и Ответ – вещи взаимоисключающие.

 Знание одного в силу самой логики исключает знание другого.

В рамках одной Вселенной невозможно знание Вопроса и Ответа сразу.

 

Путеводитель хитч-хайкера по Галактике.

Жизнь, Вселенная и всё остальное.

Дуглас Адамс

Вопрос возможности существования искусственного интеллекта сродни вопросу о существовании разума на других планетах и вопросу «Одиноки ли мы во Вселенной?». Поэтому он всегда будет будоражить умы человечества. Он порождает множество новых вопросов: Что такое разум? Какие он может иметь формы? Как определить наличие или отсутствие разума?.. Но эти вопросы лежат далеко за пределами вопросов программирования, давайте оставим иx философам и остановимся на наиболее прикладных вопросах, которые, тем не менее, вплотную соприкасаются с вопросами искусственного интеллекта.

Компьютер и машина Тьюринга

Прежде чем я буду использовать слова «компьютер» и «машина Тьюринга» как синонимы, нельзя не затронуть вопрос, что такое машина Тьюринга.

Определения машины Тьюринга как такового нет, поэтому я позволю себе рассказать своими словами.

Простейшая машина Тьюринга

Машина Тьюринга – это воображаемый аппарат со следующими характеристиками:

  • машина имеет конечное количество состояний и всегда находится в одном из них;
  • существует допускающее состояние, попадая в которое, машина заканчивает работу;
  • существует отклоняющее состояние, попадая в которое машина завершает работу с ошибкой;
  • машина работает над воображаемой бесконечной магнитной лентой, на которой записаны «символы» из некоторого конечного набора (алфавита);
  • машина может считать «символ», находящийся под магнитной головкой;
  • машина может писать сама на магнитную ленту;
  • машина может сдвигать свою магнитную головку на шаг вправо или влево;
  • машина «знает» набор правил вида: «если головка находится над символом X и машина находится в состоянии A, то следует записать на ленту символ Y, сдвинуть головку вправо или влево и перевести машину в состояние B»;
  • и конечно, у машины есть начальное состояние и начальное положение магнитной головки.

Звучит запутанно и скучновато? Давайте разберём пример. Создадим машину, которая вычитает два числа.

Входные данные на ленте представим в унарном коде. Начало записи обозначим символом «#», конец – символом «;». Уменьшаемое будем кодировать символом «a», вычитаемое – символом «b» и ещё добавим к алфавиту символ «.»; это будет «пробел».

Короче говоря, данные для операции «5-3» будут кодироваться строкой «#aaaaabbb;».

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

Для реализации такой машины нам достаточно два «рабочих» состояния, назовём их «X» и «Y», кроме них, конечно, у нас будет допускающее состояние «T» (true) и запрещающее состояние «F» (false).

Правила для машины, выполняющей такое вычитание, можно записать так:

(X ;) -> (; R T)

(X #) -> (# R X)

(X .) -> (. R X)

(X a) -> (a R X)

(X b) -> (. L Y)

(Y ;) -> (; R F)

(Y #) -> (# R F)

(Y .) -> (. L Y)

(Y a) -> (. R X)

(Y b) -> (b L Y)

Подобным образом обычно записываются машины Тьюринга, запись очень проста. Например, первая строчка означает, что если машина находилась в состоянии «X» и головка стояла на знаке «;», то следует записать знак «;» (то есть не вносить изменений), передвинуть головку на шаг вправо (буква «R») и перейти в состояние «T».

Осталось только добавить, что начальным состоянием у нас будет «X», а магнитная головка вначале будет находиться над первым символом ленты.

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

#include <stdio.h>

int MT (char *d) {

  char s, *p;

  p=d;   /* магнитная головка */

  s='X'; /* стояние */

  for (;;) {

    printf("d=%s s=%c p=%c\n", d, s, *p);

    if (s == 'X') {

      if (*p == ';') return 1;

      if (*p == '#')         p++;

      if (*p == '.')         p++;

      if (*p == 'a')         p++;

      if (*p == 'b') *p='.', p--, s='Y';

    }

    if (s == 'Y') {

      if (*p == ';') return -1;

      if (*p == '#') return -1;

      if (*p == '.')         p--;

      if (*p == 'a') *p='.', p++, s='X';

      if (*p == 'b')         p--;

    }

  }

  return 0;

}

int main (void) {

  int r;

  char data[]="#aaaaabbb;";

  r=MT(data);

  printf("\n result=%d\n data=%s\n", r, data);

  return 0;

}

Функция MT как раз и реализует описанную машину. Она производит вычитание и возвращает «1» в случае успеха или «-1» в случае ошибки.

Теперь, я думаю, логика работы этой машины всем понятна: находясь в состоянии «X», она сканирует строку справа налево, в поисках первого символа «b». Найдя «b», она его стирает и переходит в состояние «Y», в котором сканирует строку слева направо в поисках «а». Обнаружив «а», она его стирает и переходит в состояние «X».

Результат работы программы будет вот таким:

d=#aaaaabbb; s=X p=#

d=#aaaaabbb; s=X p=a

d=#aaaaabbb; s=X p=a

d=#aaaaabbb; s=X p=a

d=#aaaaabbb; s=X p=a

d=#aaaa..bb; s=X p=.

d=#aaaa...b; s=Y p=.

d=#aaa....b; s=X p=.

d=#aaa....b; s=X p=.

d=#aaa....b; s=X p=.

d=#aaa.....; s=Y p=.

d=#aaa.....; s=Y p=.

d=#aaa.....; s=Y p=.

d=#aa......; s=X p=.

d=#aa......; s=X p=.

d=#aa......; s=X p=.

d=#aa......; s=X p=.

d=#aa......; s=X p=.

d=#aa......; s=X p=;

 result=1

 data=#aa......;

Окончательная строка с двумя буквами «a» говорит, что машина вычислила «5-3=2».

Важно отметить, что машину Тьюринга можно закодировать – записать в виде последовательности символов. Способы могут быть самыми разными (вы уже видели два из них).

Разновидности машин Тьюринга

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

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

Компьютеры, программы и машина Тьюринга

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

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

Например, когда процессор выполняет операцию 2+2 с точки зрения Тьюринга это выглядит как правило «если состояние машины (регистров процессора) является [ax=2, dx=2], а магнитная головка считала код операции «+», то следует изменить состояние на [ax=4, dx=2], записать «+» (то есть не вносить изменений) и передвинуть головку на шаг вправо». Мы выполнили операцию:

ax := ax + dx

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

Но несмотря на все свои возможности, компьютер даже слабее, чем машина Тьюринга. (Говоря о «слабости» или «силе», мы, конечно, имеем в виду не производительность, а круг задач, которые устройство способно решить за сколь угодно большое, но всё же конечное время.) Любая машина Тьюринга работает над бесконечной лентой, память же компьютера ограничена.

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

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

Всесилен ли компьютер?

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

Одна из фундаментальных задач, не поддающихся решению, это задача останова.

Задача формулируется очень просто: по имеющейся записи машины Тьюринга (или попросту – программы) определить, остановится ли она или будет работать вечно. Ответ надо дать, естественно, за конечное время.

Это фундаментальная задача, решение которой сулит невероятный рывок в разработках компиляторов и интерпретаторов, беспрецедентный прорыв в криптографии и многое другое. Хотите получить «нобеля» – решите задачу останова (я не шучу!).

К сожалению (или к счастью?), существует очень простое доказательство её неразрешимости. (Впервые этот факт доказал Алан Матисон Тьюринг в 1936 году.) И я не могу отказать себе в удовольствии изложить суть этого изящного доказательства.

Доказательство неразрешимости задачи останова

Я буду говорить на С-образном алгоритмическом языке, более понятном большинству программистов. Для наглядности функции я буду обозначать большими буквами, а строки – маленькими.

Предположим, что мы реализовали функцию S(m,d), которая принимает два аргумента: строку m (machine) с закодированной программой (или функцией) и d (data) – данные для этой программы; а возвращает ture или false в зависимости от того, остановится ли программа или будет работать вечно.

Естественно, зависнет программа или нет, можно сказать, только если знать, какие данные будут ей переданы. Поэтому мы передаём функции S и закодированную машину, и строку данных.

Давайте создадим функцию F(x), реализующую следующий алгоритм:

F(x) {

  if (S(x,x)) for(;;)

}

Строку, кодирующую эту функцию, обозначим f. Что будет, если мы вызовем S(f,f)?

Возможны два варианта:

  • функция вернёт true, то есть F(f) не зависнет, но тогда (посмотрите на логику функции) функция зависнет – мы пришли к противоречию;
  • функция S(f,f) вернёт false, то есть F(f) зависнет, но тогда внутри функции F бесконечный цикл не выполнится, а значит, функция не зависнет – снова противоречие.

Парадокс возник из-за нашего первого предположения: «Предположим, что мы реализовали функцию S(m,d), которая...» А значит, оно неверно.

Всесилен ли человек?

Опытный программист может возразить: «Это только бездушная железяка не может понять, зависнет ли она, но я-то всегда смогу дать ответ, прочитав внимательно код». К сожалению, доказать неправомочность этого заявления я не смогу, так как в моём распоряжении просто нет строгого определения «программиста». Мне остаётся только апеллировать к контрпримерам. Вот один из многих.

Поиск совершенных чисел

«Совершенное число» – это не красивое сочетание слов, а математический термин. Так называются числа, равные сумме своих делителей. Например, 6 делится на 1, 2 и 3. Сумма делителей равна самому числу. Такими же свойствами обладают числа 28 (1+2+4+7+14=28), 496, 8128, 33550336, 8589869056... Как вы понимаете, эти числа тесно связаны с вопросами разложения на множители, поиском делителей и больших простых чисел. Ещё Евклид обнаружил, а Эйлер строго доказал связь совершенных чисел с числами Мерсенна: каждому простому числу Мерсенна соответствует чётное совершенное число, и наоборот. А те, кто занимается криптографией и генерацией случайных чисел, конечно, знают, какую важную роль играют в этой науке числа Мерсенна.

Так вот. До сих пор неизвестно, бывают ли нечётные совершенные числа. Неизвестно даже, сколько существует совершенных чисел, конечно или бесконечно их число.

Таким образом, несложно реализовать программу, перебирающую все нечётные числа, проверяющую, является ли число совершенным и заканчивающую работу, только если таковое обнаружено.

Остановится ли такая программа? Пока ни одни человек не знает ответа на этот вопрос. Хотя, может оказаться, что в этом частном случае задача поддаётся решению. Неразрешимость этой задачи также не доказана.

«Горячие головы» скажут, что программа остановится как минимум из-за переполнения, но, согласитесь, что это не ответ. Самое большое совершенное число, обнаруженное на сегодняшний день, записывается 18,304,103 десятичными знаками (http://www.mersenne.org/perfect9.txt), это более 7 Мб в двоичном представлении. (Да-да! Человечество проявляет большое упорство в поисках этих чисел, а их свойства интересуют не только теоретиков, но и спецслужбы.)

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

Тезис Тьюринга-Чёрча

Все эти факты наводят на мысль о том, что возможности человека и компьютера имеют сходные пределы.

Равенство этих возможностей постулирует так называемый физический (или сильный) тезис Чёрча-Тьюринга, который гласит: «Любая функция, которая может быть вычислена физическим устройством (в том числе, конечно, и человеческим мозгом), может быть вычислена машиной Тьюринга». То есть всё, что может сделать человек, может сделать и компьютер.

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

Кажется, что у человека остаётся только одно преимущество перед машиной – свободная воля.

Свобода воли у человека и у компьютера

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

Сначала давайте убедимся в том, что свобода воли есть у нас. Загадайте одно из двух – «чёрное» или «белое». Получилось? Повторите попытку несколько раз. Поздравляю! Вы в очередной раз воспользовались своей свободой и получили последовательность, которую я не могу угадать. Вы выбирали цвета не случайным, но и не предсказуемым, индивидуальным образом. Может ли делать тоже самое компьютер, руководствуясь некой программой?

Давайте рассмотрим «элементарный» клеточный автомат.

Пусть программа работает над клетчатой лентой, клетки могут быть чёрными и белыми, каждое новое состояние ленты получается из предыдущего по простому правилу. Программа рассматривает саму клетку и две соседние клетки (справа и слева). Так из каждой тройки мы получаем новое значение. Правила таковы:

БББ -> Б

ЧББ -> Ч

БЧБ -> Ч

ЧЧБ -> Ч

ББЧ -> Ч

ЧБЧ -> Б

БЧЧ -> Б

ЧЧЧ -> Б

Букой «Б» я обозначил «белое», а «Ч» – «чёрное».

В самом простом случае если изначально на ленте была только одна чёрная клетка, то мы получим развитие событий, показанное на рисунке.

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

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

Самым интересным здесь является поведение центральной клетки (она выделена). Ни один статистический тест пока не выявил никакой закономерности в её поведении. (Stephen Wolfram использует именно этот механизм для генерации случайных чисел в пакете «Mathematica», http://www.wolfram.com.)

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

Скептики могут сразу возразить, что никакой свободы здесь нет, если заложить ту же самую программу в любой компьютер, то он воспроизведёт тот же результат. Посмею отклонить это поспешное возражение, и вот почему.

Представьте, что технологии развились настолько, что стало возможным создавать идеальные копии частей пространства. Представьте теперь, что создана стопроцентная копия вас (со всеми вашими воспоминаниями, опытом, чувствами и мыслями) и всего вашего окружения (всего, что вы видите и чувствуете). Теперь вас просят загадать последовательность чёрных и белых клеток; и вашего клона просят сделать тоже самое. Я подозреваю (хотя и не могу проверить), что экспериментаторы получат одинаковые последовательности.

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

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

Искусственный интеллект

Итак, к чему же мы пришли? Компьютерная программа имеет ограничения, но и человеческий мозг не всесилен. Человек может проявлять свободу воли – вести себя индивидуально и непредсказуемо. Но такое же поведение может обнаруживать и элементарная программа.

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

Несколько ответов скептикам

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

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

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

Многие и многие программы написаны так, чтобы ответ выдавался в определённый срок, ценой точности этого ответа. Если бы прогноз погоды на завтра можно было рассчитывать месяц, то можно было бы получить гораздо более достоверный результат, если бы у «поисковика» был часок на раздумье, то результаты поиска были бы намного точнее, если бы при игре в шахматы компьютер мог просчитать все ходы до конца партии (а количество вариантов превышает количество атомов во Вселенной), то выиграть у него было бы невозможно... В общем, всё как у людей: либо быстро и приблизительно, либо медленно и (если получится) точно.

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

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

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

Каким же будет искусственный интеллект?

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

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

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

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

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

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

Действительно. Работая над созданием искусственного интеллекта, доживём ли мы до счастливого дня, когда сможем с облегчением выдохнуть и сказать: «Всё! Работа завершена»?

Скорее всего – нет. Такой день не наступит.

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

Если вы спросите меня: «Так каким же будет искусственный разум?», я отвечу: «Непостижимым». А каким ещё может быть настоящий разум?

Напоследок

Мне хотелось бы посоветовать всем интересующимся этими вопросам как минимум две книжки.

Первая – «Классика программирования: алгоритмы, языки, автоматы, компиляторы», Мозговой М.В.

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

Вторая – «Глаз разума», Д. Хофштадтер и Д. Деннетт.

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

Приложение

Автореферативные парадоксы и самосознание

Любопытно, что парадокс возникает при попытке машины Тьюринга проанализировать саму себя. Эта ситуация не нова, автореферативные парадоксы, такие как «Это утверждение ложно», известны давно. Многие психологи, логики, философы и специалисты по искусственному интеллекту полагают, что именно подобные парадоксы позволяют разуму выделить Себя. Например, я могу спокойно заявить «Уважаемый читатель не знает, что мою кошку зовут Люська». Это утверждение может быть истинно или ложно, но внутренне оно не противоречиво. Напротив, я не могу сказать тоже самое о себе: «Я не знаю, что мою кошку зовут Люська». Здесь я сразу натыкаюсь на внутреннее противоречие и начинаю замечать, что я чем-то отличаюсь от читателя, есть некая принципиальная разница.

Можно ли считать появление подобных парадоксов в машине Тьюринга зачатками интеллекта и свидетельством возможности самосознания? Трудно сказать. На этом пути можно увлечься и прийти к весьма странным и неожиданным выводам.

Добавлю только, например, Гёдель и его последователи считали, что существование подобных парадоксов доказывает невозможность существования разума. Вообще никакого, кроме Божественного. Как видите, двигаясь в обратную сторону, можно тоже прийти к интригующим заключениям.


Комментарии отсутствуют

Добавить комментарий

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

               Copyright © Системный администратор

Яндекс.Метрика
Tel.: (499) 277-12-41
Fax: (499) 277-12-45
E-mail: sa@samag.ru