2. Шаров, О. Г. Нейтрализация синтаксических ошибок в графических языках / О. Г. Шаров, А. Н. Афанасьев // Программирование. - 2008. - № 1. - С. 61 -66.
4. Шаров, О. Г. Методы и средства трансляции графических диаграмм / О. Г. Шаров, А. Н. Афанасьев // Программирование. - 2011. - № 3. - С. 65 - 76.
5. Афанасьев, А. Н. Программная система анализа диаграммных языков / А. Н. Афанасьев, Р. Ф. Гайнуллин, О. Г. Шаров // Программные продукты и системы. - 2012. - № 3. - С. 138 - 141.
УДК 519.688, 004.42
ОБЪЕКТНО-ОРИЕНТИРОВАННЫЙ СИМУЛЯТОР МАШИНЫ ТЬЮРИНГА
Штанюк Антон Александрович, к.т.н., доцент кафедры программной инженерии Нижегородского государственного университета им. Н.И. Лобачевского, [email protected]
Введение
Цель данной работы состоит в построении программного симулятора машины Тьюринга (МТ) с использованием объектно-ориентированного языка программирования C++ [1]. Программа может быть полезной в рамках учебного процесса при изучении и программировании МТ. Цель состояла в том, чтобы создать максимально простую программную реализацию, которую легко изучать и развивать. Для упрощения программирования самой МТ команды машины были описаны в виде строк на достаточно простом языке, соответствующем классическому представлению команд [2].
1. Описание МТ
Машина Тьюринга является теоретическим компьютером и широко используется при исследовании алгоритмов, знакомстве с процессами вычислений на самом низком, «механическом» уровне.
Необходимыми компонентами такого устройства является лента с ячейками, при этом в каждой ячейке находится только один символ. Имеется указатель, «обозревающий» одну ячейку, а также устройство, позволяющее двигать указатель вдоль ленты. Впрочем, широко распространено эквивалентное представление в виде неподвижного указателя и лентопротяжного механизма (как в катушечном магнитофоне).
Указатель имеет возможность просматривать содержимое ячеек, менять свое состояние, а также перезаписывать содержимое ленты.
Математически машина полностью описывается набором следующих множеств:
129
Q={q0,qi,...,qm} - множество состояний машины (одно будет начальным, еще одно -конечным);
C={ c1, c2cn} - множество символов, записанных на ленте;
D={d1,d2,d3} - команды (движение вправо/влево, на месте);
R={r1,r2,.,rk} - множество правил (программа).
Множество правил задает поведение машины. Пример правила:
q00*->q01xR
Интерпретировать его нужно следующим образом: если текущее состояние машины -q0 0, а текущий символ на ленте ‘*’, то нужно сменить состояние на q01, записать символ ‘x’ на место текущего и сдвинуться по ленте вправо.
Исходные данные - это содержимое ленты до пуска машины. Результатом является содержимое ленты после остановки машины. Остановка происходит, если машина перешла в указанное состояние.
2. Программная реализация
Множество команд для перемещений вдоль ленты задается с помощью механизма перечислимых типов:
enum {R=1,L=-1,H=0};
(символы обозначают, соответственно, движение вправо, влево и стояние на месте) Состояние машины задается с помощью структуры, в которую входит название состояния (например “q0 0”), а также текущий символ на ленте.
struct State {
string q; char sym;
};
Каждое правило программы описывается с помощью структуры
struct Rule {
string text; // содержимое правила string curQ; // текущее состояние string nextQ; // следующее состояние char curSym; // текущий символ char nextSym; // следующий символ char cmd; // команда на перемещение
};
Экземпляр данной структуры заполняется информацией, извлеченной из строки правила. Так, если мы вводим в машину правило «q00*->q01xR»,
то содержимое полей будет следующим:
text - q00*->q01xR curQ - q00
nextQ - q01
curSym - * nextSym - x cmd - R
Алгоритм разбора строки правила предполагает наличие всех символов на определенных позициях. Единственное, что может меняться в этом формате - ширина поля записи состояния. То есть запись q0 0 требует трех знакомест, а q0 0 0 - уже четырёх. Эта
130
ширина определяется, исходя из предполагаемого числа состояний, и передается в машину при ее создании (параметр width).
Теперь опишем главный компонент симулятора - класс машины Тьюринга (class MT):
class MT
{
public:
MT(string,string,int); char getSym()const { return mem[curPos];
}
string getState()const { return curState.q;
}
string getMem() const { return mem;
// конструктор
// селектор символа из тек. позиции // селектор текущего состояния // селектор содержимого ленты
}
bool addRule(string); // добавление правила void step(); // шаг машины
private:
void process(int);
string mem; // содержимое ленты
int width; // ширина поля записи состояния
int curPos; // текущая позиция на ленте
State curState; // текущее состояние машины vector<Rule> rules; // вектор правил (программа) int rNum; // количество правил
};
Интерфейс класса включает в себя конструктор (MT), три селектора (getSym,getState,getMem), возвращающих значения внутренних переменных, метод (addRule), добавляющий правила, и метод (step), моделирующий работу одного шага машины. В закрытый раздел класса помещен еще один вспомогательный метод (process), упрощающий выполнение программы машиной.
В состав машины входит содержимое ленты с ячейками в виде строки стандартной библиотеки (mem), текущая позиция на ленте в виде числового значения (curPos), текущее состояние машины (curState), вектор правил (rules), а также две вспомогательные переменные: width - для хранения ширины поля записи состояния и rNum - количество правил в программе.
Реализация конструктора проста. Создается новая машина, для которой указывается запись на ленте, начальное состояние и значение переменной width:
MT::MT(string mem,string beg state,int width)
{
this->mem=mem;
this->width=width;
curPos=0;
curState.q=beg state;
curState.sym=mem[curPos];
rNum=0;
}
Текущая позиция устанавливается на первый символ строки.
При добавлении нового правила происходит его синтаксический разбор и помещение в вектор правил, который на момент создания машины пуст. Данная реализация МТ предполагает синтаксическую корректность вводимых правил, но может быть без труда снабжена функцией проверки.
131
bool MT::addRule(string rule)
{
rules.push back(*new Rule); rules[rNum].text=rule;
rules[rNum].curQ.assign(rule,0,width);
rules[rNum].curSym=rule[width];
size t pos=rule.find("->")+(width-1);
rules[rNum].nextQ.assign(rule,pos,width);
rules[rNum].cmd=rule[rule.length()-1];
rules[rNum++].nextSym=rule[rule.length()-2];
return true;
}
Рассмотрим работу функций process и step :
void MT::process(int i)
{
if(rules[i].cmd=='L')
curPos+=L;
else if(rules[i].cmd=='R') curPos+=R;
curState.q=rules[i].nextQ;
if(curPos<0)
return;
if(curPos>=mem.length())
mem.resize(mem.size()+1,,AI);
curState.sym=mem[curPos];
}
void MT::step()
{
int i;
for(i=0;i<rNum;i++) {
if(curState.q==rules[i].curQ&&curState.sym==rules[i].curSym)
{
if(rules[i].nextSym!=' ')
mem[curPos]=rules[i].nextSym;
process(i);
}
}
}
Шаг машины возможен, только если есть введенные правила. Далее мы пытаемся определить, какое правило может быть использовано на данном шаге. Для этого просматривается вектор правил и при совпадении первого состояния в правиле с текущим, а также первого символа в правиле с текущим, считаем, что соответствующее правило найдено. Нам необходимо заместить текущий символ на ленте на новый (если только в правиле не значится пробел), а также обработать команду, записанную в правиле, и, возможно, сменить состояние машины. Эту работу выполняет вспомогательный метод process, вызываемый из step. В процессе обработки правила в функции process могут возникнуть две исключительные ситуации. Первая из них связана с выходом за левую границу ленты. Эта ситуация в симуляторе считается ошибочной и она приводит к неопределенному поведению машины. Вторая ситуация связана с выходом за правую границу ленты. Данная ситуация ошибочной не считается, и в этом случае задействуется новая ячейка с номером, на единицу больше текущего. Таким образом, лента может наращиваться в одном направлении, пока в системе имеется свободная память.
3. Пример работы машины
132
Рассмотрим пример реализации программы, эмулирующей умножение двух целых чисел в единичной системе счисления (1-1,11-2,111-3,...).
int main() {
MT mt("*11x11=*","q00",3); cout<<mt.getMem()
<<" "<<mt.getState()
<<" "<<mt.getSym()<<endl;
mt.addRule("q00*->q00 R"); mt.addRule("q001->q00 R"); mt.addRule("q00x->q01xR"); mt.addRule("q011->q02aR"); mt.addRule("q021->q021L"); mt.addRule("q02a->q02aL"); mt.addRule("q02=->q02=L"); mt.addRule("q02x->q03xL"); mt.addRule("q031->q04aR"); mt.addRule("q03a->q03aL"); mt.addRule("q03*->q06*R"); mt.addRule("q04x->q04xR"); mt.addRule("q04a->q04aR"); mt.addRule("q04=->q04=R"); mt.addRule("q041->q041R"); mt.addRule("q04*->q051R"); mt.addRule("q05A->q02*L"); mt.addRule("q06a->q061R"); mt.addRule("q06x->q07xR"); mt.addRule("q07a->q07aR"); mt.addRule("q071->q02aR"); mt.addRule("q07=->q08=L"); mt.addRule("q08a->q081L"); mt.addRule("q08x->q09 H");
for(;;) {
mt.step();
cout<<mt.getMem()
<<""<<mt.getState()
<<""<<mt.getSym()<<endl; if(mt.getState()=="q09") break;
}
return 0;
}
В качестве результата работы программы печатается последовательность строк, отображающих состояние ленты, текущее состояние машины и текущий символ на ленте. Для удобства эти строки приведены ниже в виде таблицы:
*11x11=* q0 0 * *aaxa1=11* q02 = *1axaa=111* q03 a
*11x11=* q0 0 1 *aaxa1=11* q02 1 *1axaa=111* О CO 1
*11x11=* q0 0 1 *aaxa1=11* q02 a *aaxaa=111* q04 a
*11x11=* q0 0 x *aaxa1=11* q02 x *aaxaa=111* q04 x
*11x11=* q01 1 *aaxa1=11* q03 a *aaxaa=111* q04 a
*11xa1=* q02 1 *aaxa1=11* q03 a *aaxaa=111* q04 a
*11xa1=* q02 a *aaxa1=11* q03 * *aaxaa=111* q04 =
*11xa1=* q02 x *aaxa1=11* q06 a *aaxaa=111* q04 1
*11xa1=* О CO 1 *1axa1=11* q06 a *aaxaa=111* q04 1
*1axa1=* q04 x *11xa1=11* q06 x *aaxaa=111* q04 1
*1axa1=* q04 a *11xa1=11* q07 a *aaxaa=111* q04 *
*1axa1=* q04 1 *11xa1=11* q07 1 *aaxaa=1111 > о СЛ
133
*1axa1=* q04 = *11xaa=11* q02 = *aaxaa=1111* q02 1
*1axa1=* q04 * *11xaa=11* q02 a *aaxaa=1111* q02 1
*1axa1=1A q05 л *11xaa=11* q02 a *aaxaa=1111* q02 1
*1axa1=1* q02 1 *11xaa=11* q02 x *aaxaa=1111* q02 1
*1axa1=1* q02 = *11xaa=11* q03 1 *aaxaa=1111* q02 =
*1axa1=1* q02 1 *1axaa=11* q04 x *aaxaa=1111* q02 a
*1axa1=1* q02 a *1axaa=11* q04 a *aaxaa=1111* q02 a
*1axa1=1* q02 x *1axaa=11* q04 a *aaxaa=1111* q02 x
*1axa1=1* q03 a *1axaa=11* q04 = *aaxaa=1111* q03 a
*1axa1=1* q03 1 *1axaa=11* q04 1 *aaxaa=1111* q03 a
*aaxa1=1* q04 a *1axaa=11* q04 1 *aaxaa=1111* q03 *
*aaxa1=1* q04 x *1axaa=11* q04 * *aaxaa=1111* q06 a
*aaxa1=1* q04 a *1axaa=111 л q05 л *1axaa=1111* q06 a
*aaxa1=1* q04 1 *1axaa=111 * q02 1 *11xaa=1111* q06 x
*aaxa1=1* q04 = *1axaa=111 * q02 1 *11xaa=1111* q07 a
*aaxa1=1* q04 1 *1axaa=111 * q02 1 *11xaa=1111* q07 a
*aaxa1=1* q04 * *1axaa=111 * q02 = *11xaa=1111* q07 =
*aaxa1=11 л q05 л *1axaa=111 * q02 a *11xaa=1111* q0 8 a
*aaxa1=11 * q02 1 *1axaa=111 * q02 a *11xa1=1111* q0 8 a
*aaxa1=11 * q02 1 *1axaa=111 * q02 x *11x11=1111* q0 8 x
*11x11=1111* q0 9 x
Конечная строка содержит условие задачи и числовой результат (*11x11 = 1111 *) .
В заключение отметим, что данный программный симулятор может быть усовершенствован путем добавления новых возможностей:
• проверка правил на корректность;
• расширение ленты в обе стороны;
• загрузка правил из текстового файла.
Литература
1. Бьярне Страуструп. Программирование: принципы и практика использования C++,
исправленное издание— М.: «Вильямс», 2011
2. Википедия [Электронный ресурс] http://en.wikipedia.org/wiki/Машина Тьюринга
УДК 621.311
ПРИНЦИПЫ ПОСТРОЕНИЯ ОРГАНИЗАЦИОННОЙ И РАСЧЕТНОЙ МОДЕЛЕЙ В ИНФОРМАЦИОННЫХ СИСТЕМАХ ДЛЯ ЗАДАЧ ПРОИЗВОДСТВЕННОГО И ФИНАНСОВОГО ПЛАНИРОВАНИЯ ГЕНЕРИРУЮЩИХ КОМПАНИЙ
Сердюкова Надежда Викторовна, аспирант, Саратовский государственный технический университет имени Гагарина Ю.А., Россия, Саратов, [email protected]
Основной обязанностью аналитиков и оперативного персонала генерирующих компаний (ГК) является контроль большого числа технико-экономических показателей (ТЭП), характеризующих себестоимость производства энергии. Главным свойствами большинства ТЭП являются их зависимость от используемого оборудования и взаимозависимость показателей друг от друга. Для учёта ТЭП и расчёта их значений в динамике часто применяются MES-системы (от английского Manufacturing Execution Systems - системы управления производством), задачами которых являются построение технологической модели ТЭС, сбор технологической информации, расчёт необходимых ТЭП и хранение всей этой информации в разрезах построенной модели. На основании этих данных в MES-системах работают модули визуализации и управления моделями, модули планирования и оптимизации производства, модули формирования корпоративной отчётности и финансового планирования.
134