LINUX.ORG.RU

Хочу машину времени, или отладка серии преобразований графа?

 мосговой штурм


1

1

Есть некоторая сложная поверхность в 3D прострастве (с т.з. физики - волновой фронт). Поверхность составлена из треугольников, треугольником может быть до неск млн.

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

Эта шляпа задается как двусвязный граф. Есть три типа узлов - лучи, грани и треугольники. Треугольник ссылается на грани и лучи. Грани ссылаются на прилежащие к ним треугольники. Лучи не ссылаются никуда - им и так хорошо.

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

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

★★★★★

Если честно, то я не очень понимаю, чем тебе поможет отматывание назад, если сейчас ты только пост-фактум можешь определить наличие проблемы, т.е. если на n-ом преобразовании ты нашёл косяк и отмотал на n-1, где косяка ещё нет, то как ты его сможешь найти?

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

ya-betmen ★★★★★
()
Последнее исправление: ya-betmen (всего исправлений: 1)

У меня есть функция, отслеживающая связность данных, и иногда она говорит - опаньки...

«Опаньки» может возникать при аналитическом продолжении по разным путям многозначной функции (например, нечто вроде каустики волнового фронта).

некоторый участок фронта становится хитровыкрученным а потм уже гавкается.

Хитровыкрученный Риман не поможет? Но лучше поспрошать математиков.

quickquest ★★★★★
()
Ответ на: комментарий от quickquest

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

AIv ★★★★★
() автор топика
Ответ на: комментарий от ya-betmen

Ну вот с индентификатором мне идея как то ближе, но я только сейчас сообразил как этот индентификатор делать;-)

AIv ★★★★★
() автор топика

Мне бы хотелось откатиться назад

В Visual Studio такое есть. Даже работает, правда не знаю как оно себя ведет когда данных много.

ebantrop
()

Писать историю изменений в лог?

loz ★★★★★
()

читал только заголовок: используй язык с персистентными структурами данных, или просто построй их в своём ЯП и аналог unfoldr.

qnikst ★★★★★
()
Последнее исправление: qnikst (всего исправлений: 1)

Сишечка, или плюсики? В общем, не суть важно, важно что тебе надо создать структуру «граф», через которую обращаешься к объектам по их идентификаторам (и все ссылки на объекты также делаются через идентификаторы). При необходимости ты клонируешь эту структуру и получаешь срез на соответствующий момент времени. Типа

struct Ray {
    int id;
    double x0, x1, y0, y1;
};
struct Border {
    int id;
    double x0, y0, z0, x1, y1, z1;
}
struct Triangle {
    int id;
    int borders[];
}
struct Graph {
    struct Borders[]
    struct Triangle[];
    struct Rays[];
};
function GetTriangle(Graph * g, int id);
function GetBorder(Graph * g, int id);
function GetRay(Graph * g, int id);
Структура легко клонируется (указателей благо там нет), потом с клоном можешь работать как угодно - распечатать, посмотреть и т.п.

no-dashi ★★★★★
()
Ответ на: комментарий от no-dashi

Плюсы. У меня там просто голые пойнтеры;-(

Мыль неплоха, но не хотелось бы переписывать все целиком.

AIv ★★★★★
() автор топика
Ответ на: комментарий от AIv

Ну, тогда городи умное клонирование, что тут ещё сказать?

class Point {
    double x, y, z;
    Point * cloned;
    public Point * clone() {
       if (cloned==null) cloned = new Point(x,y,z);
       return cloned;
    }
    public void resetClone() { cloned = null; }
}

class Triangle {
    Point * a;
    Point * b;
    Point * c;
    Triangle * cloned;
    public Triangle * clone() {
       if (cloned==null) cloned = new Triangle(a->clone(),b->clone(),c->clone());
       return cloned;
    }
    public void resetClone() {
       cloned = null;
       a->resetClone();
       b->resetClone();
       c->resetClone();
    }
}
Склонировал, вызвал у «текущей» структуры resetClone(), поехал дальше. Клонированная структура при этом «отцеплена» от основной. При желании, можно даже сохранять в ней ссылку на «основную» структуру, или делать клона более сложной структуры, чтобы хранить там какие-то метаданные.

no-dashi ★★★★★
()
Ответ на: комментарий от no-dashi

Пожаклй проще разадвать UID-ы (просто счетчик) и следить при повторном запуске за проблемной структурой (выводить ее в лог какойн нить или рисовать).

AIv ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.