|
nedoPC.orgElectronics hobbyists community established in 2002 |
|
а не замутить ли нам недосимулятр?
Author |
Message |
b2m
Devil
Joined: 26 May 2003 06:57 Posts: 859
|
А нельзя что-ли сначала рассчитать все выходы, и только потом в самом конце итерации переписать значения выходов на входы в соответствии с соединениями?
При этом можно даже монтажное И/ИЛИ учесть
_________________Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/
|
13 Sep 2012 22:38 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22428 Location: Silicon Valley
|
Тогда у тебя задержка будет не на обратных связях, а вообще на каждом элементе...
P.S. Хотя наверное это более правдоподобно и элементы сортировать ненадо в соответствии с удалённостью от входов
|
13 Sep 2012 23:01 |
|
|
bar
Senior
Joined: 07 Aug 2006 10:18 Posts: 185
|
Мне показалось наоборот. Вплоть до того, что элементы каждого слоя можно выписать в отдельный массив и обходить каждый массив в произвольном порядке. [s]Или не в порядке, а параллельно, засунув в GPU[/s] Мне казалось что поф... Но я взял таки ручку с бумажкой и вижу что не поф. Ну и как интересно будет правильным разрулить ситуацию? В случае триггера можно обойти эти И-НЕ два раза, каждый раз пересчитывая. В общей ситуации, надо думать, придётся детектить циклы и бегать по этим циклам, разглядывая переключения элементов. И бегать до тех пор, пока либо ситуация стабилизируется, то есть, пробежав круг, мы ничего не изменим. Либо до тех пор, пока не выясним, что состояние элементов меняется циклически (самовозбуждение?). Да, и если математически (читай теоретически) множество состояний группы элементов будет конечным множеством, то практически оно может оказаться достаточно большим, чтобы считать его бесконечностью. А это значит, что цикличность изменения состояния элементов мы можем и не узнать никогда. То есть бегать по кругу -- не вариант в общей ситуации. Я наблюдал, кстати, подобное в cedar. Если rs-триггер перевести в запрещённое состояние, то есть на оба входа сунуть ему 1, ему становится хорошо, и он самовозбуждается. Правда для этого надо чтобы там одновременно появились бы единички на входах. Если значения менять по-одному, то ничего не выходит.
Надо будет погонять его под отладкой. Вопрос каким образом cedar достигает подобного выходит достаточно интересным, тем более что период колебаний триггера у него неустойчивый. Странный период, он зависит от того, какой длины шаг симуляции по времени, и ещё от фазы луны. Причём бывает, что фаза луны меняется в процессе этих самых колебаний.
И если когда я увидел это в первый раз, я не особо парился на этот счёт, то теперь мне стало интересно. То ли cedar учитывает скорость распространения сигнала по схеме, то ли он гоняет по циклам примерно рандомное количество раз, обрывая эту беготню по кругу используя какие-то не очень подходящие критерии в качестве детекта зацикленности. Вариант со временем выглядит более правдоподобным -- а зачем оно ещё может быть надо?
|
14 Sep 2012 00:22 |
|
|
bar
Senior
Joined: 07 Aug 2006 10:18 Posts: 185
|
Добавлю.
Мне просто эта идея со слоями напомнила нейронные сети. И, кстати, в нейронных сетях тоже иногда используют обратные связи. И если мне память не изменяет, эти обратные связи закидывая сигнал в предыдущие слои там его и оставляют до следующей итерации. Ну, конечно же, нейронные сети они ничего не пытаются симулировать, они подражают работе биологической нервной системы, но не пытаются её повторить один-в-один. Но и всё же...
Кстати замечу, что b2m-подход, будет выдавать несколько иные результаты нежели то, что мы обсуждали до сих пор. У него входной сигнал дойдёт до слоя i за i итераций. Если все выходы схемы расположены на одном и том же уровне, то надо думать, что в результате-то (если не забыть дать b2m-подходу несколько итераций на разогрев), в результате получится одно и то же. [add]Подумав ещё... Нихрена. Если как раз с тем триггером решить ситуацию таким образом, чтобы значения с выходов элементов текущего слоя не влияли бы, до тех пор пока мы не закончим с текущим слоем, чтобы вместо них использовались бы значения с предыдущей итерации, тогда да, а так нет[/add]
Но если выходы в разных слоях, что немало вероятно, то результаты будут различны. И рождается вопрос: какой вариант правильнее?
|
14 Sep 2012 00:48 |
|
|
b2m
Devil
Joined: 26 May 2003 06:57 Posts: 859
|
Правильнее учитывать время от изменения на входе логического элемента до изменения на выходе. В "моём" подходе оно будет усреднённым для всех логических элементов и равно времени одной итерации.
_________________Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/
|
14 Sep 2012 02:45 |
|
|
bar
Senior
Joined: 07 Aug 2006 10:18 Posts: 185
|
Угумс. Я тоже так теперь думаю. Без этого времени не удастся без грязных хаков решить проблему обратной связи в общем виде.
|
14 Sep 2012 04:30 |
|
|
bar
Senior
Joined: 07 Aug 2006 10:18 Posts: 185
|
Мастер по C++. А вот скажи мне, как бы так в C++ обойти отсутствие generic'ов? Вот есть у меня N классов. Все они производные от одного и того же класса. Даже скажу подробнее, чтобы было понятнее. Это геометрические примитивы. Типа точка, отрезок, прямая, окружность, и чёртегознает ещё мне в голову придёт добавить в этот список потом.
И хочу я расстояние между ними вычислять. В C++ есть перегрузка функций -- это почти то что мне надо, но выбор реализации функции в ней выбирается статически, что полностью обесценивает перегрузку и делает её совершенно бесполезной.
Как-то незаметно я привык к generic'ам из common lisp'а, к тому что это просто, и когда здесь писал перегруженные функции distance, подумал, что ежели потребуется в рантайме выбирать нужную функцию, то я как-нибудь выкручусь, ведь в C++ есть rtti. Ан не тут-то было.
Я поискал в гугле насчёт generic'ов и C++, но там вообще вынос мозга. Пишут что в C# есть generic'и, но там синтаксис как у темплитов, и это такой вынос мозга... Нашёл какую-то статейку, где вроде про дженерики в C++, но там хрен поймёшь: в C++ или в C#. Тоже синтаксис я тя пну и source кода не видно. Дальше я не вникал.
Более конкретно, вот есть у меня две переменные: И хочется как-то избавится от необходимости в таком коде: Понятно тут можно оптимизировать и уйти от N*N if'ов, сделать N+N, а учитывая коммутативность ещё поделить количество if'ов примерно на 2. Но дело в том, что... по-моему всё равно уродство. Да и добавляя новый класс придётся лезть в эти if'ы, дописывать чего-то, причём так, чтобы не пропустить ни одного места, где можно пропустить. Можно конечно кодогенератор написать, но опять же, попахивает идиотизмом: специальный кодогенератор ради какой-то мелочи. Да и как этот кодогенератор можно научить выудить из заголовка список классов производных от primitive? Утонешь в регекспах. Приходит в голову другой вариант -- напихать в каждый класс virtual методов, которые будут измерять расстояние от this до другого примитива. Это конечно позволит избавиться от большинства typeid'ов, а можно даже ото всех, но это как-то совсем черезжопу. Примерно так: Если у нас N разных примитивов, то придётся N+1 виртуальную функцию засовывать в каждый класс. Можно сделать двумерный массив указателей на те реализации перегруженной distance. Немного повозиться в рантайме с разруливанием коммутативности, или явно создать по перегруженной функции на каждую пару типов. Самый многообещающий вариант, но, блин, C++ ленив приделывать типам целочисленные идентификаторы, и придётся вместо двумерного массива делать двумерный map, или отдельно преобразовывать строковые идентификаторы типов в небольшие целые числа. Вот на твой взгляд, о Мастер C++, какой из этих путей менее уродлив? Или лучше пойти C'шным путём? То есть завести целочисленное поле type в каждом классе, и потом свести реализацию generic_distance, к: Чего-то мне кажется, что C'шный подход выйдет наиболее лаконичным и наименее сбивающим с толку читателя кода.
|
14 Sep 2012 22:00 |
|
|
b2m
Devil
Joined: 26 May 2003 06:57 Posts: 859
|
То есть всего у нас будет (не считая функций с параметром указателем на базовый класс) N*N функций, половина из которых будут использовать комутативный закон. Это то-же самое, что двумерный массив N*N указателей на процедуры. Здесь же ты избавишься от необходимости преобразовывать аргументы указатели к указателям на нужные пару классов.
Кроме того, все объекты можно привести к небольшому числу геометрических фигур: линия, треугольник, прямоугольник, овал, группа фигур. Т.е. параметрами будут указатели не на реальный объект, а на его геометрическую фигуру (которые можно реализовать как промежуточные базовые классы, и всю эту канитель реализовывать только в них).
_________________Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/
|
14 Sep 2012 23:44 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22428 Location: Silicon Valley
|
Generics=Templates?
|
15 Sep 2012 07:57 |
|
|
bar
Senior
Joined: 07 Aug 2006 10:18 Posts: 185
|
Templates всю работу свою выполняют во время компиляции. Как я понимаю generics в понимании C# это ровно то же самое, но в рантайме. То есть подстановка конкретных типов выполняется во время выполнения.
В лисповском же понимании, от которого я собственно и шёл, если это понимание в терминах C++ выражать: generic -- это перегруженная функция, конкретная реализация которой выбирается не во время компиляции, а в рантайме.
То есть допустим если я напишу в C++: То вот такое не скомпиляется: Потому что C++ во время компиляции видит что типы p1 и p2 -- это указатели на primitive, при этом нету distance перегруженной на (primitive*, primitive*), и C++ не найдёт какую именно функцию надо вызывать. А если бы и нашёл, то нашёл бы во время компиляции. Но ситуация такова, что на этапе компиляции неизвестно какие именно примитивы надо будет засовывать в distance во время выполнения. Ну, допустим, код:
[add] Добавлю насчёт перегрузки distance для (primitive*, primitive*). Такой перегрузки "по логике ситуации" быть не должно. Поскольку primitive -- абстрактный класс, то сосчитать расстояние от него до куда бы то ни было мы не можем. Такая реализация должна быть (по-логике) чем-то типа virtual функции объявленной с "= 0;" в конце.
|
15 Sep 2012 17:55 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22428 Location: Silicon Valley
|
Вот Александреску в 11 главе писал как сделать то, что ты хочешь:
http://books.google.fr/books?id=aJ1av7U ... &q&f=false
P.S. Лучше (и понятнее) писать на сях, тегируя объекты - код будет сильно прозрачней...
|
15 Sep 2012 19:05 |
|
|
bar
Senior
Joined: 07 Aug 2006 10:18 Posts: 185
|
=) Его я так и не удосужился прочитать. Угу. Тем более что искать где спереть александреску лень, а сайт тот показывает лишь несколько страниц излияний александреску, объясняющего, что он собирается сделать. И когда он подходит к самому интересному: к способу как сделать то, что он собирается сделать, сайт отказывается показывать дальше. Типа своих три страницы бесплатных вы уже прочитали (если я правильно понял ту французскую надпись).
|
15 Sep 2012 21:40 |
|
|
b2m
Devil
Joined: 26 May 2003 06:57 Posts: 859
|
Вот этот его DoubleDispatch и есть черезжопу. Вышеописанная проблема как раз, на мой взгляд, элегантно решается виртуальными функциями (см. код, который bar обозвал как черезжопу).
_________________Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/
|
16 Sep 2012 00:49 |
|
|
bar
Senior
Joined: 07 Aug 2006 10:18 Posts: 185
|
Тебе нравится тот код?
У меня руки так и тянутся написать там комментарий о том, несмотря на одинаковый внешний вид тел функций point::distance(primitive*) и line_segment::distance(primitive*) -- это совершенно разный код, потому что используемый в них указатель this имеет разный тип. А я такое желание неуёмное желание комментировать склонен рассматривать как признак того, что код неудачен. Может всё дело в том что я в C++ не гуру совсем. Может для C++ подобное нормально. Но и всё ж...
|
16 Sep 2012 01:28 |
|
|
b2m
Devil
Joined: 26 May 2003 06:57 Posts: 859
|
Да, и я таким способом уже пользовался, когда делал интерпретатор пролога: используется при унификации двух произвольных объектов. Работает на ура, и кода не так уж много.
Думал-думал как избавиться от этих функций - никак не придумал. Похоже, это неотъемлемая часть этого метода. А ещё, не нравилась необходимость объявлять все эти виртуальные и по большей части абстрактные distance(point*),distance(line_segment*),... в базовом классе primitive. То есть при добавлении нового примитива приходилось менять не только объявление базового класса, но и классы, с которыми "контачит" новый примитив. Именно поэтому я предлагал вынести эту функциональность в отдельный законченный набор базовых классов.
_________________Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/
|
16 Sep 2012 03:06 |
|
|
Who is online |
Users browsing this forum: No registered users and 3 guests |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot post attachments in this forum
|
|