winmain.cpp
#include <windows.h>
#include "library.h"
#include "petry.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
CLogFile Log;
////////////////////////////////////////////////////////////////////////////////////////////////////
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
CNet Petry;
Log.Setup("log.txt");
Log.Reset();
if(Petry.LoadFromFile("input.txt"))
{
Petry.Run();
Petry.SaveEC("output.txt");
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
library.h
#ifndef LIBRARY
#define LIBRARY
////////////////////////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
class CList //циклический двунаправленный список
{
public:
CList(void);
~CList();
int GetCount(void); //получить длину списка
void Clear(void); //очистить список
void Free(void); //освободить память из-под элементов и очистить список
void Add(void); //добавить элемент после текущего и сделать его текущим
void Delete(void); //удалить текущий элемент и сделать текущим следующий за ним
void* GetData(void); //получить текущее значение
void SetData(void*); //установить текущее значение
void GoBegin(void); //сделать текущим первый элемент
void GoNext(void); //сделать текущим следующий элемент
void GoPrev(void); //сделать текущим предыдущий элемент
struct ListItem //элемент списка
{
void* Data; //данные
ListItem* Next; //указатель на следующий элемент
ListItem* Prev; //указатель на предыдущий элемент
};
private:
int Count; //количество элементов в списке
ListItem* Begin; //первый элемент списка
ListItem* Cur; //текущий элемент списка
};
////////////////////////////////////////////////////////////////////////////////////////////////////
class CLogFile //файл протокола
{
public:
CLogFile(void);
void Setup(char*); //установить имя файла
void Reset(void); //сброс содержимого протокола
void Print(char*, ...); //форматированная запись в протокол (см. printf)
private:
char FileName[256]; //имя файла протокола
};
////////////////////////////////////////////////////////////////////////////////////////////////////
class CSyntaxer //синтаксический анализатор текстовой информации
{
public:
CSyntaxer(void);
~CSyntaxer();
int Open(char*); //открыть файл для анализа
void Close(void); //закрыть файл
int GetWord(char*); //получить слово из файла
int GetNumber(int*); //получить целое число из файла
private:
int SkipComment(void); //пропустить комментарий
int SkipSpaces(void); //пропустить незначащие символы (пробел, табуляция и т.п.)
private:
FILE* file;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
#endif
petry.h
#ifndef PETRY
#define PETRY
////////////////////////////////////////////////////////////////////////////////////////////////////
#include "library.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
struct SItem //состояние
{
int ID; //идентификатор
int M; //количество меток в состоянии
CList TS; //список входящих связей
CList ST; //список выходящих связей
};
////////////////////////////////////////////////////////////////////////////////////////////////////
struct TItem //переход
{
int ID; //идентификатор
bool A; //флаг активности
int D; //время активности
CList ST; //список входящих связей
CList TS; //список выходящих связей
};
////////////////////////////////////////////////////////////////////////////////////////////////////
struct STItem //ST связь
{
int N; //количество захватываемых меток
SItem* S; //состояние-источник
TItem* T; //переход-приемник
};
////////////////////////////////////////////////////////////////////////////////////////////////////
struct TSItem //TS связь
{
int N; //количество отдаваемых меток
TItem* T; //переход-источник
SItem* S; //состояние-приемник
};
////////////////////////////////////////////////////////////////////////////////////////////////////
struct SPItem //описание внешнего воздействия
{
SItem* S; //объект воздействия
int P; //момент воздействия
int M; //количество добавляемых меток
};
////////////////////////////////////////////////////////////////////////////////////////////////////
struct TPItem //описание активного перехода
{
TItem* T; //переход
int P; //момент конца активности
};
////////////////////////////////////////////////////////////////////////////////////////////////////
struct ECItem //элемент календаря событий
{
TItem* T; //переход
int P1; //момент начала активности
int P2; //момент конца активности
};
////////////////////////////////////////////////////////////////////////////////////////////////////
class CNet //сеть Петри
{
public:
~CNet();
int LoadFromFile(char*); //загрузить информацию о сети из файла
int Run(void); //начать работу сети
void Clear(void); //очистить сеть
int SaveEC(char*); //сохранить календарь событий в файле
private:
int LoadS(void); //загрузить S из файла
int LoadT(void); //загрузить T из файла
int LoadST(void); //загрузить ST из файла
int LoadTS(void); //загрузить TS из файла
int LoadSP(void); //загрузить SP из файла
int LoadTP(void); //загрузить TP из файла
int SetupS(void); //настроить списки связей для S
int SetupT(void); //настроить списки связей для T
int Prepare(void); //подготовить EC к началу работы сети
int Finish(void); //завершить выполнение переходов
int External(void); //выполнить внешние воздействия
int Start(void); //начать выполнение переходов
private:
CList S; //список состояний
CList T; //список переходов
CList ST; //список ST связей
CList TS; //список TS связей
CList SP; //протокол внешних воздействий
CList TP; //протокол активных переходов
CList EC; //календарь событий
CSyntaxer Stx; //необходим для загрузки файлов
int Time; //текущее время
};
////////////////////////////////////////////////////////////////////////////////////////////////////
#endif
library.cpp
#include "library.h"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
CList::CList(void)
{
Count = 0;
Begin = 0;
Cur = 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
CList::~CList()
{
Clear();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void CList::Clear(void)
{
while(Cur)
Delete();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void CList::Free(void)
{
void* p;
while(Cur)
{
p = GetData();
if(p)
delete p;
Delete();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void CList::Delete(void)
{
ListItem* n;
ListItem* p;
//если список пустой
if(!Cur)
return;
//если в списке один элемент
if(Cur->Next == Cur)
{
delete Cur;
Begin = 0;
Cur = 0;
}
//если в списке более одного элемента
else
{
n = Cur->Next;
p = Cur->Prev;
delete Cur;
p->Next = n;
n->Prev = p;
Cur = n;
}
--Count;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CList::GetCount(void)
{
return Count;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void CList::Add(void)
{
ListItem* t;
ListItem* n;
//создать элемент
t = new ListItem;
if(!t)
return;
t->Data = 0;
//если список пустой
if(!Cur)
{
t->Next = t;
t->Prev = t;
Begin = t;
}
//если список непустой
else
{
n = Cur->Next;
t->Next = n;
t->Prev = Cur;
Cur->Next = t;
n->Prev = t;
}
Cur = t;
++Count;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void CList::GoBegin(void)
{
Cur = Begin;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void CList::GoNext(void)
{
if(Cur)
Cur = Cur->Next;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void CList::GoPrev(void)
{
if(Cur)
Cur = Cur->Prev;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void* CList::GetData(void)
{
if(!Cur)
return 0;
return Cur->Data;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void CList::SetData(void* p)
{
if(!Cur)
return;
Cur->Data = p;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
CLogFile::CLogFile(void)
{
FileName[0] = 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void CLogFile::Setup(char* fn)
{
strcpy(FileName, fn);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void CLogFile::Reset(void)
{
FILE* f;
f = fopen(FileName, "w");
if(f)
fclose(f);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void CLogFile::Print(char* str, ...)
{
FILE* f;
va_list v;
if(!str)
return;
f = fopen(FileName, "a");
if(!f)
return;
//запись в протокол
va_start(v, str);
vfprintf(f, str, v);
va_end(v);
fclose(f);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
CSyntaxer::CSyntaxer(void)
{
file = 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
CSyntaxer::~CSyntaxer()
{
Close();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CSyntaxer::Open(char* fn)
{
Close();
file = fopen(fn, "rb");
if(!file)
return 0;
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void CSyntaxer::Close(void)
{
if(file)
{
fclose(file);
file = 0;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CSyntaxer::SkipComment(void)
{
int c;
if(!file)
return 0;
while(1)
{
c = getc(file);
if(c == -1 || c == '\n')
break;
}
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CSyntaxer::SkipSpaces(void)
{
int c;
if(!file)
return 0;
while(1)
{
c = getc(file);
if(c == -1)
break;
if(c == ' ' || c == '\t' || c == '\n' || c == '\r')
continue;
if(c == ';')
{
if(!SkipComment())
return 0;
continue;
}
fseek(file, ftell(file) - 1, 0);
break;
}
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CSyntaxer::GetWord(char* str)
{
int c;
int i;
*str = 0;
if(!file)
return 0;
//чтение слова
if(!SkipSpaces())
return 0;
i = 0;
while(1)
{
c = getc(file);
if(c == -1 || c == ' ' || c == '\t' || c == '\r' || c == '\n')
{
if(!i)
return 0;
break;
}
if(c == ';')
{
if(!i)
return 0;
fseek(file, ftell(file) - 1, 0);
break;
}
if(c >= 'A' && c <= 'Z')
{
str[i] = c;
++i;
continue;
}
if(c >= 'a' && c <= 'z')
{
str[i] = c;
++i;
continue;
}
return 0;
}
str[i] = 0;
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CSyntaxer::GetNumber(int* num)
{
int c;
bool minus;
bool empty;
*num = 0;
if(!file)
return 0;
//чтение числа
if(!SkipSpaces())
return 0;
minus = false;
empty = true;
while(1)
{
c = getc(file);
if(c == -1 || c == ' ' || c == '\t' || c == '\r' || c == '\n')
{
if(empty)
return 0;
break;
}
if(c == ';')
{
if(empty)
return 0;
fseek(file, ftell(file) - 1, 0);
break;
}
if(c == '-')
{
if(minus)
return 0;
minus = true;
continue;
}
if(c >= '0' && c <= '9')
{
*num = int(*num * 10 + (c - '0'));
empty = false;
continue;
}
return 0;
}
if(minus)
*num *= -1;
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
petry.cpp
#include "petry.h"
#include <string.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
extern CLogFile Log;
////////////////////////////////////////////////////////////////////////////////////////////////////
CNet::~CNet()
{
Clear();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CNet::LoadS(void)
{
int x, i;
SItem* p;
//чтение параметров S
Log.Print(" S: ");
if(!Stx.GetNumber(&x))
{
Log.Print("ID=???");
return 0;
}
Log.Print("ID=%d\n", x);
//проверка дублирования ID'а
for(i = 0; i < S.GetCount(); ++i)
{
p = (SItem*)S.GetData();
if(p->ID == x)
{
Log.Print(" Элемент S с таким ID уже есть\n");
return 0;
}
S.GoNext();
}
p = 0;
//вставка нового S в список
p = new SItem;
if(!p)
{
Log.Print(" Не хватает памяти\n");
return 0;
}
S.Add();
S.SetData((void*)p);
//задание параметров S
p->ID = x;
p->M = 0;
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CNet::LoadT(void)
{
int x, y, i;
TItem* p;
//чтение параметров T
Log.Print(" T: ");
if(!Stx.GetNumber(&x))
{
Log.Print("ID=???");
return 0;
}
Log.Print("ID=%d ", x);
if(!Stx.GetNumber(&y))
{
Log.Print("D=???");
return 0;
}
Log.Print("D=%d\n", y);
//проверка дублирования ID'а
for(i = 0; i < T.GetCount(); ++i)
{
p = (TItem*)T.GetData();
if(p->ID == x)
{
Log.Print(" Элемент T с таким ID уже есть\n");
return 0;
}
T.GoNext();
}
p = 0;
//вставка нового T в список
p = new TItem;
if(!p)
{
Log.Print(" Не хватает памяти\n");
return 0;
}
T.Add();
T.SetData((void*)p);
//задание параметров T
p->ID = x;
p->D = y;
p->A = false;
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CNet::LoadST(void)
{
int x, y, z, i;
SItem* ps;
TItem* pt;
STItem* pst;
//чтение параметров ST
Log.Print(" ST: ");
if(!Stx.GetNumber(&x))
{
Log.Print("S=???");
return 0;
}
Log.Print("S=%d ", x);
if(!Stx.GetNumber(&y))
{
Log.Print("T=???");
return 0;
}
Log.Print("T=%d ", y);
if(!Stx.GetNumber(&z))
{
Log.Print("N=???");
return 0;
}
Log.Print("N=%d\n", z);
//проверка существования ID'а S
for(i = 0; i < S.GetCount(); ++i)
{
ps = (SItem*)S.GetData();
if(ps->ID == x)
{
i = -1;
break;
}
S.GoNext();
}
if(i > -1)
{
Log.Print(" Нет элемента S с таким ID\n");
return 0;
}
//проверка существования ID'а T
for(i = 0; i < T.GetCount(); ++i)
{
pt = (TItem*)T.GetData();
if(pt->ID == y)
{
i = -1;
break;
}
T.GoNext();
}
if(i > -1)
{
Log.Print(" Нет элемента T с таким ID\n");
return 0;
}
//поиск такой же связи
for(i = 0; i < ST.GetCount(); ++i)
{
pst = (STItem*)ST.GetData();
if(pst->S == ps && pst->T == pt)
{
Log.Print(" Такая связь уже существует\n");
return 0;
}
ST.GoNext();
}
pst = 0;
//вставка нового ST в список
pst = new STItem;
if(!pst)
{
Log.Print(" Не хватает памяти\n");
return 0;
}
ST.Add();
ST.SetData((void*)pst);
//задание параметров ST
pst->N = z;
pst->S = ps;
pst->T = pt;
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CNet::LoadTS(void)
{
int x, y, z, i;
SItem* ps;
TItem* pt;
TSItem* pts;
//чтение параметров TS
Log.Print(" TS: ");
if(!Stx.GetNumber(&x))
{
Log.Print("T=???");
return 0;
}
Log.Print("T=%d ", x);
if(!Stx.GetNumber(&y))
{
Log.Print("S=???");
return 0;
}
Log.Print("S=%d ", y);
if(!Stx.GetNumber(&z))
{
Log.Print("N=???");
return 0;
}
Log.Print("N=%d\n", z);
//проверка существования ID'а T
for(i = 0; i < T.GetCount(); ++i)
{
pt = (TItem*)T.GetData();
if(pt->ID == x)
{
i = -1;
break;
}
T.GoNext();
}
if(i > -1)
{
Log.Print(" Нет элемента T с таким ID\n");
return 0;
}
//проверка существования ID'а S
for(i = 0; i < S.GetCount(); ++i)
{
ps = (SItem*)S.GetData();
if(ps->ID == y)
{
i = -1;
break;
}
S.GoNext();
}
if(i > -1)
{
Log.Print(" Нет элемента S с таким ID\n");
return 0;
}
//поиск такой же связи
for(i = 0; i < TS.GetCount(); ++i)
{
pts = (TSItem*)TS.GetData();
if(pts->S == ps && pts->T == pt)
{
Log.Print(" Такая связь уже существует\n");
return 0;
}
TS.GoNext();
}
pts = 0;
//вставка нового TS в список
pts = new TSItem;
if(!pts)
{
Log.Print(" Не хватает памяти\n");
return 0;
}
TS.Add();
TS.SetData((void*)pts);
//задание параметров TS
pts->N = z;
pts->T = pt;
pts->S = ps;
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CNet::LoadSP(void)
{
int x, y, z, i;
SItem* ps;
SPItem* psp;
//чтение параметров SP
Log.Print(" SP: ");
if(!Stx.GetNumber(&x))
{
Log.Print("S=???");
return 0;
}
Log.Print("S=%d ", x);
if(!Stx.GetNumber(&y))
{
Log.Print("P=???");
return 0;
}
Log.Print("P=%d ", y);
if(!Stx.GetNumber(&z))
{
Log.Print("M=???");
return 0;
}
Log.Print("M=%d\n", z);
//проверка существования ID'а S
for(i = 0; i < S.GetCount(); ++i)
{
ps = (SItem*)S.GetData();
if(ps->ID == x)
{
i = -1;
break;
}
S.GoNext();
}
if(i > -1)
{
Log.Print(" Нет элемента S с таким ID\n");
return 0;
}
//вставка нового SP в список
psp = new SPItem;
if(!psp)
{
Log.Print(" Не хватает памяти\n");
return 0;
}
SP.Add();
SP.SetData((void*)psp);
//задание параметров SP
psp->S = ps;
psp->P = y;
psp->M = z;
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CNet::LoadTP(void)
{
int x, y, i;
TItem* pt;
TPItem* ptp;
//чтение параметров TP
Log.Print(" TP: ");
if(!Stx.GetNumber(&x))
{
Log.Print("T=???");
return 0;
}
Log.Print("T=%d ", x);
if(!Stx.GetNumber(&y))
{
Log.Print("P=???");
return 0;
}
Log.Print("P=%d\n", y);
//проверка существования ID'а T
for(i = 0; i < T.GetCount(); ++i)
{
pt = (TItem*)T.GetData();
if(pt->ID == x)
{
i = -1;
break;
}
T.GoNext();
}
if(i > -1)
{
Log.Print(" Нет элемента T с таким ID\n");
return 0;
}
//вставка нового TP в список
ptp = new TPItem;
if(!ptp)
{
Log.Print(" Не хватает памяти\n");
return 0;
}
TP.Add();
TP.SetData((void*)ptp);
//задание параметров TP
ptp->T = pt;
ptp->P = y;
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CNet::SetupS(void)
{
int i, j;
SItem* ps;
STItem* pst;
TSItem* pts;
Log.Print(" Настройка списка связей для элементов S...\n");
//пройти по всем элементам S
for(i = 0; i < S.GetCount(); ++i)
{
ps = (SItem*)S.GetData();
//пройти по всем элементам ST
for(j = 0; j < ST.GetCount(); ++j)
{
pst = (STItem*)ST.GetData();
if(pst->S == ps)
{
//добавить pst в список выходящих связей
ps->ST.Add();
ps->ST.SetData((void*)pst);
}
ST.GoNext();
}
//пройти по всем элементам TS
for(j = 0; j < TS.GetCount(); ++j)
{
pts = (TSItem*)TS.GetData();
if(pts->S == ps)
{
//добавить pts в список входящих связей
ps->TS.Add();
ps->TS.SetData((void*)pts);
}
TS.GoNext();
}
S.GoNext();
}
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CNet::SetupT(void)
{
int i, j;
TItem* pt;
STItem* pst;
TSItem* pts;
Log.Print(" Настройка списка связей для элементов T...\n");
//пройти по всем элементам T
for(i = 0; i < T.GetCount(); ++i)
{
pt = (TItem*)T.GetData();
//пройти по всем элементам ST
for(j = 0; j < ST.GetCount(); ++j)
{
pst = (STItem*)ST.GetData();
if(pst->T == pt)
{
//добавить pst в список входящих связей
pt->ST.Add();
pt->ST.SetData((void*)pst);
}
ST.GoNext();
}
//пройти по всем элементам TS
for(j = 0; j < TS.GetCount(); ++j)
{
pts = (TSItem*)TS.GetData();
if(pts->T == pt)
{
//добавить pts в список выходящих связей
pt->TS.Add();
pt->TS.SetData((void*)pts);
}
TS.GoNext();
}
T.GoNext();
}
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CNet::SaveEC(char* fn)
{
int i;
ECItem* pec;
CLogFile Out;
Log.Print("Сохранение календаря событий в файле %s...\n", fn);
Out.Setup(fn);
Out.Reset();
Out.Print("Tid\tSTm\tETm\n");
Out.Print("------- ------- -------\n");
EC.GoBegin();
for(i = 0; i < EC.GetCount(); ++i)
{
pec = (ECItem*)EC.GetData();
Out.Print("%d\t%d\t%d\n", pec->T->ID, pec->P1, pec->P2);
EC.GoNext();
}
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CNet::LoadFromFile(char* fn)
{
char str[20];
Log.Print("Загрузка сети из файла %s...\n", fn);
if(!Stx.Open(fn))
{
Log.Print(" Не удалось открыть файл\n");
return 0;
}
//цикл чтения файла
Log.Print(" Протокол чтения файла:\n");
while(1)
{
if(!Stx.GetWord(str))
break;
//найдено описание S
if(!strcmp(str, "S"))
{
if(!LoadS())
return 0;
continue;
}
//найдено описание T
if(!strcmp(str, "T"))
{
if(!LoadT())
return 0;
continue;
}
//найдено описание ST
if(!strcmp(str, "ST"))
{
if(!LoadST())
return 0;
continue;
}
//найдено описание TS
if(!strcmp(str, "TS"))
{
if(!LoadTS())
return 0;
continue;
}
//найдено описание SP
if(!strcmp(str, "SP"))
{
if(!LoadSP())
return 0;
continue;
}
//найдено описание TP
if(!strcmp(str, "TP"))
{
if(!LoadTP())
return 0;
continue;
}
//найдено незнакомое слово
Log.Print(" Незнакомая команда: %s\n", str);
return 0;
}
//настроить списки связей для S и T
if(!SetupS())
return 0;
if(!SetupT())
return 0;
Log.Print(" Загрузка сети успешно завершена\n");
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void CNet::Clear(void)
{
Log.Print("Очистка сети...\n");
S.Free();
T.Free();
ST.Free();
TS.Free();
SP.Free();
TP.Free();
EC.Free();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CNet::Prepare(void)
{
int i;
TPItem* ptp;
ECItem* pec;
Log.Print(" Подготовка календаря событий...\n");
//проход по всем TP
for(i = 0; i < TP.GetCount(); ++i)
{
pec = new ECItem;
if(!pec)
{
Log.Print(" Не хватает памяти\n");
return 0;
}
ptp = (TPItem*)TP.GetData();
pec->P1 = -1;
pec->P2 = ptp->P;
pec->T = ptp->T;
pec->T->A = true;
EC.Add();
EC.SetData((void*)pec);
Log.Print(" EC: T=%d P1=%d P2=%d\n", pec->T->ID, pec->P1, pec->P2);
TP.GoNext();
}
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CNet::Finish(void)
{
int i, j;
ECItem* pec;
TSItem* pts;
//поиск завершающихся T в EC
for(i = 0; i < EC.GetCount(); ++i)
{
pec = (ECItem*)EC.GetData();
if(pec->P2 == Time)
{
Log.Print(" Time=%-5d T%d завершен: ", Time, pec->T->ID);
pec->T->A = false;
//проход по всем выходящим связям pec->T
for(j = 0; j < pec->T->TS.GetCount(); ++j)
{
pts = (TSItem*)pec->T->TS.GetData();
pts->S->M += pts->N;
Log.Print("S%d=%d ", pts->S->ID, pts->S->M);
pec->T->TS.GoNext();
}
Log.Print("\n");
}
EC.GoNext();
}
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CNet::External(void)
{
int i;
SPItem* psp;
//поиск внешних воздействий
for(i = 0; i < SP.GetCount(); ++i)
{
psp = (SPItem*)SP.GetData();
if(psp->P == Time)
{
psp->S->M += psp->M;
Log.Print(" Time=%-5d S%d=%d\n", Time, psp->S->ID, psp->S->M);
}
SP.GoNext();
}
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CNet::Start(void)
{
int i, j;
TItem* pt;
STItem* pst;
ECItem* pec;
bool flag;
//проход по всем T
for(i = 0; i < T.GetCount(); ++i)
{
pt = (TItem*)T.GetData();
if(pt->A)
{
T.GoNext();
continue;
}
//проверка достаточности меток
flag = true;
for(j = 0; j < pt->ST.GetCount(); ++j)
{
pst = (STItem*)pt->ST.GetData();
if(pst->S->M < pst->N)
{
flag = false;
break;
}
pt->ST.GoNext();
}
//активизация перехода
if(flag)
{
Log.Print(" Time=%-5d T%d активен: ", Time, pt->ID);
pt->A = true;
//забрать метки из S
for(j = 0; j < pt->ST.GetCount(); ++j)
{
pst = (STItem*)pt->ST.GetData();
pst->S->M -= pst->N;
Log.Print("S%d=%d ", pst->S->ID, pst->S->M);
pt->ST.GoNext();
}
Log.Print("\n");
//добавить запись в EC
pec = new ECItem;
if(!pec)
{
Log.Print(" Не хватает памяти\n");
return 0;
}
pec->P1 = Time;
pec->P2 = Time + pt->D;
pec->T = pt;
EC.Add();
EC.SetData((void*)pec);
}
T.GoNext();
}
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int CNet::Run(void)
{
Log.Print("Работа сети...\n");
if(!Prepare())
return 0;
Time = 0;
S.GoBegin();
T.GoBegin();
ST.GoBegin();
TS.GoBegin();
SP.GoBegin();
TP.GoBegin();
while(Time < 100) //условие окончания работы сети ???
{
if(!Finish())
return 0;
if(!External())
return 0;
if(!Start())
return 0;
++Time;
}
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
input.txt
;---------------------------------------
;S id
;------ -------
S 1
S 2
S 3
S 4
;---------------------------------------
;T id d
;------ ------- -------
T 1 10
T 2 10
;---------------------------------------
;ST sid tid m
;------ ------- ------- -------
ST 1 1 1
ST 2 1 2
ST 3 2 2
;---------------------------------------
;TS tid sid m
;------ ------- ------- -------
TS 1 1 1
TS 1 3 1
TS 2 3 1
TS 2 4 1
;---------------------------------------
;SP sid p m
;------ ------- ------- -------
SP 1 0 1
SP 2 0 4
;---------------------------------------
;TP tid p
;------ ------- -------
output.txt
Tid STm ETm
------- ------- -------
1 0 10
1 10 20