Главная arrow Робототехника arrow Автоматная грамматика
Как начинался компьютер
Компьютерная революция
Двоичный код
Разработки военных лет
Интегральные микросхемы
Микрокомпьютер
Персоны
Сеть
Язык компьютера
Развитие ПО
Гибкие системы
Средства разработки
Информатика
Вычислительная наука
Операционные системы
Искусственный интеллект
Предыстория
Поиск
Знания и рассуждения
Логика
Робототехника
 

 
Автоматная грамматика Печать

В одним из перспективных направлений исследований, которое может привести к созданию систем искусственного интеллекта является использование систем управления объектно-ориентированными базами данных. При этом такие системы должны быть специально предназначены для применения в системах искусственного интеллекта. Одной из актуальных проблем в области искусственного интеллекта является понимание и обработка текстов естественного языка. Анализ текстов естественного языка удобно выполнять с использованием грамматик. Одной из задач в области анализа текстов является задача словоизменения. Задача словоизменения является хорошо изученной, поэтому ее можно применить как тестовую задачу для проверки возможности применения ООСУБД при анализе текстов естественного языка. Для реализации словоизменения русского языка возможно применить автоматную грамматику. В данной работе ставится задача рассмотреть возможность применения системы управления объектно-ориентированной базы данных/знаний Cerebrum [2, 3] для реализации автоматной грамматики. Для исследований в области искусственного интеллекта является актуальным применение искусственных нейронных сетей для анализа и обработки текстов естественного языка. Поэтому автоматная грамматика будет реализована в виде близком к структуре синхронизированного линейного дерева семантической нейронной сети [4, 5].

Архитектура СООБЗ Cerebrum

Важной особенностью СООБЗ Cerebrum является отличие в адресации объектов по сравнению со стандартом объектных баз данных ODMG [6]. По аналогии с естественным языком, когда одно и то же слово в разных контекстах имеет различное значение, и когда разные слова в некотором контексте имеют одинаковое значение, в ООБД так же возможно адресовать в разных контекстах разные экземпляры объектов с помощью одного и того же идентификатора, либо в некотором контексте адресовать один и тот же экземпляр с помощью разных идентификаторов. В этом случае каждый экземпляр persistent объекта определяет собственный контекст разадресации. В пределах любого экземпляра допустима только синонимия - когда разные ИД адресуют один и тот же внешний по отношению к текущему экземпляр другого объекта (в том числе и этого же самого если имеем ссылку на себя). Омонимия в пределах контекста разадресации не допускается. С другой стороны в БД столько контекстов сколько экземпляров. Поэтому в пределах всей БД каждый экземпляр может иметь практически неограниченное количество различных идентификаторов, без какого либо противоречия и конфликтов.

В Cerebrum каждый объект, так же как и в ODMG адресуется с использованием мягкого указателя или ID объекта Cerebrum.Runtime.NativeHandle . Получение указателей на экземпляры объектов, внешних по отношению к некоторому текущему объекту, производится в пределах контекста текущего объекта. Объект может адресовать только те объекты, с которыми он установил связь. Каждый связанный с текущим объект имеет идентификатор. Каждый уникальный идентификатор определяет в пределах текущего объекта экземпляр связанного с ним объекта. В пределах текущего объекта каждый идентификатор может адресовать только один экземпляр. Однако важным отличием от ODMG является возможность иметь в пределах некоторого объекта несколько различных NativeHandle адресующих один и тот же экземпляр. В пределах некоторого заданного объекта несколько разных идентификаторов могут ссылаться на один и тот же экземпляр объекта. В отличие от ODMG, где каждый объект имеет только один уникальный идентификатор, в Cerebrum один и тот же объект может иметь различные идентификаторы. Если рассмотреть не один экземпляр, а всю базу, то по аналогии с явлениями естественного языка синонимии и омонимии в СООБЗ Cerebrum возникает явления синонимии и омонимии идентификаторов объектов. В различных контекстах, определяемых различными экземплярами объектов, один и тот же идентификатор объекта NativeHandle может адресовать как разные экземпляры, так и один и тот же экземпляр. Это явление можно назвать омонимией объектных идентификаторов. Так же как и в естественном языке при омонимии один и тот же идентификатор в разных контекстах одной и той же базы данных может адресовать как различные, так и одинаковые экземпляры объектов. Как в одном и том же контексте, так и в разных контекстах различные идентификаторы могут ссылаться на один и тот же экземпляр объекта. В этом случае возникает явление синонимии объектных идентификаторов, когда один экземпляр может иметь в пределах базы множество различных идентификаторов - синонимов. Эту возможность удобно использовать для построения семантических и иерархических семантических сетей.

Наименее часто используемые объекты автоматически вытесняются на систему долговременного хранения, освобождая оперативную память. Поэтому в любой момент возможно принудительное вытеснение и разрушение любого незаблокированного пользовательского объекта. Если пользователь получил указатель на некоторый объект и не провел операцию блокировки, то сборщик мусора Cerebrum может посчитать этот объект неиспользуемым и принудительно вытеснить его из оперативной памяти. В результате по этому указателю в памяти будет находиться разрушенный экземпляр объекта. Для предотвращения такого явления вместо указателей на экземпляры пользовательских объектов при разадресации идентификатора возвращается указатель на объект-оболочку IConnector. В конструкторе объекта-оболочки производится увеличение счетчика блокировок объекта, в деструкторе - уменьшение счетчика блокировок. Пока хоть одна оболочка находится в памяти, счетчик блокировок не равен 0 и соответствующий этой оболочке объект защищен от разрушения. Это позволяет предотвратить вытеснение пользовательского экземпляра во время его использования. Использовать указатели на пользовательский экземпляр без сохранения указателя на оболочку IConnector нельзя. Важной особенностью данной системы является необходимость вызова метода  Dispose у всех объектов-оболочек для предотвращения чрезмерного расхода памяти.

У объекта оболочки IConnector есть свойство Component, через которое доступен пользовательский экземпляр. В большинстве случаев паттерн работы с объектом выглядит следующим образом:

using(IComposite composite = this.m_Connector.Workspace.AttachConnector(h))

{

   ISomeInterface node = composite.Component as ISomeInterface;

   result = node.SomeMethod(connector, …);

   …

}

При разадресации по идентификатору h объекта в методе this.m_Connector.Workspace.AttachConnector возвращается его оболочка IConnector. После завершения работы с объектом эту оболочку необходимо разрушить, вызвав метод Dispose. Директивы языка C# using() нужны, чтобы гарантировать удержание объекта в памяти во время вызова его методов, а затем гарантировать вызов Dispose после окончания работы с объектом. По выходу из using автоматически вызывается Dispose и разрушает объект-оболочку. При разрушении объект-оболочка уменьшит счетчик блокировок. Когда все оболочки будут разрушены и счетчик блокировок достигнет 0 экземпляр пользовательского объекта станет доступным для вытеснения из оперативной памяти. Если же по каким то причинам using не применим, и пользователь забыл или не смог провести вызов Dispose то сам .NET Framework вызовет Dispose в процессе сборки мусора. В результате утечки памяти не возникнет даже при наличии ошибок программиста.

С точки зрения разработчика Cerebrum представляет собой совокупность объектов различного назначения. В одном процессе возможно существование нескольких открытых баз данных. Каждая база данных доступна разработчику в виде объекта реализующего интерфейс IWorkspace. Экземпляр, реализующий этот интерфейс можно считать корнем базы данных.

public interface INativeDomain : System.IDisposable {

   IActivator Activator { get; }

 

   IContainerEx GetSector();

}

 

 

public interface IWorkspace : INativeDomain, IContainer {

   IActivator Activator { set; }

   NativeHandle CurrSequence();

   NativeHandle NextSequence();

}

 

где

     Activator - свойство, позволяющее установить фабрику пользовательских объектов;

     GetSector- метод, возвращающий оболочку корневого индекса пользовательских экземпляров;

     NextSequence- метод, возвращающий следующий уникальный идентификатор объекта;

     CurrSequence- метод, возвращающий последний сгенерированный идентификатор.

Этот объект так же обладает контекстом, позволяющим проводить разадресацию идентификаторов в указатели на объекты. Разадресация производится с использованием интерфейса IContainer являющегося базовым для интерфейса IWorkspace. IWorkspace так же является оболочкой к объекту DomainContext представляющему базу данных на уровне Cerebrum.Integrator.

Интерфейс IContainer содержит следующие методы:

public interface IContainer : IDisposable {

   IComposite AttachConnector(NativeHandle plasma);

   IComposite CreateConnector(NativeHandle plasma, NativeHandle typeID);

   void EngageConnector(NativeHandle plasma, IConnector connector);

   void RemoveConnector(NativeHandle plasma);

}

где

     AttachConnector - метод возвращающий объект-оболочку пользовательского объекта по идентификатору этого объекта;

     CreateConnector - метод, создающий экземпляр пользовательского объекта и возвращающий его оболочку;

     RemoveConnector - метод, удаляющий экземпляр пользовательского объекта из текущего контейнера. В случае удаления пользовательского объекта из всех контейнеров, объект полностью удаляется из базы данных;

     EngageConnector - метод, подключающий существующий экземпляр пользовательского объекта к текущему контейнеру с заданным идентификатором.

При использовании AttachConnector или CreateConnector возвращается оболочка экземпляра IComposite. Интерфейс IComposite наследует у интерфейса IConnector. IConnector имеет следующие свойства:

public interface IConnector : IDisposable {

       object Component { get; set; }

       IWorkspace Workspace { get; }

}

где

            Component - свойство, возвращающее экземпляр пользовательского объекта;

            Workspace - свойство возвращающее корневой интерфейс базы данных.

IComposite имеет следующие свойства:

public interface IComposite : IConnector {

   NativeHandle GroundHandle { get; }

   NativeHandle LiquidHandle { get; }

   NativeHandle PlasmaHandle { get; }

   NativeHandle TypeIdHandle { get; }

 

   IConnector GetPrecedent();

}

где

     PlasmaHandle - свойство, возвращающее логический идентификатор экземпляра;

     TypeIdHandle - свойство, возвращающее идентификатор типа экземпляра в таблице Types.

     GetPrecedent – свойство, возвращающее объект-оболочку родительского объекта;

     GroundHandle - свойство, возвращающее идентификатор объекта в хранилище;

     LiquidHandle - свойство, возвращающее идентификатор объекта в кэш.

Контекст экземпляра определяется объектом оболочкой IConnector. Если данный экземпляр имеет возможность устанавливать связи с другими объектами, то объект оболочку IConnector возможно привести к типу IContainer и использовать его для разадресации некоторого идентификатора NativeHandle вместо IWorkspace.

Создание persistent экземпляра пользовательского класса может быть осуществлено различными способами. Штатным способом является следующий: Необходимо зарегистрировать в таблице Tables тип пользовательского класса. Атрибут QualifiedTypeName должен содержать полное .NET имя пользовательского класса. Атрибут KernelObjectClass содержит тип объекта ядра. Для Scalar  = 8, для Warden  = 9. Затем следует определить идентификатор создаваемого объекта. Уникальный в пределах текущей базы данных идентификатор можно получить, воспользовавшись функцией NextSequence.

Cerebrum.Runtime.NativeHandle h =
            this.m_Connector.Workspace.NextSequence();

Затем следует воспользоваться функцией CreateConnector для получения указателя на объект-оболочку созданного экземпляра. Передав ей в качестве параметров идентификатор создаваемого экземпляра h и идентификатор дескриптора пользовательского типа typeId из таблицы Tables. Указатель на созданный экземпляр доступен через свойство Component объекта-оболочки.

using(IComposite composite =

   this.m_Connector.Workspace.CreateConnector(h, typeId)) {

   ISomeInterface node = composite.Component as ISomeInterface;

   result = node.SomeMethod(connector, …);

   …

}

Пользовательские классы удобно наследовать от класса GenericComponent. У каждого GenericComponent есть свойство DomainContext. Это свойство возвращает экземпляр класса DomainContext представляющий базу данных модуля Cerebrum.Integrator Метод GetChildComponents доступен изнутри пользовательского объекта и возвращает экземпляр класса, реализующий интерфейс IContainer. Это позволяет проводить разадресацию указателей на дочерние объекты изнутри пользовательского экземпляра не имея доступа к объекту оболочке возвращаемому AttachConnector/CreateConnector.

 

Реализация автоматной грамматики

Создадим новое решение .sln в среде Microsoft Visual Studio 2003. Назовем его Cerebrum.Samples.Objects-01.sln Устанавливаем references на сборки Cerebrum.Runtime.dll, Cerebrum.Integrator.dll и Cerebrum.Windows.Forms.dll. Уже существующую форму переименовываем в PrimaryWindow. Функцию Main созданную по умолчанию удаляем из PrimaryWindow. Затем добавляем класс Application. В классе Application создаем статическую функцию Main:

[STAThread]

static void Main() {

     Application app = new Application();

     Cerebrum.Windows.Forms.Application.Instance = app;

     app.Initialize();

     app.Show();

     System.Windows.Forms.Application.Run(app.PrimaryWindow);

     app.Shutdown();

     app.Dispose();

}

Переопределяем функции CreatePrimaryWindow и CreateContextService.

protected override System.Windows.Forms.Form CreatePrimaryWindow() {

     return new PrimaryWindow();

}

 

protected override IContextService CreateContextService() {

     string primaryDirectory =

              m_MasterContext!=null?(m_MasterContext.SystemDirectory):

              Path.GetDirectoryName(this.GetType().Assembly.Location);

     string databaseFileName =

              Path.Combine(primaryDirectory, "Cerebrum.Database.Master.bin");

     string activityFileName =

              Path.Combine(primaryDirectory, "Cerebrum.Database.Master.log");

     string mergeFileName =

              Path.Combine(primaryDirectory, "Cerebrum.Database.Master.xdb");

 

     return new Cerebrum.Integrator.SimpleContextService(

              this, databaseFileName, activityFileName, 4,

              true, mergeFileName, false);

}

Приведенная реализация Application является минимально необходимой для SDI Windows.Froms приложения использующая Cerebrum.

Для нейрона создаем базовый класс Cerebrum.Samples.Objects01.NeuronBase у этого класса будет два атрибута - список зависимых нейронов (DependentObjectsList) и список нейронов от которых зависит текущий нейрон (PrecedentObjectsList). Интерфейс INeuronLinks применяется для манипулирования этими списками.

public interface INeuronLinks {

     void AddPrecedent(NativeHandle h);

     void AddDependent(NativeHandle h);

 

     void DelPrecedent(NativeHandle h);

     void DelDependent(NativeHandle h);

}

Реализуем этот интерфейс в классе NeuronBase. От базового класса мы унаследуем нейрон, распознающий символ входной символьной последовательности SymbolNeuron : NeuronBase. Этот нейрон будет реализовывать интерфейс ILineralTreeNode . В этом интерфейсе нам понадобится два метода - метод для обучения зависимых нейронов GenerateDependents и метод для получения строк символов, соответствующих нейрону RestoreStrings а так же свойство, возвращающее символ, распознаваемый нейроном Symbol.

 

 

public interface ILineralTreeNode {

     Cerebrum.Runtime.NativeHandle[] GenerateDependents(

                                  IComposite outer, string text);

     string [] RestoreStrings();

     char Symbol {get;set;}

}

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

Обяжем нейрон SymbolNeuron реализовать интерфейс ILineralTreeNodeEx содержащий дополнительный метод FindAllLeafs, позволяющий обнаружить все листовые узлы синхронизированного линейного дерева.

public interface ILineralTreeNodeEx : INeuronLinks, ILineralTreeNode {

     void FindAllLeafs(System.Collections.ArrayList leafs);

}

Таким образом, объект SymbolNeuron будет обладать 3мя атрибутами - DependentObjectsList, PrecedentObjectsList и Symbol. Создадим в проекте папку Specialized и в ней класс Concepts Этот класс не будет иметь экземпляров - только статические поля. Поэтому сделаем для него статический конструктор, а конструктор экземпляра объявим как private. Создадим в этом классе несколько полей соответствующие атрибутам нейрона

Cerebrum.Runtime.NativeHandle DependentObjectsListAttribute;

Cerebrum.Runtime.NativeHandle PrecedentObjectsListAttribute;

Cerebrum.Runtime.NativeHandle SymbolAttribute;

Cerebrum.Runtime.NativeHandle SymbolNeuronType;

В статический конструктор добавим код для их инициализации

static Concepts() {

   using (IConnector connector =

       Application.Instance.MasterContext.GetTable("Attributes")) {

       using (TableView view =

                     (connector.Component as TableDescriptor).GetTableView()) {

          PropertyDescriptor descriptor =

                     view.GetItemProperties(null)["Name"];

          DependentObjectsListAttribute =

                     Tools.FindHandle(view, descriptor,

                                  "DependentObjectsList");

          PrecedentObjectsListAttribute =

                     Tools.FindHandle(view, descriptor,

                                  "PrecedentObjectsList");

          SymbolAttribute = Tools.FindHandle(view, descriptor, "Symbol");

       }

   }

   using (IConnector connector =

       Application.Instance.MasterContext.GetTable("Types")) {

       using (TableView view =

                     (connector.Component as TableDescriptor).GetTableView()) {

          PropertyDescriptor descriptor =

                     view.GetItemProperties(null)["Name"];

          SymbolNeuronType =

                     Tools.FindHandle(view, descriptor, "SymbolNeuron");

          ObjectCollectionType =

                     Tools.FindHandle(view, descriptor, "ObjectCollection");

       }

   }

}

Теперь создаем класс NeuronBase, унаследованный от Cerebrum.Integrator.GenericComponent. В него добавляем две функции, соответствующие его атрибутам и переопределяем функцию SetConnector

protected override void SetConnector(SerializeDirection direction, IConnector connector) {

   base.SetConnector (direction, connector);

   switch(direction) {

     case Cerebrum.Runtime.SerializeDirection.Init:

     {

        using(NativeWarden warden =

                           (this.GetChildComponents() as NativeWarden)) {

              warden.Newobj(Concepts.PrecedentObjectsListAttribute,

                                  KernelObjectClass.Warden);

              warden.Newobj(Concepts.DependentObjectsListAttribute,

                                  KernelObjectClass.Warden);

        }

        break;

     }

   }

}

Переопределение функции SetConnector необходимо для принудительного создания дочерних атрибутов содержащих списки идентификаторов связанных нейронов Concepts.PrecedentObjects-ListAttribute и Concepts.DependentObjectsListAttribute.

Функции

public NativeWarden GetPrecedentObjectsListVector() {

   return this.GetAttributeContainer(Concepts.PrecedentObjectsListAttribute)

                     as NativeWarden;

}

 

public NativeWarden GetDependentObjectsListVector() {

   return this.GetAttributeContainer(Concepts.DependentObjectsListAttribute)

                     as NativeWarden;

}

являются вспомогательными и облегчают получение этих списков. Следующие функции реализуют методы интерфейса INeuronLinks :

public void AddPrecedent(NativeHandle h) {

   using(NativeWarden v = GetPrecedentObjectsListVector()) {

     v.SetMap(h, MapAccess.Scalar, new NativeHandle(1));

   }

}

 

public void AddDependent(NativeHandle h) {

   using(NativeWarden v = GetDependentObjectsListVector()) {

     v.SetMap(h, MapAccess.Scalar, new NativeHandle(1));

   }

}

 

public void DelPrecedent(NativeHandle h) {

   using(NativeWarden v = GetPrecedentObjectsListVector()) {

     v.SetMap(h, MapAccess.Scalar, NativeHandle.Null);

   }

}

 

 

public void DelDependent(NativeHandle h) {

   using(NativeWarden v = GetDependentObjectsListVector()) {

     v.SetMap(h, MapAccess.Scalar, NativeHandle.Null);

   }

}

Теперь создаем класс SymbolNeuron, наследуем его от NeuronBase и ILineralTreeNodeEx. В этом классе реализуем свойство Symbol

public char Symbol {

   get {

     return Convert.ToChar(GetAttributeComponent(Concepts.SymbolAttribute));

   }

   set {

     SetAttributeComponent(Concepts.SymbolAttribute, Convert.ToInt32(value));

   }

}

и перекрываем метод SetConnector

protected override void SetConnector(

        SerializeDirection direction,

        IConnector connector) {

   base.SetConnector (direction, connector);

   switch(direction) {

     case Cerebrum.Runtime.SerializeDirection.Init:

     {

        using(NativeWarden warden =

                     (this.GetChildComponents() as NativeWarden)) {

              warden.Newobj(

                     Concepts.SymbolAttribute, KernelObjectClass.Scalar);

        }

        break;

     }

   }

}

В дополнение к предыдущему классу, в SetConnector создается скалярный атрибут для хранения символа, распознаваемого нейроном. Реализуем методы интерфейса ILineralTreeNode

 

public Cerebrum.Runtime.NativeHandle[] GenerateDependents(

        IComposite outer, string text) {

   //проверяем входные параметры

   if(text==null || text.Length<1) return null;

  

   //вырезаем первый символ из строки

   char symbol = text[0];

  

   //если первый символ совпадает с тем что распознает

   //этот нейрон - это наша строка

   if(this.Symbol!=symbol) return null;

 

   //получаем остаток строки

   string tail = text.Substring(1);

 

   if(tail.Length>0) {

     //пытаемся найти нейроны, распознающие остаток строки

     using(NativeWarden vector = this.GetDependentObjectsListVector()) {

        foreach(DictionaryEntry de in vector) {

           NativeHandle h = (NativeHandle)de.Key;

           using(IComposite connector =

                   this.m_Connector.Workspace.AttachConnector(h)) {

              ILineralTreeNode node = connector.Component as ILineralTreeNode;

              if(node!=null) {

                //рекурсивный вызов этой же функции но уже у другого нейрона

                NativeHandle[] hs = node.GenerateDependents(connector, tail);

                if(hs!=null) {

                   NativeHandle[] hs2 = new NativeHandle[hs.Length + 1];

                   hs.CopyTo(hs2, 1);

                   hs2[0] = outer.PlasmaHandle;

                   return hs2;

                }

              }

           }

        }

     }

     //если мы здесь, то найти ничего не удалось - создаем то

     //чего не хватает (обучаем сеть).

 

     // создаем ID для нового нейрона

     NativeHandle h0 = this.m_Connector.Workspace.NextSequence();

     // создаем новый экземпляр нейрона

     using(IComposite connector =

              this.m_Connector.Workspace.CreateConnector(

                      h0, Concepts.SymbolNeuronType)) {

        // а здесь мы приводим к ILineralTreeNodeEx

        // это надо чтоб добраться до функции AddPrecedent

        // которая не описана в интерфейсе ILineralTreeNode

        ILineralTreeNodeEx node = connector.Component as ILineralTreeNodeEx;

        if(node!=null) {

           //задаем нейрону его символ для распознавания

           node.Symbol = tail[0];

           //связываем созданный нейрон с собой - добавляем

           //себя в его коллекцию Precedents и его в свою коллекцию Dependents

           node.AddPrecedent(outer.PlasmaHandle);

           this.AddDependent(connector.PlasmaHandle);

 

           //рекурсивный вызов этой же функции но уже у нового нейрона

           NativeHandle[] hs = node.GenerateDependents(connector, tail);

           if(hs!=null) {

              //вставляем ссылку на себя в начало

              //результирующего массива, так как мы получили хвост

              NativeHandle[] hs2 = new NativeHandle[hs.Length + 1];

              hs.CopyTo(hs2, 1);

              hs2[0] = outer.PlasmaHandle;

              return hs2;

           }

        }

     }

   }

   // мы были последними в списке - дальше распознавать нечего, возвращаем себя

   return new Cerebrum.Runtime.NativeHandle[] {outer.PlasmaHandle};

}

 

public string[] RestoreStrings() {

   //опрашиваем всех предшественников и получаем строки, которые они распознают

   ArrayList result = new ArrayList();

   using(NativeWarden vector = this.GetPrecedentObjectsListVector()) {

     foreach(System.Collections.DictionaryEntry de in vector) {

        NativeHandle h = (NativeHandle)de.Key;

        using(IConnector connector =

                this.m_Connector.Workspace.AttachConnector(h)) {

           ILineralTreeNode node = connector.Component as ILineralTreeNode;

           if(node!=null) {

              //рекурсивный вызов этой же функции но уже у другого нейрона

              string [] heads = node.RestoreStrings();

              //обычно в heads может быть только одна строка - так как

              //обычно предшественник в дереве только один

              //на случай поддержки многозначности и нескольких путей

              //распространения волны возбуждения предусматриваем

              //более сложный вариант со многими предшественниками

              foreach(string head in heads) {

                result.Add(head + this.Symbol.ToString());

              }

           }

        }

     }

   }

   // это корневой узел без предшественников - добавляем себя в начало строки

   if(result.Count<1) {

     result.Add(this.Symbol.ToString());

   }

   return (string[]) result.ToArray(typeof(string));

}

 

 

Класс для нейронов разработан.

 

Выводы

Предложенный способ идентификации экземпляров объектов включает в себя общепринятый в ООБД как частный случай и позволяет избавиться от некоторых проблем, присущих существующим ООБД. Поддержка сетевой модели данных в ядре Cerebrum позволяет на ее основе реализовать такие модели как иерархические семантические сети и семантические сети фреймов. Поддержка методов у сохраняемых объектов позволяет реализовать активные семантические сети и искусственные нейронные сети. Благодаря наличию автоматической сборки мусора, управление временем жизни объектов и ресурсами берет на себя СУБЗ. Разработчику остается инициализировать БД и далее сосредоточиться на решении поставленной задачи. Это делает среду сетевой объектно-ориентированной базы знаний/данных Cerebrum очень удобным и перспективным инструментом для разработок систем искусственного интеллекта.

Рассмотренный пример построения автоматной грамматики продемонстрировал некоторые из возможностей СООБЗ Cerebrum. Как видно из примера, исходные тексты приложения реализующего автоматную грамматику в среде СООБЗ Cerebrum занимают относительно небольшой объем. Разработчику требуется инициализировать БД и далее сосредоточиться на решении поставленной задачи. Управление временем жизни объектов и ресурсами берет на себя СУСООБЗ. Это делает среду сетевой объектно-ориентированной базы знаний/данных Cerebrum очень удобным и перспективным инструментом для разработок систем искусственного интеллекта.