unit AIObj
Разрабатываем экспертную систему. Урок
7. Начинаем писать ЭС на C#
Это последний урок из серии "Разрабатываем экспертную систему ", публикуемый в
бесплатном разделе. Начиная со следующего,
публикация уроков будет продолжена в платном
разделе. В бесплатном же разделе иногда, возможно, будут опубликованы
некоторые отдельные статьи посвященные экспертным системам и
искусственному интеллекту.
Исходники к уроку можно скачать
здесь.
На протяжении всего цикла уроков по разработке экспертной системы мы изучили
немного теории и попробовали написать простейшую экспертную систему, переведя
пример программного кода со старого Бэйсика на Делфи. Думаю, этого достаточно,
что бы перейти, наконец то, к серьезному программированию. Поэтому с
сегодняшнего урока мы начнем писать реальную экспертную систему на языке
программирования C#.
Если вы внимательно изучали предыдущие уроки, то наверняка заметили, что по
своей сути рассмотренный нами пример простой ЭС представляет из себя не что
иное, как
нейронную сеть, состоящую всего из
одного элемента. Мы, конечно, сможем запрограммировать более сложную ИНС, но
начнем пока с того, что создадим интерфейс и шаблон главного класса будущей
программы.
И так, запускаем Visual Studio и создаем новый проект*:
Кинем на форму меню*:
Назначим ему нормальное имя*:
И введем пока очень простое меню*:
Теперь добавим к нашему проекту новый класс*:
Назвав его ExpertSystemCore*:
Аналогично нам нужно добавить другие классы (ExpertSystemData.cs,
ExpertSystemWindowsForm.cs, Proposition.cs), а так же
интерфейс IExpertSystemForm.cs*:
Для добавления интерфейса мы выбираем интерфейс*:
Для чего мы делаем интерфейс? Для связи ядра экспертной системы и диалоговой
формы. Вдруг мы в будущем захотим сильно переделать пользовательский интерфейс,
или переписать нашу ЭС на технологию
WPF. В этом случае мы просто меняем реализацию интерфейса
IExpertSystemForm и все. А логика ЭС как была так и осталась, мы ее трогать уже
не будем.
Для начала мы просто предусмотрим в интерфейсе метод draw_propositions -
перерисовать таблицу утверждений и свойство Caption - заголовок формы:
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
namespace
ExpertSystem
{
interface
IExpertSystemForm
{
///
<summary>
///
Заголовок
формы
///
</summary>
string Caption {
get; set; }
///
<summary>
///
Перерисовать
утверждения
///
</summary>
///
<param name="propositions">Список
утверждений</param>
void draw_propositions(List<Proposition>
propositions);
}
} |
Для того, что бы реализовать этот интерфейс, нам потребуется сама форма. В
принципе, форма у нас уже есть, она создалась автоматически, дадим ей только
нормальное название ExpertSystemForm*:
К форме нам надо присобачить меню.
В меню "Файл" у нас пока будет три пункта: "открыть", "сохранить" и "сохранить
как"*:
В меню "Утверждения" пока только один, мы сначала создадим заготовку программы,
потом будем ее "допиливать"*:
Еще нам надо поместить на форму контейнер для таблицы (TabControl)*:
Пока у него будет только одна закладка ("Утверждения")*:
И на нее то мы и помещаем самую таблицу утверждений*:
Таблицу утверждений мы будем хранить в типизированном списке
List, тип элементов Proposition, это класс нам надо создать. Вводим его
код в файл Proposition.cs (обратите внимание что класс сериализуемый, что бы мы
могли сохранить его в файл):
using System.Linq;
using System.Text;
namespace ExpertSystem
{
///
<summary>
///
Утверждение. Например "Это летает",
///
"Это ползает", "Имеет хвост", "Имеет перья"
///
</summary>
[Serializable]
public
class
Proposition
{
///
<summary>
///
Текст утверждения
///
</summary>
public
string caption;
///
<summary>
///
Имеет ли место данное утверждение
///
</summary>
public
bool itis;
}
} |
Сами данные экспертной системы у нас будут храниться в объекте класса
ExpertSystemData (пока там только утверждения):
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
namespace
ExpertSystem
{
[Serializable]
public class
ExpertSystemData
{
public List<Proposition>
propositions;
public ExpertSystemData()
{
propositions =
new List<Proposition>();
}
}
} |
Наконец, управлять экспертной системой будет ядро, реализуем в нем функции
сохранения и открытия файлов, а так же метод для тестирования добавления нового
утверждения:
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.Windows.Forms;
using
System.IO;
using
System.Runtime.Serialization;
using
System.Runtime.Serialization.Formatters.Binary;
namespace
ExpertSystem
{
public class
ExpertSystemCore
{
public ExpertSystemCore(ExpertSystemForm
app_form)
{
data = new
ExpertSystemData();
form = new
ExpertSystemWindowsForm();
(form as
ExpertSystemWindowsForm).form = app_form;
FFileName = "";
}
public void
AddProposition()
{
Proposition prop =
new Proposition();
prop.caption = "Тест";
prop.itis = true;
data.propositions.Add(prop);
form.draw_propositions(data.propositions);
}
///
<summary>
///
Скрытое
имя
файла
///
</summary>
private string
FFileName;
///
<summary>
///
Имя
файла,
открытого
в
даннмый
момент
///
</summary>
public string
FileName
{
get
{
return FFileName;
}
}
///
<summary>
///
База
знаний
экспертной
системы,
/// а так же другие нужные для работы данные
///
</summary>
private
ExpertSystemData data;
///
<summary>
/// Связь с формой приложения через интерфейс
IExpertSystemForm
///
</summary>
private
IExpertSystemForm form;
///
<summary>
///
Обновить
форму
приложения
///
</summary>
private void
UpdateForm()
{
form.Caption = FileName;
}
///
<summary>
///
Открыть
файл
экспертной
системы
///
</summary>
public void
Open()
{
OpenFileDialog openFileDialog
= new
OpenFileDialog();
openFileDialog.Title = "Открыть
проект...";
openFileDialog.Filter = "Файлы
экспертных
систем|*.es|Все
файлы|*.*";
if (openFileDialog.ShowDialog()
== System.Windows.Forms.DialogResult.Cancel)
return;
try
{
FileStream fs =
new FileStream(openFileDialog.FileName,
FileMode.Open);
BinaryFormatter formatter
= new
BinaryFormatter();
data = (ExpertSystemData)formatter.Deserialize(fs);
fs.Close();
FFileName = openFileDialog.FileName;
UpdateForm();
form.draw_propositions(data.propositions);
}
catch (IOException
ex)
{
MessageBox.Show(ex.Message,
"Ошибка",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
///
<summary>
///
Сохранить файл экспертной системы
///
</summary>
public
void Save()
{
//Если имя
файла не задано то вызываем диалог выбора файла
if
(FFileName == "")
{
SaveAs();
return;
}
FileStream fs =
new FileStream(FFileName,
FileMode.OpenOrCreate);
BinaryFormatter formatter =
new
BinaryFormatter();
formatter.Serialize(fs, data);
fs.Close();
UpdateForm();
}
///
<summary>
///
Сохранить файл экспертной системы с диалогом выбора файла
///
</summary>
public void
SaveAs()
{
SaveFileDialog saveFileDialog
= new
SaveFileDialog();
saveFileDialog.Title = "Сохранение
проекта...";
saveFileDialog.Filter = "Файлы
экспертных
систем|*.es|Все
файлы|*.*";
if (saveFileDialog.ShowDialog()
== System.Windows.Forms.DialogResult.Cancel)
return;
FFileName = saveFileDialog.FileName;
Save();
}
}
} |
Теперь можно реализовать и обработчики пунктов меню, вот как будет выглядеть
класс главной формы после их реализации:
using
System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Linq;
using
System.Text;
using
System.Windows.Forms;
namespace
ExpertSystem
{
public partial
class
ExpertSystemForm : Form
{
///
<summary>
///
Ядро экспертной системы
///
</summary>
private
ExpertSystemCore core;
public ExpertSystemForm()
{
InitializeComponent();
core = new
ExpertSystemCore(this);
}
private void
tsmiOpen_Click(object sender,
EventArgs e)
{
core.Open();
}
private void
tsmiSave_Click(object sender,
EventArgs e)
{
core.Save();
}
private void
tsmiSaveAs_Click(object sender,
EventArgs e)
{
core.SaveAs();
}
private void
tsmiAddProposition_Click(object sender,
EventArgs e)
{
core.AddProposition();
}
}
} |
Ну, и еще у нас осталась реализация интерфейса IExpertSystemForm. Для этого мы
создаем класс ExpertSystemWindowsForm:
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
namespace
ExpertSystem
{
public class
ExpertSystemWindowsForm :
IExpertSystemForm
{
public
ExpertSystemForm form { get;
set; }
///
<summary>
///
Заголовок
формы
///
</summary>
public string
Caption
{
get
{
if (form !=
null) return
form.Text; else
return "NULL";
}
set
{
if (form !=
null) form.Text =
value;
}
}
///
<summary>
///
Перерисовать
утверждения
///
</summary>
///
<param name="propositions">Список
утверждений</param>
public void
draw_propositions(List<Proposition>
propositions)
{
form.dgvPropositions.Rows.Clear();
if (propositions.Count == 0)
return;
form.dgvPropositions.RowCount = propositions.Count;
int j = 0;
foreach (Proposition
item in propositions)
{
redraw_row(j, item);
j++;
}
}
///
<summary>
///
Перерисовать
строку
///
</summary>
///
<param name="j">Номер
строки</param>
///
<param name="item">Утверждение</param>
private void
redraw_row(int j,
Proposition item)
{
if (j >=
form.dgvPropositions.RowCount) return;
if (j == -1)
return;
form.dgvPropositions.Rows[j].Cells[0].Value = item.caption;
form.dgvPropositions.Rows[j].Cells[1].Value = item.itis;
}
}
} |
После чего мы можем начать тестирование нашей заготовки программы. Попробуем
добавить парочку тестовых утверждений и сохранить файл:
После сохранения у нас должен измениться заголовок:
Проверьте, открывает ли программа сохраненный файл, восстанавливаются ли данные,
которые вы сохранили.
На этом урок закончим, в будущих уроках продолжим писать
экспортную систему на C#.
Скриншоты, помеченные знаком *,
являются цитатами и иллюстрациями программного
продукта "Microsoft Visual Studio 2010 Professional", авторское
право на который принадлежит корпорации
Microsoft..
|