Как стать автором
Обновить

Держись, Маша! Ты, ведь, наша! Продолжение разбора книги «Цифровая схемотехника и архитектура компьютера»

Уровень сложностиСложный
Время на прочтение21 мин
Количество просмотров12K
Всего голосов 8: ↑7 и ↓1+8
Комментарии30

Комментарии 30

Статья не плохая. Но считаю, что Вы зря принижаете программистов. Это просто профессия с очень обобщённым названием. Думаю, что многие программисты разбираться в схемотехнике. И писать: "используя свой, программистский инструментарий - всякие там корутины, потоки и весь сопутствующий этому террариум. Убедитесь в его полном бессилии...". Это немного не корректно.

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

Я не принижаю, а стараюсь говорить открытым текстом. Пусть жестковато, но мягко уже сказано было и не раз. Может, хватит "политесы разводить"? ;)

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

А будет ли реализован истинная параллельность - это не вопрос к программистам, это вопрос аппаратуры - иногда будет, иногда нет, но учитывать такую возможность мы обязаны.

Это прежде всего вопрос к программистам и только к ним, т.к. в их силах создать некую виртуальную машину в которой будет "истинная параллельность". Но это будут просто слова, если "истинная параллельность" не будет означать наличие паралдлеьной модели вычислений. Вот что главное - модель вычислений. А как она будет реализована аппаратно - дело сто двадцать пятое. Программисту об этом даже знать не нужно по большому счету ;)

Истинная паралельнось существует вполне реально, а не виртуально, и называется GPU. Хотя возможностей для синхронизации там конечно маловато.

Истинная параллельность нас окружает. Окружающий нас мир полон этой параллельности. Но нужно представлять, что функционирует этот мир по определенным законам. Чтобы его "обсчитать" нужна модель этого мира и она должна быть параллельной. Предположим Вы создали такую модель. Как понять, что она моделирует окружающий мир. Только экспериментально. Берем какую-то реальную вещь, потом создаем ее технический аналог по канонам Вашей модели и сравниваем их по результатам работы. Лучше реальную модель и технический аналог поместить в закрытые комнаты и по внешним признакам пытаться угадать где какая... Помните тест Тьюринга на способность машины мыслить?

Только здесь ситуация будет попроще. Например. Совсем простой. RS-триггер. Реальный состоит из двух элементов - два параллельных (истинных!) процесса. Берем Ваш GPU. Берем два потока, два ядра и что там еще... истинно параллельное ;) Создаем две модели элемента, связываем их по схеме триггера. Берем два "стаканчика". Под один - реальный триггер, под другой - Вашу модель. Перемешиваем. Да, из стаканчиков выодим контакты - два входа и два выхода RS-триггера. Ну вот - перемешали, премешали, запутали, короче... К входам цепляем кнопки, к выходам лампочки и, чтобы не было вопросов совсем, - осциллограф двухлучевой (лучше четыре) Давим на кнопки, смотрим на выходы - гадаем, чешем репу ;). Где реальный триггер? Сможем угадать, модель ни куда не годится. Не сможем - есть такая модель параллельного мира! Наконец-то мы ее создали, наконец-то создали модель реального мира! Вот, как-то так в первом приближении на примере RS-триггера. Создаем, конечно, еще другие модели и повторяем гадания. Находим реальный объект, который "колет" нашу модель - смотрим в чем дело, корректируем нашу модель.

Вот так "на пальцах" должен протекать научный процесс нахождения формальной модели окружающего нас параллельного (!) по своей сути реального мира. А Вы - "истинный GPU"... Это еще надо доказать, что он "истинный" Как? Я описал...

PS

Вопрос "на засыпку": В реальном мире есть мгновенные вычисления?

И, вообще, есть мгновенные вычисления? :)

Скорость вычислений ограничены теорией относительности и скоростью света в частности. Но в программировании во многих случаях абстракция мгновенных вычислений допустима в том смысле, что она не влияет на результат. То ли дело схемотехника - неправильно развёл дорожки и вот она уже не работает просто потому, что одна дорожка оказалось короче другой.

ключевое слово - допустима. Пример.

у = !(x1&&x2);

Допустимо? Да в полный рост.. Это модель мгновенного элемента И-НЕ (пример - см. логические элементы в SymInTech).

Смотрим на мгновенный триггер:

Q = !(R&&NQ);

NQ = !(S&&Q);

Допустимо? Почему бы и нет. Компилятор с его автоматами пропустит на ура. Но только все это лажа, т.к. мгновенных вычислений в природе нет. Ну, совсем. И проявится это в резултатах работы такого "триггера".

На все нужно время. На все! Даже на выполнение отдельной команды на уровне ассемблера.

Математики пишут у=а(х); Нормально? Да, в чем вопрос - нормально! Но на самом деле нормально было бы: y(t+1) = f(x(t)); Да, сожнее, да, необычно, но, черт возьми (прошу прощения), только так правильно!

Статья интересная, плюс, но содержание спорное от начала до конца. И первым делом - ваш код никуда не годится и хорошо показывает ваш уровень как программиста.

Если рассматривать эл. схемы против типичного программирования, то самые главные различия это:

1) в электрических цепях скорость передачи данных ограничена, и это нужно учитывать;

2) даже в схемах с чисто цифровой логикой присутствуют аналоговые эффекты, и это нужно учитывать;

3) программы на электрических схемах строятся по Data Flow концепции, а в типичных языках программировании - Control Flow. Однако никто не мешает на том же с++ написать набор абстракций для Data Flow - в цифровой обработке сигналов это норма.

4) ну и набор инструментов в программировании практически не ограничен. Сделать там 3-значную логику или на кватернионах - плёвое дело. В отличие от схемотехники.

Выяснять принадлежность получившегося КА к Муру, Мили или ещё кому-то - совершенно бессмысленное занятие. Это вопрос чтобы валить студентов на экзамене, а не писать надёжные и работающие программы.

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

Алаверды. Комментарий интересный, но тоже спорный от начала до конца. Можно, конечно, по каждому пункту, но лучше потихоньку. Начнем с главного - "плевка" в самый центр моей "программистской души" :) Вы как-то быстро оценили мой уровень, опустив его сразу ниже некуда (: Возможно Вы и правы, но ...

Что Вас конкретно не устроило в моем коде? Мнение профессионала всегда интересно. Я тут порылся и отыскал две любимые книжки на момент освоения С++. Времени, когда я создавал одновременно код ядра ВКПа (ВКП-ой оно стало позже). Итак, две книжки: 1) Ричард Вайнер, Люис Пинсон С++ изнутри, Киев , НПИФ "ДиаСофт", 1993 2)Стефан Дьюхарст, Кэти Старк. Программирование на С++, Киев , НПИФ "ДиаСофт", 1993.  Вот к чему я тогда прикипел... А, ведь, уже 30-ть лет прошло! Жуть! Был это С++ версии 2.0 и, кажется, Borland C++. И вот с тех пор все это работает. Сейчас С++ дорос, кажется, 20.0. По ходу я переносил код в Visual Studio. Дошел до версии 2010. Плюнул - перешел на Qt. Сейчас это версия 5.14 максимум. Все переносилось "по щелчку" Версии С++ я не контролировал в процессе переноса. Проблемы были только с графикой и диалогами. Но это нормально, т.к. разные библиотеки. Но зачем ломать здание (автоматы), которое столько лет стоит. Да и построено, вроде, по канонам С++. Так, что не так, что сразу убивает во мне программиста? Сгораю от любопытства ;)

Пожалуйста, не нужно мой комментарий воспринимать как "плевок". Любой код характеризует написавшего его программиста, и если он вдруг не устроил анонима из интернета - ещё не повод его в себе хоронить.

Хороший код - это не тот код, который хорошо работает. Это код, смысл и логика которого понятна даже без комментариев, а также позволяет масштабировать в очевидных направлениях. Ваш же код излишне переусложнён, необходимость использования строковых значений неочевидно, названия методов ни о чём не говорят, в названиях используются префиксы, засоряющих внимание.

мой вариант на c# навскидку
public class TrafficLight
{
	public enum Status
	{
		Red,
		Yellow,
		Green
	}

	private enum InternalStatus
	{
		RedYellow,
		YellowGreen,
		GreenYellow,
		YellowRed
	}

	public class EventArgs
	{
		public Status status;
		public EventArgs(Status status)
		{
			this.status = status;
		}
	}
	public delegate void TrafficLightEventHandler(object sender, EventArgs e);
	public event TrafficLightEventHandler StatusChanged;

	private System.Windows.Forms.Timer timer;
	private InternalStatus status;
	private int RedSeconds, YellowSeconds, GreenSeconds, SecondCounter;

	public TrafficLight(int RedSeconds = 2, int YellowSeconds = 1, int GreenSeconds = 3)
	{
		this.RedSeconds = RedSeconds;
		this.YellowSeconds = YellowSeconds;
		this.GreenSeconds = GreenSeconds;
	
		timer = new System.Windows.Forms.Timer();
		timer.Interval = 1000;
		timer.Tick += Timer_Tick;
	}

	public void Start()
	{
        StatusChanged(this, new EventArgs(Status.Red));
		status = InternalStatus.RedYellow;
		SecondCounter = RedSeconds;
		timer.Enabled = true;
	}

	public void Stop()
	{
		timer.Enabled = false;
	}

	private void Timer_Tick(object sender, System.EventArgs e)
	{
		SecondCounter--;
		if (SecondCounter > 0) return;
		switch (status)
		{
			case InternalStatus.RedYellow:
				status = InternalStatus.YellowGreen;
				SecondCounter = YellowSeconds;
				StatusChanged(this, new EventArgs(Status.Yellow));
				break;
			case InternalStatus.YellowGreen:
				status = InternalStatus.GreenYellow;
				SecondCounter = GreenSeconds;
				StatusChanged(this, new EventArgs(Status.Green));
				break;
			case InternalStatus.GreenYellow:
				status = InternalStatus.YellowRed;
				SecondCounter = YellowSeconds;
				StatusChanged(this, new EventArgs(Status.Yellow));
				break;
			case InternalStatus.YellowRed:
				status = InternalStatus.RedYellow;
				SecondCounter = RedSeconds;
				StatusChanged(this, new EventArgs(Status.Red));
				break;
		}
	}
}
и использование
TrafficLight trafficlight;

private void FormMain_Load(object sender, EventArgs e)
{
	trafficlight = new TrafficLight();
	trafficlight.StatusChanged += Trafficlight_StatusChanged;
	trafficlight.Start();
}

private void Trafficlight_StatusChanged(object sender, TrafficLight.EventArgs e)
{
	switch (e.status)
	{
		case TrafficLight.Status.Red: radioButtonRed.Checked = true; break;
		case TrafficLight.Status.Yellow: radioButtonYellow.Checked = true; break;
		case TrafficLight.Status.Green: radioButtonGreen.Checked = true; break;
	}
}

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

Я отвечу Вам, начав новую ветку. Чтобы всем было видно и задать вопросы именно по коду.

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

Вы тут спросили конкретные претензии к Вашему коду?

Вообще то я не настоящий сварщик, но навскидку - функции с именами y1,y2,y3...y8,y9,y12 и одинаковой сигнатурой, причем 3 последние в явном виде в коде не используются - это по нашему, по-бразильски.
Ну а если учесть, что все это для реализации автомата довольно таки примитивного светофора - то вообще нет слов, что же тогда будет в по-настоящему сложной схеме - y215?

В по-настоящему сложной схеме y215 не будет ни когда! У меня - абсолютно точно. Чтобы было понятно. В текущей реализации максимальные значения предикатов и действий - x32, y32. Кажется так. В больших индексах просто нужды не было.

Специфику программной реализации включают и модели на рис. 3, 4. Ей соответствует петля в начальном состоянии st, помеченная предикатом x12 и действием y12. Здесь предикат x12 выполняет проверку условий, обеспечивающих работу автомата, а отвечающее за инициализацию действие y12

Простите, а где на ваших рисунках (рис.3 и рис.4, как я понимаю, подразумевались) определения для предиката x12 и действия y12? Предикаты x1, x2 и x3 есть, а вот предиката x12 нет.

Вы задали правильный вопрос, но на него уже есть ответ. Цитата из статьи:

Специфику программной реализации включают и модели на рис. 3, 4. Ей соответствует петля в начальном состоянии st, помеченная предикатом x12 и действием y12. Здесь предикат x12 выполняет проверку условий, обеспечивающих работу автомата, а отвечающее за инициализацию действие y12 создает ссылки на входные/выходные переменные автомата, выполняет инициализацию значений и т.п. Автомат покинет начальное состояние st, когда будут выполнены все процедуры инициализации

Во-первых, вы думаете, что если еще раз продублировали использованную мной цитату, то это как-то исправляет содержимое ваших рисунков? Серьезно?

Как по мне, так если вы привели схему КА на которой есть x12 и y12, то добавьте в эту же схему и расшифровку x12, y12 наряду с другими расшифровками.

Во-вторых, реализацию этого x12 я в вашем C++ном говнокоде нашел:

int FTraficLights::x12() { return pVarTa != nullptr && pVarTb; }

Только вот сдается мне, что pVarTa!=nullptr не имеет отношения к логике самого КА с рисунков 3 и 4. Это часть вашей C++ной реализации. Получается, что если бы реализация делалась прямыми руками, а не дендро-фекальным методом, то никакой x12 для КА вообще бы не потребовался.

...Серьезно?

Вполне.

...Получается, что если бы реализация делалась прямыми руками, а не дендро-фекальным методом, то никакой x12 для КА вообще бы не потребовался.

Абсолютно в дырочку ;). Есть такие планы - инициализацию поручить ядру, но ... есть еще что обмыслить ;) Так что пока так. Могу лишь сказать, что когда я делаю автоматы, используя визуальные средства среды, то в такой явной инициализации нужды нет. Но на уровне С++ я такую возможность оставил. Вот теперь думаю... "а не дурак ли я" :)

Но пока без этого нельзя. А почему? Ну, например, в этом случае. Я загружаю автомат в среду (на уровне среды у меня нет кода типа и использование (см. пример Refridgerator)) и он становится видимым. Его надо настроить - указать имя переменной - датчика Ta. Я указываю это имя - автома подхватывает, устанавливая ссылку (см. метод FCreationOfLinksForVariables()) и начинает реализовать свою логику.

Я даже могу согласиться с названием - говнокод. Но только пока лучше не придумал. А пока работает - и пусть работает. Пусть "говнокод", но пока он меня не подводил. Пусть подванивает, но, зато, надежно ;)

Да. Может Вы что-то можете предложить более "розОвое" (в смысле запаха, конечно)

Вполне.

Ну афигеть. Я думал, что закос под наукообразие в ваших текстах -- это типа привычка из-за работы в академических кругах. Но, видимо, это что-то с психикой.

Вот теперь думаю... "а не дурак ли я" :)

Смайлик здесь лишний.

Пусть "говнокод", но пока он меня не подводил. Пусть подванивает, но, зато, надежно ;)

Т.е. вот этот список публичных членов, никак не проинициализированный в конструкторе -- это надежно?

class FTraficLights :
    public LFsaAppl
{
    enum {enNone, enRed, enYellow, enGreen};
public:
    ...
    CVar *pVarStrNameTa;// имя входного датчика Ta
    CVar *pVarStrNameTb;// имя входного датчика Tb
    CVar *pVarTypeOfFSM;// тип автомата
    CVar *pVarTa;		//
    CVar *pVarTb;		//
    CVar *pVarLa;		//
    CVar *pVarLb;		//

Да вас не хватило даже на то, чтобы для большей части из них хотя бы примитивное описание написать в комментарии.

А вот это описание переходов между состояниями:

void FTraficLights::MooreAction()
{
    string strState = FGetState();
    if (strState=="st")     { y1(); y5(); }		// none, none
    else if (strState=="S0"){ y4(); y6(); }		// La=green, Lb=red
    else if (strState=="S1"){ y3(); }           // La=yellow
    else if (strState=="S2"){ y2(); y8(); }		// La=red, Lb=green
    else if (strState=="S3"){ y7(); }           // Lb=yellow
}

Вы предлагаете эту внутреннюю кухню КА программисту вручную через лесенку if-ов описывать?

Может Вы что-то можете предложить более "розОвое" (в смысле запаха, конечно)

Я бы предложил посмотреть на вещи типа Boost.MSM, Boost.Statechart, SML, TinyFSM, но, боюсь, ваши знания C++ из начала 1990-х не позволят разобраться с этими проектами.

Если Вы увидели вместо науки "наукообразие" - уточните, конкретизируйте. Рассмотрим, разберемся, что к чему. Если же это просто "выплеск желчи", то тут что-то с психикой уже не у меня... Был бы рад ошибиться ;)

По поводу публичных членов. Правильное замечание, но и на него есть ответ. Если Вы пропустили, то обратите внимане на метод FCreationOfLinksForVariables(). В нем происходит основная инициализация. Те указатели, с которыми могут быть проблемы, дополнительно проверяет предикат x12 и если что-то не так (в данном случае не установлены некоторые указатели) то вызывается "до посинения" действие y12, которое может выполнять или специфические действия или вызывать уже упомянутый метод. Так что, как видите, все продумано и отработано практиткой. Да все это описано в статье...

По поводу "переходов". Ну, да - предлагаю именно так. Почему? Отвечаю. Таблица переходов и ядро были изначально заточены только на автоматы Мили. Их все же за глаза хватает. Но в процессе эксплуатации стало понятно, что и от автоматов Мура может быть польза. Ломать описание, лезть в ядро - еще тот геморрой. Делаем просто: создаем метод в котором читаем текущее состояние, к нему привязывает действия автомата. Так получаем автомат Мура (см. код). В ядре определяем место запуска этого метода. Ну, и соотвестввенно создаем признак вызова (чтобы он не занимал время в обычной ситуации - автоматов Мили). "Кухня" Вам показалась сложной? Ну, не знаю... если это не понятно? Мне кажется, что это простой до гениальности выход :)

По поводу ссылок. Спасибо. Даже возьму на заметку. Но... Мои "наукообразные" знания позволяют оценивать идею, заложенную в том или ином проекте. Если она коррелируется с моими идеями - разбираться имеет смысл. Даже не разбираться - просто проверить. (Не люблю копаться в чужом коде, предпочитаю создавать свой). Но если идею не озвучивают, то смысл ее "вытаскивать" за автора самому на поверхность - только тратать свое драгоценное время. Согласны? Я может и дурак, но не до такой же степени, что доверять любому, сказавшему слова "Конечный автомат". Или у Вас другое мнение на сей счет? Все же опыт меня убедил, что не все что называют термином "Конечный автомат" в большинстве случаев им является. Даже если по ходу упоминают "состояния". Ну, тертый я уже... в том числе и академическими кругами, где, к сожалению, наукообразия более чем достаточно... Одна SWICH-технология чего стоит (Извините, - не удержался "пнуть", но, к моему сожалению, есть за что. Уж ей-то я посвятил уйму времени)

Но, правда ведь, не мы такие - жизнь такая. Поэтому я Вас даже понимаю. :)

А чем цепочка if-else-if-else-... отличается от switch в лучшую сторону? В практиках хорошего программирования считается наоборот.

Если Вы увидели вместо науки "наукообразие" - уточните, конкретизируйте. Рассмотрим, разберемся, что к чему

Мне это зачем? Я увидел вашу статью, попытался прочитать, почерпнуть что-то. Не смог из-за стиля. Почитал комментарии, увидел человека с очень своеобразными взглядами на происходящее. Выводы сделал. Больше постараюсь не вляпываться.

Если Вы пропустили, то обратите внимане на метод (). В нем происходит основная инициализация. Те указатели, с которыми могут быть проблемы, дополнительно проверяет предикат x12 и если что-то не так

facepalm.jpg

Публичные члены означают большой и толстый болт, положенный на инкапсуляцию. Любой желающий может назначить pVarTa все что угодно и когда угодно.

Ваши бубличные члены не имеют никаких вменяемых значений до вызова FCreationOfLinksForVariables и если кто-то их случайно тронет до этого момента, то у вас будет UB.

В том числе и если предикат x12 будет как-то вызван до FCreationOfLinksForVariables.

Это, блин, такие азы программирования на C++, что прямо стыдно их в очередной раз проговаривать.

Ваши бубличные члены не имеют никаких вменяемых значений до вызова FCreationOfLinksForVariables и если кто-то их случайно тронет до этого момента, то у вас будет UB.

Вы правы. Может быть, конечно, все. Но только давайте будем поспокойнее...

От дурака сложно придумать защиту. Чтобы проблем не было есть определенные правила создания связей между объектами-автоматами. Тут все ок. Работает и уже давно. Проблема в другом - в подвисании ссылок, т.к. автомат может быть удален из среды и все ссылки на него будут недействительны. Вот это актуально.

Я посмотрел Ваши статьи. Точнее не сами статьи, а их тематику. Что-то подобное, как мне кажется, я там узрел. Вы, похоже, тоже работаете со множеством активных взаимодействующих объектов. Может быть, даже их число меняется в динамике. Как Вы решаете эти проблемы, если только решаете? Типа посылки сообщения объекту, с которым была связь, но потом в силу его удаления - пропала. Как объект узнает, что его "друг" исчез? В общем случае - это даже множество объектов.

Скажем так, образно, речь идет о том, чтобы выдернуть логический элемент из схемы в процессе ее работы. Можно, конечно, остановить работу сети и переписать связи при удалении того или иного объекта, но, может, есть более красивое решение?

Выводы сделал. Больше постараюсь не вляпываться.

Это нормально. Это Ваше решение. Не хотите - навязывать что-то не буду. Действительно, кому-то и А.А.Шалыто - это норм. Я свое слово сказал, а Ваше дело или его услышать или проигнорировать.

Вы, похоже, тоже работаете со множеством активных взаимодействующих объектов. Может быть, даже их число меняется в динамике. Как Вы решаете эти проблемы, если только решаете? Типа посылки сообщения объекту, с которым была связь, но потом в силу его удаления - пропала. Как объект узнает, что его "друг" исчез?

Такие проблемы решаются через ООП и грамотной архитектурой классов.

1) объекты находятся не в вакууме, а внутри контейнера. Когда объект удаляется, у него из деструктора (базового класса) вызывается метод контейнера, который разруливает все связи, вхождения в коллекции и прочее.

2) для объекта необходимо предусмотреть значения по умолчанию на случай, когда источник данных ещё не подключен или уже отключен. А не проверять ссылки на nullptr!

Итак, код. На С++. На совершенно ином уровне абстракции ;)

Автомат Мили
class FTraficLightsMealy: public FTraficLights
{
public:
    bool FCreationOfLinksForVariables();
    FTraficLightsMealy(string strNam);
};

static LArc TBL_FTraficLightsMealy[] = {
    LArc("st",		"st","^x12","y12"),			//
    LArc("st",		"S00","x12x3","y4y6y10"),	// enGreen, enRed, FSetMoore(false);
// Mealy`s automaton
    LArc("S00",		"S10","^x1","y3"),			// enYellow, -
    LArc("S10",		"S20","--",	"y2y8"),		// enRed,    enGreen
    LArc("S20",		"S30","^x2","y7"),			// -,        enYellow
    LArc("S30",		"S00","--",	"y4y6"),		// enGreen,  enRed
    LArc()
};

FTraficLightsMealy::FTraficLightsMealy(string strNam):
    FTraficLights(strNam, TBL_FTraficLightsMealy)
{

}

bool FTraficLightsMealy::FCreationOfLinksForVariables() {
    FTraficLights::FCreationOfLinksForVariables();
    pVarTypeOfFSM->SetDataSrc(this, 1);
    return true;
}

Автомат Мура
class FTraficLightsMoore: public FTraficLights
{
public:
    void MooreAction();
    bool FCreationOfLinksForVariables();
    FTraficLightsMoore(string strNam);
};

static LArc TBL_FTraficLightsMoore[] = {
    LArc("st",		"st","^x12","y12"),			//
    LArc("st",		"S0","x12^x3","y9"),		// FSetMoore(true)
// Moore's automaton
    LArc("S0",		"S1","^x1",	"--"),			//
    LArc("S1",		"S2","--",	"--"),			//
    LArc("S2",		"S3","^x2",	"--"),			//
    LArc("S3",		"S0","--",	"--"),			//
    LArc()
};

FTraficLightsMoore::FTraficLightsMoore(string strNam):
    FTraficLights(strNam, TBL_FTraficLightsMoore)
{

}

bool FTraficLightsMoore::FCreationOfLinksForVariables() {
    FTraficLights::FCreationOfLinksForVariables();
    pVarTypeOfFSM->SetDataSrc(this, 0.0);
    return true;
}

void FTraficLightsMoore::MooreAction()
{
    string strState = FGetState();
    if (strState=="st")     { y1(); y5(); }		// none, none
    else if (strState=="S0"){ y4(); y6(); }		// La=green, Lb=red
    else if (strState=="S1"){ y3(); }           // La=yellow
    else if (strState=="S2"){ y2(); y8(); }		// La=red, Lb=green
    else if (strState=="S3"){ y7(); }           // Lb=yellow
}

Не проверял, но, думаю, работать будет (ведь, создано на базе работающего кода).

Признаюсь честно, я тащусь от возможностей С++. И вообще, у меня рука "тянется к кобуре" когда:

  1. Кто-то утверждает, что С (любой другой подставьте язык) лучше С++

  2. Кто-то говорит, что ООП - это типа отстой

  3. Когда называпют "СВИСТ-технологию" А.А.Шалыто автоматным программированием

    Вот, затрелил бы! За ... амбициозную тупость! Хотя, может быть, и не прав. Но ни чего с собой поделать не могу. :)

    Да, кстати, выше код на C# сделан по типу SWITCH-технологии.

    Извините, но процитирую себя:

    "... Это и есть автоматное программирование без изъятий, но здесь ... и близко нет SWITCH-технологии.  Подумайте, прочитайте в конце концов, если не читали, статью[4]. Не поняли - перечитайте ее еще раз, еще раз, может, даже еще раз, но включите наконец-то мозги... А то все switch, switch иногда case, if else... Это все и всегда будет про блок-схемы, а не про автоматы... "

    Делайте выводы...

Ссылаться на свои собственные статьи в качестве аргументации собственной правоты обычно считается недостойным учёных мужей. Конечно, не каждый switch реализует КА - зато наоборот, любой КА реализуется через switch вполне естественным образом. А если не нравится вам switch - ну ок, можно ту же самую логику реализовать через массивы с делегатами с доступом по индексу. Причём продвинутые с++ компиляторы с этим справляются самостоятельно уже давно.

Ссылаться на свои собственные статьи в качестве аргументации собственной правоты обычно считается недостойным учёных мужей. 

Ну, что тут Вам ответить. Я с Вами согласен. Но, к сожалению, я не знаю других мужей точно также трактующих автоматное програмирование. Поэтому, извиняйте, но ситуация такая, какая уж есть. Если знаете другого "ученого мужа" - поделитесь. Я мечтаю с таким познакомиться ;)

По поводу switch. Тут, как говорится, к гадалке не ходи: ни один современный компилятор не реализует автоматную модель (КА, если хотите). Все, что Вы перечислили, лишь имитирует автоматы, как комбинационная модель имитирует реальную схему. Улавливаете разницу?

Можно попробовать такую аналогию:

Комбинационная модель <-> продвинутый компилятор С++,

Последовательностная модель <-> реальная схема.

Комбинационная модель != последовательностная модель.

Мысль, идея понятны?

PS. Добавлю еще с некоторым (небольшим) огрублением):

Конечный автомат - модель отдельного объекта реального мира

Сеть взаимосвязанных синхронных конечных автоматов - модель реального мира

Если знаете другого "ученого мужа" - поделитесь

Совершенно случайно знаю одного. Профильное образование имеет (отдельно по электронике, отдельно по информатике), 35 лет практики, куча статей на хабре (ну вы понели, о ком речь).

ни один современный компилятор не реализует автоматную модель

Мой первый интерпретатор математических выражений как раз и был реализован на классическом КА.

Все, что Вы перечислили, лишь имитирует автоматы, как комбинационная модель имитирует реальную схему. Улавливаете разницу?

Конечно. Разница в том, что в реальности нет никаких конечных автоматов. Конечный автомат - это математическая абстракция, как и машина Тьюринга, как и нормальные алгорифмы Маркова, как и всякое прочее другое.

Мой первый интерпретатор математических выражений как раз и был реализован на классическом КА.

Есть один нюанс - в теории проектирования трансляторов фактически другие автомата.Они, ну, очень похожи (особенно на уровне модели абстрактного автомата), но - другие. Когда-то в поисках нужных автомтов я рылся и в них. Книжки Льюис, Зозенкрац Стирнз, Грис, и совсем уж классика - Ахо, Ульман до сих пор перед глазами на моей полке ;) Все это интересно, конечно, но быстро понял, что не то все это, и вернулся автоматам по Глушкову, к его формулировке дискретной кибернетики... Так что такое сравнение авматов - не проходит. Как говортся, "тепло", но не то.. В трансляторах фактически чистые функции отображения, в синтезе - они же, но с привязкой ко времени. А это нюанс. Там - фактически чистые алгоритмы, в синтезе - преобразователи информации (по Глушкову), т.е. процессы. Кратко, трансляторы - это очень интересно, но - не то.

Конечный автомат - это математическая абстракция, как и машина Тьюринга, как и нормальные алгорифмы Маркова, как и всякое прочее другое.

Вы правы, но не совсем ;) Конечный автомат - как дискретный преобразователь, является математической моделью реальных объектов. В них содержится и алгоритм и закон их работы в реальном времени. Тьюринг и все остальное - это модели алгоритмов без привязки ко времени. И в этом их проблемы. Для машин Тьюринга они вылезли в попытках создать многоголовочную машину, как модель параллельных вычислений. Как-то не пошло. Забросили... :( Но понятно почему. Не учли время... Далее. У реальных объектов есть еще инерционность в работе. Где у Тьюринга, Маркова и далее по списку - инерционность? Нет. От слова совсем.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории