nedoPC.org

Community of electronics hobbyists established in 2002

...
Atom Feed | View unanswered posts | View active topics It is currently 26 Jun 2017 21:57



Reply to topic  [ 161 posts ]  Go to page Previous  1 ... 6, 7, 8, 9, 10, 11  Next
а не замутить ли нам недосимулятр? 
Author Message
Doomed

Joined: 26 May 2003 09:57
Posts: 598
Reply with quote
Post 
А нельзя что-ли сначала рассчитать все выходы, и только потом в самом конце итерации переписать значения выходов на входы в соответствии с соединениями?
При этом можно даже монтажное И/ИЛИ учесть :)

_________________
Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/


14 Sep 2012 01:38
Profile WWW
Admin
User avatar

Joined: 09 Jan 2003 02:22
Posts: 15362
Location: New York
Reply with quote
Post 
b2m wrote:
А нельзя что-ли сначала рассчитать все выходы, и только потом в самом конце итерации переписать значения выходов на входы в соответствии с соединениями?
При этом можно даже монтажное И/ИЛИ учесть :)


Тогда у тебя задержка будет не на обратных связях, а вообще на каждом элементе...

P.S. Хотя наверное это более правдоподобно и элементы сортировать ненадо в соответствии с удалённостью от входов

_________________
:eugeek: https://twitter.com/Shaos1973


14 Sep 2012 02:01
Profile WWW
Senior

Joined: 07 Aug 2006 13:18
Posts: 186
Reply with quote
Post 
Shaos wrote:
По-моему ты черезчур усложняешь...
Мне показалось наоборот. Вплоть до того, что элементы каждого слоя можно выписать в отдельный массив и обходить каждый массив в произвольном порядке. [s]Или не в порядке, а параллельно, засунув в GPU[/s]

Shaos wrote:
Кстати в случае триггера оба элемента будут равноправны - и от входов они будут на одинаковом "расстоянии" - как быть в этом случае?

Мне казалось что поф... Но я взял таки ручку с бумажкой и вижу что не поф. Ну и как интересно будет правильным разрулить ситуацию? В случае триггера можно обойти эти И-НЕ два раза, каждый раз пересчитывая. В общей ситуации, надо думать, придётся детектить циклы и бегать по этим циклам, разглядывая переключения элементов. И бегать до тех пор, пока либо ситуация стабилизируется, то есть, пробежав круг, мы ничего не изменим. Либо до тех пор, пока не выясним, что состояние элементов меняется циклически (самовозбуждение?). Да, и если математически (читай теоретически) множество состояний группы элементов будет конечным множеством, то практически оно может оказаться достаточно большим, чтобы считать его бесконечностью. А это значит, что цикличность изменения состояния элементов мы можем и не узнать никогда. То есть бегать по кругу -- не вариант в общей ситуации.
Shaos wrote:
P.S. В случае использования координаты X триггер с двумя И-НЕ, расположенных друг на другом будет просто самовозбуждаться, превращаясь в генератор...
Я наблюдал, кстати, подобное в cedar. Если rs-триггер перевести в запрещённое состояние, то есть на оба входа сунуть ему 1, ему становится хорошо, и он самовозбуждается. Правда для этого надо чтобы там одновременно появились бы единички на входах. Если значения менять по-одному, то ничего не выходит.
Надо будет погонять его под отладкой. Вопрос каким образом cedar достигает подобного выходит достаточно интересным, тем более что период колебаний триггера у него неустойчивый. Странный период, он зависит от того, какой длины шаг симуляции по времени, и ещё от фазы луны. Причём бывает, что фаза луны меняется в процессе этих самых колебаний.

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


14 Sep 2012 03:22
Profile
Senior

Joined: 07 Aug 2006 13:18
Posts: 186
Reply with quote
Post 
bar wrote:
Shaos wrote:
По-моему ты черезчур усложняешь...
Мне показалось наоборот. Вплоть до того, что элементы каждого слоя можно выписать в отдельный массив и обходить каждый массив в произвольном порядке. [s]Или не в порядке, а параллельно, засунув в GPU[/s]

Добавлю.

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

Кстати замечу, что b2m-подход, будет выдавать несколько иные результаты нежели то, что мы обсуждали до сих пор. У него входной сигнал дойдёт до слоя i за i итераций. Если все выходы схемы расположены на одном и том же уровне, то надо думать, что в результате-то (если не забыть дать b2m-подходу несколько итераций на разогрев), в результате получится одно и то же. [add]Подумав ещё... Нихрена. Если как раз с тем триггером решить ситуацию таким образом, чтобы значения с выходов элементов текущего слоя не влияли бы, до тех пор пока мы не закончим с текущим слоем, чтобы вместо них использовались бы значения с предыдущей итерации, тогда да, а так нет[/add]
Но если выходы в разных слоях, что немало вероятно, то результаты будут различны. И рождается вопрос: какой вариант правильнее?


14 Sep 2012 03:48
Profile
Doomed

Joined: 26 May 2003 09:57
Posts: 598
Reply with quote
Post 
Правильнее учитывать время от изменения на входе логического элемента до изменения на выходе. В "моём" подходе оно будет усреднённым для всех логических элементов и равно времени одной итерации.

_________________
Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/


14 Sep 2012 05:45
Profile WWW
Senior

Joined: 07 Aug 2006 13:18
Posts: 186
Reply with quote
Post 
b2m wrote:
Правильнее учитывать время от изменения на входе логического элемента до изменения на выходе.
Угумс. Я тоже так теперь думаю. Без этого времени не удастся без грязных хаков решить проблему обратной связи в общем виде.


14 Sep 2012 07:30
Profile
Senior

Joined: 07 Aug 2006 13:18
Posts: 186
Reply with quote
Post 
Мастер по C++. А вот скажи мне, как бы так в C++ обойти отсутствие generic'ов? Вот есть у меня N классов. Все они производные от одного и того же класса. Даже скажу подробнее, чтобы было понятнее. Это геометрические примитивы. Типа точка, отрезок, прямая, окружность, и чёртегознает ещё мне в голову придёт добавить в этот список потом.
И хочу я расстояние между ними вычислять. В C++ есть перегрузка функций -- это почти то что мне надо, но выбор реализации функции в ней выбирается статически, что полностью обесценивает перегрузку и делает её совершенно бесполезной.

Как-то незаметно я привык к generic'ам из common lisp'а, к тому что это просто, и когда здесь писал перегруженные функции distance, подумал, что ежели потребуется в рантайме выбирать нужную функцию, то я как-нибудь выкручусь, ведь в C++ есть rtti. Ан не тут-то было.

Я поискал в гугле насчёт generic'ов и C++, но там вообще вынос мозга. Пишут что в C# есть generic'и, но там синтаксис как у темплитов, и это такой вынос мозга... Нашёл какую-то статейку, где вроде про дженерики в C++, но там хрен поймёшь: в C++ или в C#. Тоже синтаксис я тя пну и source кода не видно. Дальше я не вникал.

Более конкретно, вот есть у меня две переменные:
Code:
primitive *p1, *p2;
И хочется как-то избавится от необходимости в таком коде:
Code:
if(typeid(*p1) == typeid(point) && typeid(*p2) == typeid(point)) {
    return point_point_distance(p1, p2);
} else if(typeid(*p1) == typeid(point) && typeid(*p2) == typeid(line_segment)) {
    return point_segment_distance(p1, p2);
} else if...
Понятно тут можно оптимизировать и уйти от N*N if'ов, сделать N+N, а учитывая коммутативность ещё поделить количество if'ов примерно на 2. Но дело в том, что... по-моему всё равно уродство. Да и добавляя новый класс придётся лезть в эти if'ы, дописывать чего-то, причём так, чтобы не пропустить ни одного места, где можно пропустить. Можно конечно кодогенератор написать, но опять же, попахивает идиотизмом: специальный кодогенератор ради какой-то мелочи. Да и как этот кодогенератор можно научить выудить из заголовка список классов производных от primitive? Утонешь в регекспах.

Приходит в голову другой вариант -- напихать в каждый класс virtual методов, которые будут измерять расстояние от this до другого примитива. Это конечно позволит избавиться от большинства typeid'ов, а можно даже ото всех, но это как-то совсем черезжопу. Примерно так:
Code:
class point {
    virtual float distance(primitive *p) {
        return p->distance(this);
    }
    virtual float distance(point *p);
    virtual float distance(line_segment *ls);
};
class line_segment {
    virtual float distance(primitive *p) {
        return p->distance(this);
    }
    virtual float distance(point *p) {
        /* используем коммутативность: */
        return p->distance(this);
    }
    virtual float distance(line_segment *ls);
};
Если у нас N разных примитивов, то придётся N+1 виртуальную функцию засовывать в каждый класс.

Можно сделать двумерный массив указателей на те реализации перегруженной distance. Немного повозиться в рантайме с разруливанием коммутативности, или явно создать по перегруженной функции на каждую пару типов. Самый многообещающий вариант, но, блин, C++ ленив приделывать типам целочисленные идентификаторы, и придётся вместо двумерного массива делать двумерный map, или отдельно преобразовывать строковые идентификаторы типов в небольшие целые числа.

Вот на твой взгляд, о Мастер C++, какой из этих путей менее уродлив? Или лучше пойти C'шным путём? То есть завести целочисленное поле type в каждом классе, и потом свести реализацию generic_distance, к:
Code:
return generic_fn_table[p1->type][p2->type](p1, p2);
Чего-то мне кажется, что C'шный подход выйдет наиболее лаконичным и наименее сбивающим с толку читателя кода.


15 Sep 2012 01:00
Profile
Doomed

Joined: 26 May 2003 09:57
Posts: 598
Reply with quote
Post 
bar wrote:
Если у нас N разных примитивов, то придётся N+1 виртуальную функцию засовывать в каждый класс.

То есть всего у нас будет (не считая функций с параметром указателем на базовый класс) N*N функций, половина из которых будут использовать комутативный закон. Это то-же самое, что двумерный массив N*N указателей на процедуры. Здесь же ты избавишься от необходимости преобразовывать аргументы указатели к указателям на нужные пару классов.

Кроме того, все объекты можно привести к небольшому числу геометрических фигур: линия, треугольник, прямоугольник, овал, группа фигур. Т.е. параметрами будут указатели не на реальный объект, а на его геометрическую фигуру (которые можно реализовать как промежуточные базовые классы, и всю эту канитель реализовывать только в них).

_________________
Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/


15 Sep 2012 02:44
Profile WWW
Admin
User avatar

Joined: 09 Jan 2003 02:22
Posts: 15362
Location: New York
Reply with quote
Post 
Generics=Templates?

_________________
:eugeek: https://twitter.com/Shaos1973


15 Sep 2012 10:57
Profile WWW
Senior

Joined: 07 Aug 2006 13:18
Posts: 186
Reply with quote
Post 
Shaos wrote:
Generics=Templates?
Templates всю работу свою выполняют во время компиляции. Как я понимаю generics в понимании C# это ровно то же самое, но в рантайме. То есть подстановка конкретных типов выполняется во время выполнения.

В лисповском же понимании, от которого я собственно и шёл, если это понимание в терминах C++ выражать: generic -- это перегруженная функция, конкретная реализация которой выбирается не во время компиляции, а в рантайме.

То есть допустим если я напишу в C++:
Code:
class primitive {...};
class point : public primitive { ... };
class circle : public primitive { ... };

float distance(point *p1, point *p2) {
  ...
}
float distance(circle *c1, circle *c2) {
  ...
}
То вот такое не скомпиляется:
Code:
primitive *p1, *p2;
p1 = new point;
p2 = new point;
distance(p1, p2);
Потому что C++ во время компиляции видит что типы p1 и p2 -- это указатели на primitive, при этом нету distance перегруженной на (primitive*, primitive*), и C++ не найдёт какую именно функцию надо вызывать. А если бы и нашёл, то нашёл бы во время компиляции. Но ситуация такова, что на этапе компиляции неизвестно какие именно примитивы надо будет засовывать в distance во время выполнения. Ну, допустим, код:
Code:
vector<primitive*> path1, path2;
/* каким-то образом заполняем path1 и path2 _разными_ примитивами */
for(p1 = path.begin(); p1 != path.end(); p1 ++) {
    for(p2 = path.begin(); p2 != path.end(); p2 ++) {
        distance(p1, p2);
    }
}

[add] Добавлю насчёт перегрузки distance для (primitive*, primitive*). Такой перегрузки "по логике ситуации" быть не должно. Поскольку primitive -- абстрактный класс, то сосчитать расстояние от него до куда бы то ни было мы не можем. Такая реализация должна быть (по-логике) чем-то типа virtual функции объявленной с "= 0;" в конце.


15 Sep 2012 20:55
Profile
Admin
User avatar

Joined: 09 Jan 2003 02:22
Posts: 15362
Location: New York
Reply with quote
Post 
Вот Александреску в 11 главе писал как сделать то, что ты хочешь:

http://books.google.fr/books?id=aJ1av7U ... &q&f=false

P.S. Лучше (и понятнее) писать на сях, тегируя объекты - код будет сильно прозрачней...

_________________
:eugeek: https://twitter.com/Shaos1973


15 Sep 2012 22:05
Profile WWW
Senior

Joined: 07 Aug 2006 13:18
Posts: 186
Reply with quote
Post 
Shaos wrote:
Вот Александреску в 11 главе писал как сделать то, что ты хочешь:
=)
Его я так и не удосужился прочитать.
Shaos wrote:
P.S. Лучше (и понятнее) писать на сях, тегируя объекты - код будет сильно прозрачней...
Угу. Тем более что искать где спереть александреску лень, а сайт тот показывает лишь несколько страниц излияний александреску, объясняющего, что он собирается сделать. И когда он подходит к самому интересному: к способу как сделать то, что он собирается сделать, сайт отказывается показывать дальше. Типа своих три страницы бесплатных вы уже прочитали (если я правильно понял ту французскую надпись).


16 Sep 2012 00:40
Profile
Doomed

Joined: 26 May 2003 09:57
Posts: 598
Reply with quote
Post 
Shaos wrote:
Александреску в 11 главе писал как сделать

Вот этот его DoubleDispatch и есть черезжопу. Вышеописанная проблема как раз, на мой взгляд, элегантно решается виртуальными функциями (см. код, который bar обозвал как черезжопу).

_________________
Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/


16 Sep 2012 03:49
Profile WWW
Senior

Joined: 07 Aug 2006 13:18
Posts: 186
Reply with quote
Post 
b2m wrote:
Shaos wrote:
Александреску в 11 главе писал как сделать

Вот этот его DoubleDispatch и есть черезжопу. Вышеописанная проблема как раз, на мой взгляд, элегантно решается виртуальными функциями (см. код, который bar обозвал как черезжопу).
Тебе нравится тот код?

У меня руки так и тянутся написать там комментарий о том, несмотря на одинаковый внешний вид тел функций point::distance(primitive*) и line_segment::distance(primitive*) -- это совершенно разный код, потому что используемый в них указатель this имеет разный тип. А я такое желание неуёмное желание комментировать склонен рассматривать как признак того, что код неудачен. Может всё дело в том что я в C++ не гуру совсем. Может для C++ подобное нормально. Но и всё ж...


16 Sep 2012 04:28
Profile
Doomed

Joined: 26 May 2003 09:57
Posts: 598
Reply with quote
Post 
bar wrote:
Тебе нравится тот код?

Да, и я таким способом уже пользовался, когда делал интерпретатор пролога: используется при унификации двух произвольных объектов. Работает на ура, и кода не так уж много.

bar wrote:
несмотря на одинаковый внешний вид тел функций point::distance(primitive*) и line_segment::distance(primitive*) -- это совершенно разный код

Думал-думал как избавиться от этих функций - никак не придумал. Похоже, это неотъемлемая часть этого метода. А ещё, не нравилась необходимость объявлять все эти виртуальные и по большей части абстрактные distance(point*),distance(line_segment*),... в базовом классе primitive. То есть при добавлении нового примитива приходилось менять не только объявление базового класса, но и классы, с которыми "контачит" новый примитив. Именно поэтому я предлагал вынести эту функциональность в отдельный законченный набор базовых классов.

_________________
Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/


16 Sep 2012 06:06
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 161 posts ]  Go to page Previous  1 ... 6, 7, 8, 9, 10, 11  Next

Who is online

Users browsing this forum: No registered users and 2 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

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software.