Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Дополнение к Ассоциативная самозамкнутая сеть
Часть 0. Повторюсь
В начале хотел бы отметить те вещи, которые некоторые люди отметили как минус при прочтении предыдущей части. Заранее хочу сказать спасибо за любую конструктивную критику.
Эта часть во многом дублирует сказанное и что будет сказано, что бы обратить внимание на важные элементы.
В первую очередь хочу сказать — ИИ не подразумевает никакого рандома. За основу бралась не связь между нейронами, а принципы работы ассоциативной теменной коры и когнитом.
Не стоит отдельно задачи по вычислению дерева, или сделать логический вывод на основе правил в какой-то задаче. Суть не в выполнении отдельных задач, перечисленных в тексте. Цель именно что в создании ИИ, способного выполнять каждую из перечисленных задач одним и постепенно развивающимся ИИ, с развитием после выполнения каждой отдельной и совершенно отличающейся задачи. Т. к. со временем будут находиться схожие элементы и опыт позволит более эффективно решать новые, совершенно разнородные задачи. Описание действий, за счет которых задача будет решаться, находится внутри БД (базы данных) ИИ и являться её частью (в том числе отдельные программы и скрипты могут быть интегрированы как часть ИИ, что делать не рекомендуется и о чем будет сказано в тексте). Каждое действие и все его элементы могут быть заменены (исправлены) в любой момент.
Было уместное, на первый взгляд, сравнение с Лиспом, однако здесь во первых отсутствует типизация как таковая (только один тип на все). Во вторых методы/действия являются такими же объектами, не каждый объект является действием по умолчанию, но каждый объект может быть вызван как действие, что не приведет к ошибке и должно выдать результат. Функции не должны требовать аргументов для выполнения, функции сами должны искать аргументы для выполнения (далее будут упомянуты Родители и Синонимы/Антонимы), функции хранят внутри себя описание, что они хотят найти. Это суммарно и должно решить задачу. Пары выполняют принципиально иную задачу (они проистекают из совершенно иной логики и выполняют иные задачи). Создаваемое здесь можно с натяжкой назвать интерпретируемым языком, но он не относится к функциональному программированию. Объект здесь практически всегда является списком, что и позволяет выполнять поставленную задачу. В общем наличие двух похожих терминов (пары и списки) не делают результирующие структуры схожими.
И строго говоря назвать это языком программирования не получится, т. к. он не предназначен для кодирования команд. Лишь для их вызова. Благодаря чему возможно сохранение подавляющего большинства структур без изменений при переносе между платформами. А так же выполнение различных частей на кардинально разных платформах (вплоть до выполнения части задач на процессоре, а другой части на видеокарте).
Нейросети были же достаточно быстро отринуты в связи с непрозрачностью для последующего анализа и переноса результатов. ИИ должен быть прозрачен, понятен и должна быть возможность четко описать как он добился тех или иных результатов.
Суть не в простейших логических Да или Нет, или множителях, суммарно описывающих состояние системы. Состояние системы должно описываться явным, ясным для человека (и не только) образом. А работа должна производиться с цельными структурами, каждая из которых будет иметь смысл по отдельности. Или «манипулирование чистыми абстракциями без их реализаций» — как всегда найдется кто-то, кто выскажет мою мысль лучше меня самого. Однако абстракции связанные с действиями имеют несоизмеримо большее значение, чем просто описание вещей. Именно правила мышления разных уровней создают то, что принято считать интеллектом. И каждое отдельное правило должно быть выделено как отдельный объект.
С другой стороны по ряду причин я настаиваю на том, что создание сильного ИИ путем наращивания мощностей и использования базиса слабого ИИ крайне непродуктивен. Так же как и попытка повторить мозг. Нужно искать ключевые моменты, вещи определяющие и усиливающие интеллект в существующих моделях/структурах и работать лишь с самыми важными и эффективными элементы. Так же как оптимизация и новые решения способны выполнить другие задачи на порядки быстрее на старом железе, так и здесь нужно искать новые подходы, ведь старые создавались под отличающиеся задачи, во времена с иными знаниями.
Во время создания текущего кода я пришел к выводу, что возможность понятного взаимодействия с человеком является фактором, несколько тормозящим работу ИИ, но обязательным для коммерческого успеха, потому все так, как описано. Однако данная особенность в первую очередь будет учитываться в соответствующей БД и не относится непосредственно к ИИ. Те 20 строчек кода из предыдущей статьи (а в первую очередь даже не код, а структура с картинки) практически не несут на себе отпечатков каких-либо правил мышления, о чем было сказано не раз. В чем и весь смысл.
И да, все это пока что лишь описание задачи и одного из возможных вариантов её решения. Это еще не полностью сформированная БД, решающая данную задачу (можете не повторять это в комментариях, это и так прекрасно понимает и автор, и другие читатели).
Часть 1. Принципы связи объектов в примитивах
Немного углубимся в структуру и примитивы для лучшего понимания методов использования данного кода. Наглядные принципы хранения данных представлены во второй части в таблицах.
Как было сказано в первой части — сутью данного ИИ является способ хранения данных, а именно связь между двумя объектами описывается третьим объектом, подчиняющимся тем же правилам и хранящим внутри себя такие же связи. При необходимости ИИ можно модифицировать, связывать объекты не парами, а тройками и т. д., суть же при этом остается прежней — связь между объектами описывается точно таким же объектом.
Для начала вспомним про, точки соприкосновения с объектами вовне этого ИИ — примитивы. Т.к. сам по себе ИИ является работой абстрактного характера, то на базовом уровне он минимально учитывает платформы, на которых будет запускаться. Примитивы будут вызываться, как и прочие объекты, из списка <TODOLIST>, где <ObjB> — вызываемый примитив, <ObjA> — параметры вызова.
Примеры призваны показать базис для связи объектов. Ведь добавлять параметры как заранее предопределенные объекты зачастую будет неуместно. Связью между объектами должны выступать такие же активно используемые объекты.
<Создание> создает новую пару и добавляет её последней в хранилище <dataIn>.
Код примитива:
void callIt(DuoP* caller, ObjTO* dataIn) {
ObjTO::DuoPList* currentDuoPListS = dataIn->duoPList->prevDuoPList;
while (currentDuoPListS->duoP->objA != SYSTEMOBJ) {
//Ищем хранилище в dataIn
//Ключевой объект (для поиска хранилища) прописан в примитиве в первом связанном объекте
if (currentDuoPListS->duoP->objA == caller->objB->duoPList->nextDuoPList->duoP->objB) {
ObjTO::DuoP* nDuoP = new ObjTO::DuoP;
nDuoP->p = currentDuoPListS->duoP->objB;
//EMPTYOBJ - объект, который в дальнейшем будем интерпретировать как пустой, ничего не значащий
nDuoP->objA = EMPTYOBJ;
nDuoP->objB = EMPTYOBJ;
//новый объект добавляем в конец списка
ObjTO::DuoPList* nDuoPList = new ObjTO::DuoPList;
nDuoPList->duoP = nDuoP;
nDuoPList->nextDuoPList = currentDuoPListS->duoP->objB->duoPList;
nDuoPList->prevDuoPList = currentDuoPListS->duoP->objB->duoPList->prevDuoPList;
currentDuoPListS->duoP->objB->duoPList->prevDuoPList = nDuoPList;
nDuoPList->prevDuoPList->nextDuoPList = nDuoPList;
break;
}
currentDuoPListS = currentDuoPListS->prevDuoPList;
}
}
Ключевой объект — специальная Метка. Когда мы говорим «хранилище», то подразумеваем нечто определенное, однако произносим обобщенное слово. Здесь аналогично — есть конкретный объект <Хранилище>, а если общеизвестный объект, означающий слово «хранилище» и позволяющий ориентироваться.
<dataIn> — место хранения всей информации в рамках текущей мысли (кэш операций, списки вызванных объектов и т. д.), а так же отдельный блок ссылок на более глобальные объекты.
Операция копирования пар. <ObjA> будет хранить объекты-источники копирования (откуда копируем), объекты-назначения (куда копируем), условия копирования в заданном порядке. Условие — сравнение на равенство, в данном случае хотя бы одно. Сравнение производится над <ObjA> источника копирования.
Поиск наиболее подходящего объекта будет выполняться посредством последовательного копирования с применением поочередно разных фильтров. Так же можно использовать перекрестное сравнение двух и более списков, как отличный способ поиска закономерностей с последующим выделением логического обоснования.
Код примитива:
void callIt(DuoP* caller, ObjTO* dataIn) {
bool done = false;
//________________________________________________________
//Важное тут \
//Фиксированное местоположение ключевых объектов
ObjTO* copyFrom = caller->objA->duoPList->nextDuoPList->duoP->objB;
ObjTO* copyTo = caller->objA->duoPList->nextDuoPList->nextDuoPList->duoP->objB;
ObjTO* copyConditions = caller->objA->duoPList->nextDuoPList->nextDuoPList->nextDuoPList->duoP->objB;
ObjTO::DuoPList* currentDuoPListF = copyFrom->duoPList->prevDuoPList;
ObjTO::DuoPList* currentDuoPListT = copyTo->duoPList->prevDuoPList;
ObjTO::DuoPList* currentDuoPListC = copyConditions->duoPList->prevDuoPList;
//________________________________________________________/
if (currentDuoPListC->duoP->objA != SYSTEMOBJ) {
//когда есть условия. Если список пустой, то единственным объектом там будет SYSTEMOBJ, указывающий сам на себя в обоих направлениях
while (currentDuoPListF->duoP->objA != SYSTEMOBJ) {
while (currentDuoPListC->duoP->objA != SYSTEMOBJ) {
if (currentDuoPListC->duoP->objB == currentDuoPListF->duoP->objA) {
while (currentDuoPListT->duoP->objA != SYSTEMOBJ) {
ObjTO::DuoP* nDuoP = new ObjTO::DuoP;
nDuoP->p = currentDuoPListT->duoP->objB;
nDuoP->objA = currentDuoPListF->duoP->objA;
nDuoP->objB = currentDuoPListF->duoP->objB;
ObjTO::DuoPList* nDuoPList = new ObjTO::DuoPList;
nDuoPList->duoP = nDuoP;
nDuoPList->nextDuoPList = currentDuoPListT->duoP->objB->duoPList;
nDuoPList->prevDuoPList = currentDuoPListT->duoP->objB->duoPList->prevDuoPList;
currentDuoPListT->duoP->objB->duoPList->prevDuoPList = nDuoPList;
nDuoPList->prevDuoPList->nextDuoPList = nDuoPList;
if (!done) { done = true; } //не используется здесь, пометка для следующего примера
currentDuoPListT = currentDuoPListT->prevDuoPList;
}
break;
}
currentDuoPListC = currentDuoPListC->prevDuoPList;
}
currentDuoPListF = currentDuoPListT->prevDuoPList;
}
} else {
//когда нет условий
while (currentDuoPListF->duoP->objA != SYSTEMOBJ) {
//Да, код дублируется, не закидывайте меня ссаными тряпками за такой пример
while (currentDuoPListT->duoP->objA != SYSTEMOBJ) {
ObjTO::DuoP* nDuoP = new ObjTO::DuoP;
nDuoP->p = currentDuoPListT->duoP->objB;
nDuoP->objA = currentDuoPListF->duoP->objA;
nDuoP->objB = currentDuoPListF->duoP->objB;
ObjTO::DuoPList* nDuoPList = new ObjTO::DuoPList;
nDuoPList->duoP = nDuoP;
nDuoPList->nextDuoPList = currentDuoPListT->duoP->objB->duoPList;
nDuoPList->prevDuoPList = currentDuoPListT->duoP->objB->duoPList->prevDuoPList;
currentDuoPListT->duoP->objB->duoPList->prevDuoPList = nDuoPList;
nDuoPList->prevDuoPList->nextDuoPList = nDuoPList;
if (!done) { done = true; } //не используется здесь, пометка для следующего примера
currentDuoPListT = currentDuoPListT->prevDuoPList;
}
currentDuoPListF = currentDuoPListF->prevDuoPList;
}
}
}
В идеале система должна строиться на последовательном запуске объектов из списков <TODOLIST>, которые, в стою очередь, будут наполняться наиболее подходящими объектами по ходу решения задачи. Однако построить такую систему, обходящуюся лишь операциями сравнениями на равенство, будет сложно и очень долго. Потому для удобства описания сложных процессов на ранних этапах заполнения базы данных ИИ можно использовать примитивы — сложные скрипты и управляющие конструкции.
Самым простым примером управляющей конструкции будет прерывание цикла <TODOLIST>. Например после копирования, при успешном завершении операции (когда был скопирован хотя бы один элемент), вызывается примитив, удаляющий все последующие пары из <TODOLIST>. Для любого примитива рекомендуется добавлять какой-либо результирующий компонент, описывающий результат работы (что потребует так же создание уникального объекта, дабы не изменить типовой объект-шаблон). Для копирования в соответствующий <ObjA> будем добавлять пару <Скопировано успешно><Список скопированных пар>, при наличии скопированных пар. Это позволит как быстро просмотреть результат, так и отменить его в случае необходимости. А управляющий примитив прервет цикл лишь увидев наличие <Скопировано успешно> у стоящего перед ним <Копирование>. Имеем классические четко прописанные операторы-аналоги классических if, true.
Код примитива:
void callIt(DuoP* caller, ObjTO* dataIn) {
ObjTO::DuoPList* currentDuoPList = caller->p->duoPList->prevDuoPList;
while ( (currentDuoPList->duoP != caller) ) {
currentDuoPList = currentDuoPList->prevDuoPList;
}
ObjTO::DuoPList* currentDuoPListC = currentDuoPList->nextDuoPList->duoP->objA->duoPList->prevDuoPList;
//Ключевые объекты прописаны в макросе, располагаются на фиксированных позициях в SYSTEM
while ( (currentDuoPListC->duoP->objA != CONDITION) && (currentDuoPListC->duoP->objA != SYSTEMOBJ) ) {
currentDuoPListC = currentDuoPListC->prevDuoPList;
}
ObjTO::DuoPList* currentDuoPListT;
if ( (currentDuoPListC->duoP->objA == CONDITION) && (currentDuoPListC->duoP->objB == TRUE) ) {
caller->p->duoPList->nextDuoPList = currentDuoPList;
currentDuoPList = currentDuoPList->prevDuoPList;
while (currentDuoPList->duoP->objA != SYSTEMOBJ) {
currentDuoPListT = currentDuoPList;
currentDuoPList = currentDuoPList->prevDuoPList;
delete currentDuoPListT->duoP;
delete currentDuoPListT;
//НЕ подчищаем объекты
}
caller->p->duoPList->nextDuoPList->nextDuoPList = currentDuoPList;
};
}
Логическим продолжением Ключевых объектов можно считать универсальный управляющий конструкт, завязанный на сам примитив или на самого себя (такой подход и его модификации я рассматриваю как наиболее эффективный):
void callIt(DuoP* caller, ObjTO* dataIn) {
ObjTO::DuoPList* currentDuoPList = caller->p->duoPList->prevDuoPList;
while ((currentDuoPList->duoP != caller)) {
currentDuoPList = currentDuoPList->prevDuoPList;
}
//Ключевой объект и является примитивом, содержимое предназначено для него. Примитив является описанием связи - соответствием.
ObjTO::DuoPList* currentDuoPListCondition = currentDuoPList->nextDuoPList->duoP->objA->duoPList->prevDuoPList;
while ((currentDuoPListCondition->duoP->objA != caller->objB) && (currentDuoPListCondition->duoP->objA != SYSTEMOBJ)) {
currentDuoPListCondition = currentDuoPListCondition->prevDuoPList;
}
if (currentDuoPListCondition->duoP->objA == SYSTEMOBJ) { return; }
ObjTO* conditions = currentDuoPListCondition->duoP->objB;
//Значения и условия сравнения будут находиться в соответствующем объекте и находиться по аналогичному правилу соответствия.
ObjTO::DuoPList* currentDuoPListValue = currentDuoPList->nextDuoPList->duoP->objA->duoPList->prevDuoPList;
while ((currentDuoPListValue->duoP->objA != caller->objB) && (currentDuoPListValue->duoP->objA != SYSTEMOBJ)) {
currentDuoPListValue = currentDuoPListValue->prevDuoPList;
}
if (currentDuoPListValue->duoP->objA == conditions) { return; }
ObjTO* value = currentDuoPListValue->duoP->objB;
if ( ) {
//......
}
}
(Если желаете пользоваться подобными управляющими конструкциями, то сделайте caller ссылкой на объект типа DuoPList, сэкономит много ресурсов).
Описывать примитивы можно очень долго, ведь они будут работать как с устройствами ввода-вывода, так и создавать новые потоки. Так же при возникновении необходимости или в начале разработки можно использовать достаточно крупные примитивы. Небольшие скрипты или даже крупные программы будут вызываться как объекты и выполнять функции, на тщательную проработку которых в виде сети примитивных операций в данный момент не хватает времени или иных ресурсов. Со временем крупные примитивы можно будет разбить на цепочку базовых примитивов. Но всегда нужно держать в голове, что лишь минимизация количества используемых примитивов (а соответственно и их упрощение) позволит полноценно раскрыться ИИ.
Кроме описания непосредственно примитивов нужно обладать еще и пониманием структуры будущей БД. Тут хочу еще раз повторить, что она будет отличаться для различных финальных реализаций и для каждой реализации нужны свои примитивы, зачастую полностью отличающиеся друг от друга.
Например для описанных выше примитивов структуру большинства объектов БД можно представить как:
Где Синяя ячейка — это описываемый объект.
Зеленые ячейки — это <ObjA> пар, содержащихся в объекте из синей ячейки. Данные пары являются способом разбить содержимое Синей ячейки на группы в целях оптимизации, где <ObjA> будет являться описание группы. <ObjA> первого порядка.
Серые ячейки — это <ObjB> пар из синего объекта. Каждый из них является списком объектов (серый столбец целиком это и есть <ObjB> первого порядка), <ObjB> первого порядка стоит интерпретировать исключительно как список. С объектами <ObjB> второго порядка логически связан объект из Синей ячейки, а описанием этой связи является <ObjA> второго порядка.
Т.е. два объекта (<TheObj> и <ObjB2>) являются связанными логическими объектами, где описанием связи является <ObjA2>. В то время как <ObjB1> — это просто способ сгруппировать содержимое в целях оптимизации, а <ObjA1> — описание по какому параметру была выполнена группировка.
Один объект (<ObjB2>) может содержаться в нескольких группах, но не рекомендуется дублировать <ObjB2> в рамках одной группы, хотя это не запрещено и при составлении своей БД каждый может делать то, что считает наиболее эффективным. Обратите внимание, что непосредственно в коде ИИ отсутствуют какие либо запреты, ведь это противоречит базовым принципам. Есть только 2 обязательных условия — расположение двух последних элементов в объекте <SYSTEM> (последним будет <NOTHINGTODO>, определяющий что делать когда отсутствует или пустует список <TODOLIST>, предпоследним дублируется <SYSTEM>), и первая пара любого объекта будет <SYSTEM> (хотя что такое <SYSTEM> может быть переопределено).
Ранее было сказано, что два объекта соединяются при помощи третьего. Однако введение дополнительных уровней-логических фильтров, позволяет оптимизировать работу ИИ. Человеческий мозг не редко называют шумящим компьютером, в нем используются различные механизмы, останавливающие лишние сигналы. Здесь используются различные определяющие элементы, позволяющие использовать лишь необходимые в данный момент связи, своего рода фильтры применяющиеся до активации объектов, призванные выполнять ту же роль, что и тормозящие механизмы мозга.
Часть 2. Как заполнять БД
Для лучшего понимания принципа заполнения таблиц необходимо сделать небольшое отступление. Здесь опишу логику, которой следовал при создании ИИ.
Внимание Вода (аналогия):
Представьте себя водителем. Вы едите на работу. Когда впереди тормозит машина — Вы тормозите. Когда загорается зеленый свет — ускоряетесь. Когда проезжаете синий дом — поворачиваете на право. Этот процесс можно описать простыми скриптами, разбить их на группы, полностью понимать и описывать каждое действие. Вы ведь четко знаете, что едете на работу и знаете маршрут.
Перед тем как поехать на работу Вы наверняка проснулись и встали. Вполне возможно, что базовые физиологические порывы мешали оторвать голову от подушки, но действие было сделано. Так почему? Особенно вопрос актуален в случаях, когда работа не доставляет удовольствие.
Скорее всего все задавались следующими вопросами хотя бы раз. Может лучше поспать и затем сказать, что «пробки», «ДТП», «заболел» и т.п. В таком случае идет сравнение желаний и последствий и выбирается более приоритетный вариант. Люди заранее определяют для себя приоритетность работы и затем сравнивают её противопоставляющимся событием, будь то желание поспать или звонок друга с крайне неотложной просьбой помочь. Т.е. работа определяется как нечто предопределенное, как аксиома.
Но если работу рассматривать не как данность, а как набор вещей, которые вам нужно делать, которые раздражают, но которые приносят средства, то через некоторое время можете решить заниматься чем-то более интересным, пусть и за несколько меньшие деньги. Либо изменить ряд пунктов в рамках работы (например работать на пол ставки, но после обеда и высыпаться). И вообще зачем нужны деньги выше базового минимума...
Обратите внимание, как мы постепенно переходим к более «высоким» и «глобальным» вещам. Сначала рассматривались правила движения. Затем — «а может сегодня можно не мучиться и не ехать на работу». Далее будет логично задаться вопросом — зачем нужна такая работа, на которую не хочется ехать, может её стоит сменить. В конце концов мы дойдем и до вопроса зачем работать, а так же зачем мы живем. Однако каждый из них является лишь частью предыдущего вопроса. «Высокие» и «глобальные» вещи являются лишь частью самых простых бытовых вопросов.
Этим отступлением я хотел сказать, что во первых вопросы о смысле жизни и «а не заехать ли мне по пути в макдак» имеют количественные, но не качественные различия. И второе — «глобальные» вопросы являются частью для самых банальных действий. Однако что бы каждый раз при необходимости затормозить на светофоре не задумываться о смысле жизни, необходимо иметь так же заранее подготовленный ответ вопрос, и пусть он будет не всегда полностью точным и верным, зачастую полученным из внешнего источника (так же как и люди принимают за истину сказанное из авторитетного источника, не проверяя досконально каждое услышанное слово). А если ответа нет — взять его из похожей ситуации (синонима, ниже синонимы будут упомянуты еще раз) для быстрого ответа, и в дальнейшем разобрать уже конкретный пример, когда будет время. Т.е. минимизация слепых рекурсий. Поиск аналогий за счет принципа хранения данных.
Это была одна из основных мыслей, легшей в основу данного ИИ, т. к. выделить один целостный логический объект у нейросетей и иных существующих на данный момент ИИ для последующей имплементации в другой физически изолированный ИИ является либо невозможным, либо крайне сложным.
Заполним пару таблиц, для лучшего понимания написанного. Например новые сведения поступают извне, соответственно их создаст какое-то внешнее устройство/программа. Получив текстовое сообщение, мы получим объект, содержащий всю информацию об этом сообщении.
Первый столбец — перечисление системных объектов. Для работы хорошо бы иметь некоторые предопределенные объекты, для базового ориентирования в БД (ориентирование будет производиться средствами записанными в БД). Однако обратите внимание на код, макросы обозначают, что на определенном месте в списке <SYSTEM> располагается определенный объект (не считая случаев, когда вызываемый объект несет в себе или сам является Ключевым), а точнее ссылка на него. Если возникнет необходимость изменить один из базовых системных объектов, то можно лишь заменить ссылку на конкретной позиции и система будет продолжать работать. Вероятнее всего список не претерпит изменения и все объекты будут иметь абсолютно одинаковый <SYSTEM>. Список системных объектов будет длиннее, что должно быть понятно исходя из уже описанных примитивов. Например для объекта в <dataIn> имеется упомянутое ранее хранилище, оно помечено как <STORAGE>.
Второй столбец — список родителей. В данном случае наследование серьезно отличается от классического понятия из ООП. Здесь родитель — это скорее общность, в которую входит объект, нежели классический родитель, автоматически расширяющий функциональность объекта. У родителей могут быть свои родители, а многократное углубление по определенной линии может занять слишком долгое время (упомянутый ранее поиск смысла жизни перед поворотом по пути на работу). Родители не являются автоматическим расширением объекта, они являются местом для поиска, когда нужной информации не обнаружилось непосредственно в объекте или в описании связи.
Третий столбец определим как данные, непосредственно относящиеся к текущему конкретному текстовому сообщению. То, что в сумме делает это сообщение уникальным по отношению к другим. Обратите внимание, там можно разместить и примитив, содержащий текстовое поле, позволяющее в дальнейшем человеку быстро ориентироваться в БД. Например в как в родителе:
Объект из первой таблицы (<Конкретное входящее текстовое сообщение>) был создан внешним, по отношению к ИИ, источником и запущен как часть ИИ.
Запуск означает лишь вызов метода callIt() объекта. Но натыкаемся на ситуацию, когда объект не имеет списка <TODOLIST>. Не найдя оный ИИ производит вызов на исполнение последнего объекта из <SYSTEM>. Именно с этим связано обязательное условие о двух последних элементах в объекте <SYSTEM> — т. к. обработка списка действий происходит до обнаружения <SYSTEM>, то <SYSTEM> будет размещен предпоследним (а так же первым, скорее всего в данном списке он будет встречаться 2 раза). Последним и вызываемым будет объект, предназначенный именно для случаев, когда непонятно что делать. В рамках примера он вызывает <TODOLIST> родителя, однако в реальной БД он может быть сколь угодно сложным, например рекомендуется проверять так же синонимы — объекты содержащие высокий процент совпадающих связей и/или связанных объектов, тем самым находя аналогии (во многом ИИ строился вокруг данной идеи, как попытке создания аналога нейросетей с поиском логических связанных закономерностей, а не всех подряд, либо надстройки над нейросетями, выполняющей логические задачи), либо схожим образом находя антонимы, антиподы объектов, что опять же будет полезно при выполнении множества задач.
<Входящее текстовое сообщение> так же хранит список действий, которые можно произвести над объектом.
Однако все, что можно сделать над объектом не описывает всего, что можно совершить получив объект. Именно исходя из этой формулировки существует <dataIn>, объект хранящий информацию о текущем потоке мысли, память для текущих операций, а так же ссылку на объект, работающий с общими параметрами системы.
Мы можем делать разные действия, например ехать за рулем во момент, когда пришло сообщение. Тогда у действий будут сравниваться приоритеты. Прочитать текст обычно не является важным действием, однако если ожидается какое-то важное сообщение, то прервем поездку. И обобщенное текстовое сообщение имеет своё значение Приоритета (ожидая нечто важное, мы все сообщения изначально помечаем как Важные). Однако родитель может находиться не на один или два уровня, а гораздо глубже, потому есть риск ошибиться, сделать неверную оценку. Но и досконально проверять все что только возможно тоже будет неверным подходом. Так что для многих объектов можно просто хранить список приоритетов всех родителей, который может объединяться в один объект. Вопросы оптимизации тут значат многое, но они должны решаться за счет внутренней структуры БД, но не за счет большого количества примитивов на все случаи жизни и/или сложных примитивов.
Второй момент, на который стоит обратить внимание располагается в <ObjA2_1> в <calls>. Первым объектом, который был вызван в этой мысли был <Конкретное входящее текстовое сообщение>. Записывать все или часть вызовов в историю будет полезно, однако информацию о вызвавших объектах можно разделить на две подгруппы: логические и фактические. Логически группа объектов будет вызвана из одного и того же источника, но фактически непосредственно метод callIt() будут вызывать разные объекты.
Суть же кроется не в конкретном примере, а в напоминании, что каждый объект является так же и списком. И как уже было ранее, никто не мешает некоторые объекты интерпретировать исключительно как списки. Я предпочитаю избегать таких случаев, оставлять их исключительно в регламентированном месте структуры, однако кто-то может найти более эффективное применение подобной гибкости.
Аргументами для функций в большинстве случаев будут либо объекты из списка <calls>, как логически связанные элементы в рамках мысли. Либо объекты связанные уже с обрабатываемым объектом из списка <calls> или хранилища. Каждый следующий объект будет проистекать из предыдущего. Где все будет начинаться с внешнего события, но не обязано заканчиваться.
все представленное в этой части носит исключительно ознакомительный характер, создано для разъяснения базовых способов взаимодействия с ИИ, не является фрагментом готовой БД.
Заключение
Из-за очень тесного взаимодействия основных примитивов со структурой, БД должна составляться одним человеком или небольшой группой давно сработавшихся коллег, что бы структура, способы мышления и все с этим связанное могло объединиться в целостный и внутренне непротиворечивый продукт.
Вот так вот стартовав с идеи взять лучшее от высокоуровневых структур мозга (не просто связи между нейронами), готовый ИИ стал структурой хранения данных, являющейся своеобразным интерпретируемым языком без синтаксиса. А структуры хранения данных и часть методов их обработки будут отдаленно знакомы людям, работавшим с SQL. Т.е. он должен быть прост в освоении и использовании широкими массами.
Скепсис можно понять, ведь пока не будет реально работающего сильного ИИ, то будут и сомнения. Для составления работающего прототипа БД для данного ИИ понадобится в самом лучше случае, если сложатся все звезды, минимум пол года неотрывной работы. Не буду скрывать, что ищу компанию, которую это заинтересует, в которой я мог бы работать над созданием такой БД. Но если у меня не получится, то может кто-то взглянув на сказанное здесь, поймет где была допущена принципиальная ошибка и создаст нечто куда как более эффективное. Хотя лично я не сомневаюсь в успехах данного ИИ.
Прошу всех желающих в комментарии, вероятно некоторые из них помогут мне не совершить ошибки при составлении БД.