GotAI.NET

Форум: Проблемы искусственного интеллекта

 

Регистрация | Вход

 Все темы | Новая тема Стр.1 (1)   Поиск:  
 Автор Тема: Продукционная система
og http://openai.narod.ru
Сообщений: 19
Продукционная система
Добавлено: 16 янв 09 11:06
Здравствуйте уважаемые товарищи форумчане.

Представляю вашему вниманию разработанную мной продукционную систему, исполненную в виде компонента с дуальными интерфейсами. Компонента целиком написана на С++, без использования каких либо других компонент и библиотек(кроме STL и ATL естественно)

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

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

Система обладает хорошей скоростью. Она практически вся логарифмическая, хотя есть темные квадратные места...
К явным недостаткам можно отнести:
1)бедный функционал, например в правилах очень не хватает квантора всеобщности.
2)невозможность добавлять правила после старта системы, но это не принципиальная невозможность, её можно устранить.
К явным достоинствам можно отнести скорость, легкость использования и интеграции в свои программы, особенно на COM совместимых языках, открытость.

Пример использования программы (на си-шарпе): pr1.zip

В примере создается квадратный массив ячеек, для каждой ячейки задается левый и верхний сосед.
Массив ячеек выводится на экран в виде массива кнопок, при клике на кнопку ячесйка "активируется".
"Активированная" ячейка обозначается нулем.
В программе задаются два простых правила:
1) Если узел1 - это ячейка и сверху узел2 - это активированная тячейка, и слева тоже активированная ячейка - то активировать ячейку узел1.
2) Если соседу снизу и справа активированны - то активироватся.

Правила могут быть произвольного размера. Единственно что, если они цикличные (в примере если есть связь cell1-cell2, cell2-cell3 и cell3-cell1), то они будут выдавать лишние ребра, но это я исправлю когда мне понадобятся цикличные правила.

Жду вопросов, предложений и комментариев.
[Ответ][Цитата]
og http://openai.narod.ru
Сообщений: 19
На: Продукционная система
Добавлено: 19 янв 09 12:17
Правила представляют собой паттерны, множество "фактов" - граф.
Как только в графе появляется структура подходящяя под IF-часть паттерна правила,
в граф добавляются ребра из THEN-части паттерна правила.


Принцип работы в общем:

У PMInstance есть "база знаний" в виде трехместного орграфа, и набор правил.

"База знаний" хранится массивом ребер вида "S R O"
S - субъект
R - реляция
O - объект
S, R и O просто числа.

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

Например Rule1 (x1, x2 и x3 - переменные, остальные константы),
IF-часть:

X1 rel1 M
X1 rel1 N

X2 rel1 M
X2 rel1 N

X1 rel2 X3
X2 rel2 X3

X3 rel1 M

THEN-часть
X3 rel1 N

Теперь если накидать в граф такие ребра

A rel1 M
A rel1 N
B rel1 M
B rel1 N
C rel1 M
A rel2 C
B rel2 C
->

то когда вы закинете последнее ребро "B rel2 C"
сработает правило и добавит в граф ребро "C rel1 N"
вызовится событие с идентификатором сработавшего правила и набором добавленных ребер.

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


namespace PMClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
try
{
//создаем пул продукционных систем
pmPool = new PMPoolClass();

//задаем параметры пр.системы
//(строго говоря, сейчас не используется, -зарезервировано на будущее)
PMICreateParams param = new PMICreateParams();
param.name = "First";

//получаем пр.систему из пула
pmFirst = pmPool.CreatePMInstance(param);
//привязываем обработчик события
//событие возникает при срабатывании правила
pmFirst.ruleEvent += new _IPMInstanceEvents_ruleEventEventHandler(pmFirst_ruleEvent);

//создаем таблицу лейблов. Для каждой пр.системы можно создать
//произвольное количество таких таблиц.
//и для каждого узла графа пр.системы можно задать соответсвенный элемент в
//каждой такой таблице
OuterTable ot = pmFirst.CreateOuterTable("ot");

//создаем новые узлы графа и запоминаем их идентификаторы -
// строго говоря в графе хранятся только ребра и сколько бы мы
// не получили идентификаторов - на граф это не влияет
Ideas ids = new Ideas();
ids.been = pmFirst.GetNewID();
ids.cell = pmFirst.GetNewID();
ids.leftfrom = pmFirst.GetNewID();
ids.ris = pmFirst.GetNewID();
ids.setted = pmFirst.GetNewID();
ids.upfrom = pmFirst.GetNewID();

string cell1 = "cell1";
string cell2 = "cell2";
string cell3 = "cell3";

/*simple 1*/
ruleClass ruleS1 = new ruleClass(); //создаем правило

ruleS1.AndXC(cell1, ids.ris, ids.cell); //заполняем его
ruleS1.AndXC(cell1, ids.been, ids.setted);

ruleS1.AndXC(cell2, ids.ris, ids.cell);
ruleS1.AndXC(cell2, ids.been, ids.setted);

ruleS1.AndXC(cell3, ids.ris, ids.cell);

ruleS1.AndXX(cell1, ids.leftfrom, cell3);
ruleS1.AndXX(cell2, ids.upfrom, cell3);

ruleS1.ThenXC(cell3, ids.been, ids.setted);
ruleS1.EndRule(); //это обязательно

int ruleS1ID = 0;

//добавляем правило в пр.систему и запоминаем его идентификатор
//последний параметр говорит поднимать ли события при срабатывании правила
pmFirst.AddRule(ruleS1, out ruleS1ID, true);
/*simple 1*/

/*simple 2*/ //аналогично создаем и второе правило
ruleClass ruleS2 = new ruleClass();

ruleS2.AndXC(cell1, ids.ris, ids.cell);
ruleS2.AndXC(cell1, ids.been, ids.setted);

ruleS2.AndXC(cell2, ids.ris, ids.cell);
ruleS2.AndXC(cell2, ids.been, ids.setted);

ruleS2.AndXC(cell3, ids.ris, ids.cell);

ruleS2.AndXX(cell3, ids.leftfrom, cell1);
ruleS2.AndXX(cell3, ids.upfrom, cell2);

ruleS2.ThenXC(cell3, ids.been, ids.setted);
ruleS2.EndRule();

int ruleS2ID = 0;
pmFirst.AddRule(ruleS2, out ruleS2ID, true);
/*simple 2*/

pmFirst.StartInstance(); //запускам систему
//теперь мы можем накидывать ребра

matr = new Matr(20, this, ref pmFirst, ref ot, ids);
matr.Draw();

}
catch (Exception exp)
{
MessageBox.Show("Error: " + exp.Message);
}
}

void pmFirst_ruleEvent(int ruleId, int taId)
{
//ruleId у нас не используется т.к. then-часть обоих правил одинакова
// - следовательно обрабатываться они могут одинаково
//taId - зарезервирован для будущего использования
matr.ActivateCells();
}

PMPoolClass pmPool;
PMInstance pmFirst;
Matr matr;
}

public struct Ideas
{
public int cell;
public int ris;
public int setted;
public int been;
public int leftfrom;
public int upfrom;
};

public class Matr
{
public Matr(int size, Form frm, ref PMInstance pm, ref OuterTable ot, Ideas ids)
{
this.size = size;
this.ids = ids;
this.pm = pm;
this.ot = ot;
this.frm = frm;
matr = new int[size, size];
for (int i = 0; i < size; ++i)
{
for (int j = 0; j < size; ++j)
{
//метод OuterTable во-первых возвращает идентификатор нового узла графа
//во вторых ставит ему в соответствие элемент (лейбл)
//в качестве такового мы используем номер строки и столбца через запятую
matr[i, j] = ot.AddElem(i.ToString() + "," + j.ToString());
//вот здесь мы наполняем пр.систему ребрами
pm.PutLink(matr[i, j], ids.ris, ids.cell, true);
if (j > 0) pm.PutLink(matr[i, j - 1], ids.upfrom, matr[i, j], true);
if (i > 0) pm.PutLink(matr[i - 1, j], ids.leftfrom, matr[i, j], true);
}
}
}

public void Draw()
{
for (int i = 0; i < size; ++i)
{
for (int j = 0; j < size; ++j)
{
Button cb = new Button();
cb.Text = "";
cb.Width = 20;
cb.Height = 30;
cb.Left = 25 * i + 20;
cb.Top = 35 * j + 50;
cb.Click += new EventHandler(cb_Click);
cb.Tag = (i * size + j).ToString();
frm.Controls.Add(cb);
}
}
}

//метод запускается при срабатывании правила
public void ActivateCells()
{
Array sub, rel, ob, positive;
//получаем массив всех полученных при срабатывании правила ребер
pm.GetActuatedTriplets(out sub, out rel, out ob, out positive);
for (int tr = 0; tr < sub.Length; ++tr)
{
string tmp;

//получаем из таблицы лейбл, соответвующий для этого узла
//узнаем из него номер строки и столбца
if (!ot.GetElemString(((int[])sub)[tr], out tmp)) continue;

string[] tmp2 = tmp.Split('','');
if (tmp2.Length != 2) continue;

int y = Convert.ToInt32(tmp2[0]);
int x = Convert.ToInt32(tmp2[1]);

frm.Controls[y * size + x].Text = "0";
}
}

void cb_Click(object sender, EventArgs e)
{
Button me = (Button)sender;
me.Text = "0";
int index1 = (int)(Convert.ToInt32((string)me.Tag) / size);
int index2 = (Convert.ToInt32((string)me.Tag) - size * index1);

//при клике на кнопку добавляем в систему ребро
pm.PutLink(matr[index1, index2], ids.been, ids.setted, true);
}

public int size;
int[,] matr;
PMInstance pm;
OuterTable ot;
Form frm;
Ideas ids;
}
}
[Ответ][Цитата]
MadGod
Сообщений: 413
На: Продукционная система
Добавлено: 19 янв 09 13:07
Это здорово.


[Ответ][Цитата]
гость
45.84.107.*
На: Продукционная система
Добавлено: 08 авг 26 9:01
в конце концов неплохо вышло, хотя и пришлось продать душу дьяволу
[Ответ][Цитата]
гость
212.47.237.*
На: Продукционная система
Добавлено: 08 авг 26 11:03
Цитата:
Автор: гость

продать душу дьяволу
Евросоюз окончательно согласовал конфигурацию собственной спутниковой системы связи IRIS2, которую часто называют европейским ответом Starlink.

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

Первые спутники планируют запустить в 2029 году, после чего начнется постепенное развертывание сервисов.

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

По масштабу IRIS2 будет значительно меньше Starlink, у которого уже более 10 тысяч активных спутников, однако задачи у систем разные.

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

В дальнейшем, в месте и с расширением сети, доступ к IRIS планируют открыть и для бизнеса и обычных пользователей.
[Ответ][Цитата]
 Стр.1 (1)