Циклы в программном обеспечении генеалогического дерева

1594

Я разработчик программного обеспечения для семейного древа (написано на C ++ и Qt). У меня не было проблем, пока один из моих клиентов не отправил мне сообщение об ошибке. Проблема в том, что у клиента есть двое детей со своей дочерью, и в результате он не может использовать мое программное обеспечение из-за ошибок.

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

Как я могу устранить эти ошибки, не удаляя все утверждения данных?

Partick Höse
источник
30
Если вы проследите свое семейное древо достаточно далеко назад, вы столкнетесь с этой проблемой гораздо чаще, чем хотелось бы. Отказ от представления дерева может быть болезненным, но в конечном итоге будет более правильным.
Томас
55
Вы не должны добавлять утверждения для невероятных вещей, только невозможных вещей. Циклы - это очевидные вещи, которые невозможны в графе генеалогического дерева ... никто не может быть его собственным предком с помощью любого метода. Эти другие утверждения являются просто поддельными и должны быть удалены.
pgod
44
Это не глупый вопрос в мире разведения домашних животных. Дочь к отцу, мать к сыну, сестра к брату, внуки к бабушке и дедушке - стандартная техника, и заводчики домашних животных тоже нуждаются в программном обеспечении генеалогического дерева. "Чистокровный" мой ¤% # &.
Калейссин
31
Женитьба на двоюродных братьях была очень распространена в викторианской Англии, особенно среди высших классов (это был отличный способ хранить деньги в семье). Чарльз Дарвин, например, женился на своей двоюродной сестре Эмме Веджвуд. Любое программное обеспечение семейного древа должно поддерживать подобные ситуации.
rtperson

Ответы:

727

Кажется, у вас (и / или вашей компании) есть фундаментальное недопонимание того, каким должно быть семейное древо.

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

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

У GEDCOM есть много проблем, таких как несовместимость с однополыми отношениями, инцест и т. Д., Которые в реальной жизни происходят чаще, чем вы думаете (особенно когда возвращаетесь ко времени 1700-1800).

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

Отсутствие проверок дает нам более «реальный мир», более простое и гибкое решение.

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

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

Берт Геталс
источник
32
Это выглядит как правильный подход, и его достаточно легко расширить, чтобы обнаружить более сложные проблемы. Вы можете разработать набор отношений «А случилось до В» между событиями. Например, что человек родился до каких-либо других событий, связанных с ним. Это ориентированный граф. Затем вы можете проверить, что график не содержит циклов. Смотрите этот вопрос на StackOverflow. Это должно быть хорошо, пока путешествие во времени не изобретено.
Пол Харрисон
41
@ Пол-Харрисон Если это так просто. В старых записях (даже новых) имеются несоответствия даты. Крещение перед рождением, множественные записи о рождении и т. Д. Итак, в определенной степени, по официальным данным, есть путешествия во времени. Мы допускаем эти противоречивые данные. Мы разрешаем пользователям указывать, что приложение должно рассматривать как «запись о рождении» в случае дубликатов. И мы укажем нарушенные сроки, если найдены.
Берт Гуталс
38
@ ben-voigt GEDCOM - это формат, созданный Церковью Иисуса Христа Святых последних дней. В спецификации четко указано, что брак (МАРР) должен заключаться между мужчиной и женщиной. Для однополых браков или инцестов следует использовать метку ASSO (ASSOCIATES), которая также используется для обозначения дружбы или соседства. Ясно, что однополые браки - это отношения второго сорта в рамках этой спецификации. Более нейтральная спецификация не требовала бы отношений между мужчиной и женщиной.
Берт Гуталс
1
@Bert Goethals: Вы путаете GEDCOM с некоторыми программами, которые не поддерживают однополые браки (PAF, Legacy). GEDCOM не исключает такие конструкции, как «0 @ F1 @ FAM / 1 HUSB @ I1 @ / 1 HUSB @ I2 @», и, таким образом, поддерживает однополые браки, если ваше программное обеспечение решит.
Пьер
1
@Pierre Вы можете обмануть систему действительно. Это прямо из документа 5.5.1: «MARR {MARRIAGE}: = законное, гражданское право или обычное событие создания семейной единицы мужчины и женщины как мужа и жены». ( homepages.rootsweb.ancestry.com/~pmcbride/gedcom/55gcappa.htm ) Как видите, здесь нет однополых браков.
Берт Гуталс,
563

Расслабьте свои утверждения.

Не изменяя правила, которые в большинстве случаев очень полезны для 99,9% ваших клиентов при обнаружении ошибок при вводе их данных.

Вместо этого измените его с ошибки «невозможно добавить связь» на предупреждение с «добавить все равно».

Бен Фойгт
источник
143
Когда вы сталкиваетесь с очень маловероятной ситуацией, то есть той, где пользователь обычно делает это только по ошибке, хорошей идеей будет показать ему предупреждение. Это хорошая обратная связь. Но затем позвольте пользователю идти вперед, если он действительно уверен, что хочет. Поэтому я думаю, что это хороший ответ, даже если он не разбирается в том, как это сделать.
Томасруттер
15
Хороший ответ! Мне просто интересно, как этот вид программного обеспечения справится с ситуацией «Я - мой дедушка» ( youtube.com/watch?v=eYlJH81dSiw )?
Заур Насибов
4
Это на самом деле не ответ, потому что я думаю, что проблема заключается в том, что вы пересекаете дерево? Тем не менее, это хорошее предложение.
Bdwakefield
3
@bdwakefield: Вопрос был: «Как я могу устранить эти ошибки, не удаляя все утверждения данных?» Я думаю, что я ответил на это.
Бен Фойгт
2
@Ben Это зависит от того, для чего предназначены утверждения. Если они предотвращают возникновение бесконечных циклов или фатальных ошибок, то вы фактически предлагаете убрать утверждения. Если они просто предупреждают пользователя о потенциальной ошибке, тогда ваш ответ - хороший.
rm999
224

Вот проблема с родословными: они не деревья. Это направленные ациклические графы или DAG. Если я правильно понимаю принципы биологии репродукции человека, циклов не будет.

Насколько я знаю, даже христиане принимают браки (и, следовательно, детей) между двоюродными братьями, что превратит семейное древо в семейный DAG.

Мораль этой истории такова: выбирайте правильные структуры данных.

exDM69
источник
7
Это потребовало бы дальнейшего ограничения каждого узла, имеющего 1 или 2 максимальных узла, указывающих на него для in vitro и полового размножения. Хотя, чтобы быть более правдоподобным в реальной жизни, вы можете допустить несколько пунктирных линий для неопределенного потомства на стороне отца (всегда ясно, кто такая мать, но только ДНК-тестирование может гарантировать, кто такой отец, и это редко делается даже сегодня), или даже для обоих это усыновление принимается во внимание.
Manixrock
7
@manixrock - так как этот вопрос касается редких случаев, я хотел бы заявить, что не всегда ясно, кто является матерью. усыновление, брошенные дети, суррогатные мамы и т. д. могут осложнить ситуацию.
Питер Рекор
9
Это не обязательно ациклично, не так ли? Человек-женит-бабушка.
Эд Роппл
13
Человек, женившийся на своей бабушке, не сделает себя своим дедушкой и не добавит цикл. Если у них есть дети, это будет регулярное ребро нециклического графа.
exDM69
11
Это на самом деле две ADG. Есть граф происхождения и граф правовых отношений. Обычно то же самое, но расходится больше, чем можно было ожидать.
JSacksteder
115

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

Это хитрый. Предполагая, что вы хотите сохранить структуру дерева, я предлагаю это:

Предположим так: Aесть дети со своей дочерью.

Aдобавляет себя в программу как Aи как B. Оказавшись в роли отца, давайте назовем это парнем.

Добавьте is_same_for_out()функцию, которая сообщает генерирующей выходные данные части вашей программы, что все ссылки, идущие Bвнутри, должны идти Aпри представлении данных.

Это сделает дополнительную работу для пользователя, но я думаю, что ИТ будет относительно легко внедрить и поддерживать.

Основываясь на этом, вы можете работать над синхронизацией кода Aи Bизбежать несоответствий.

Это решение, конечно, не идеально, но это первый подход.

Эдуард Тамм
источник
9
Вероятно, такие «прокси» узлы действительно являются подходящим решением. Однако я понятия не имею, как их можно вставить в пользовательский интерфейс, не оскорбляя пользователя. Я могу сказать вам, что написание программного обеспечения, которое работает с реальными людьми (особенно с вашими клиентами), нелегко.
Partick Höse
6
Это никогда не заканчивается - новый сын Б будет его собственным дядей. Я хотел бы рассмотреть полный возврат средств за программу!
Бо Перссон
3
@Will A: И затем понимает, что он также является его собственной матерью, и нанимает его младшего себя в агентство времени?
Нулевой сет
2
Дублирование (и синхронизация) данных в одной системе - плохая практика. Это указывает на то, что решение является субоптимальным и должно быть пересмотрено. Если необходимо создать дополнительные (дублирующие) узлы, укажите это как прокси и делегируйте данные для чтения и записи в исходный узел.
Берт Гуталс
84

Вы должны сосредоточиться на том, что действительно имеет значение для вашего программного обеспечения . Стоит ли потратить время на то, чтобы заставить его работать на ОДНОГО потребителя стоимость лицензии? Скорее всего нет.

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

christopheml
источник
3
Очень верно. Но также взвесить другие потенциальные проблемы с аналогичными проблемами, которые другие подняли.
Проф. Фалькен нарушил контракт с
2
Конечно. Причина заключается в следующем: если это редкий крайний случай в некритическом приложении, вам не нужно что-либо исправлять или реализовывать. Если это действительно вредит вашим пользователям, есть смысл работать над этим.
christopheml
10
Вероятно, у каждого есть случай инцеста где-то в его / ее родословной. Таким образом, вы столкнетесь с этим ударом, если кто-то (слишком) углубится в историю семьи.
datenwolf
1
Создание генеалогического дерева какой-то странной ситуации (королевская семья, Фрицль и т. Д.) Является допустимым использованием программного обеспечения.
Bulwersator
1
Программное обеспечение семейного древа, которое не позволяет жениться на двоюродных братьях, бесполезно. Почти все семьи имеют по крайней мере один случай этого. Вот почему я думаю, что оригинальный пример создан для эффекта.
Fuzzy76
79

Вы должны были установить семейство Atreides (современное, Dune или древнее, Oedipus Rex ) в качестве тестового примера. Вы не найдете ошибок, используя очищенные данные в качестве контрольного примера.

user779752
источник
2
К сожалению, слишком многие люди сначала думают о «хороших» данных, а не о крайних случаях, которые ломают их системы.
sjas
59

Это одна из причин, по которой языки типа «Go» не имеют утверждений. Они используются для обработки случаев, о которых вы, вероятно, даже не задумывались, слишком часто. Вы должны утверждать только невозможное, а не просто невероятное . Именно последнее делает утверждения плохой репутацией. Каждый раз, когда вы печатаете assert(, уходите на десять минут и действительно обдумайте это.

В вашем особенно тревожном случае вполне возможно и ужасно, что такое утверждение будет поддельным при редких, но возможных обстоятельствах. Следовательно, обработайте это в своем приложении, хотя бы для того, чтобы сказать: «Это программное обеспечение не было разработано для обработки сценария, который вы представили».

Утверждать, что твой пра-пра-прадед, будучи твоим отцом, невозможно, - разумная вещь.

Если бы я работал в тестирующей компании, которая была нанята для тестирования вашего программного обеспечения, конечно, я бы представил этот сценарий. Почему? Каждый несовершеннолетний, но умный «пользователь» будет делать то же самое и получать удовольствие от полученного «сообщения об ошибке».

Тим Пост
источник
5
Согласитесь с аргументом «когда использовать утверждения»; не понимаю, как это относится к «у некоторых языков есть утверждения, а у Go нет».
Phooji
2
@Red Hue - иногда компиляторы делают невозможное ... возможным. Некоторые версии gcc думают -10 == 10 в реализации abs ().
Тим Пост
2
@Red Hue: вся суть утверждений заключается в документировании и тестировании условий, которые всегда должны быть истинными (или ложными). Это помогает удержать вас (и других) от «исправления» вещей таким образом, чтобы возникали эти невозможные случаи, поскольку тогда они явно (а не незаметно) сломали бы приложение. Если есть веская причина для появления «невозможного» случая, значит, вы заявили слишком много.
Цао
1
@cHao @Tim Post Я просто пытаюсь понять, почему Go не имеет утверждений - это хорошо, так как большинство из вас согласны с тем, что утверждение важно иметь.
Арлен
5
Наличие утверждений (или кода, подобного утверждению) не имеет значения. Код на таких языках, как Go, может и будет делать предположения о структуре данных; он просто не может документировать и применять эти предположения с помощью утверждений. Итог: в приложении есть ошибка.
Томми МакГуайр
41

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

Шон
источник
37

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

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

Например, если вы посмотрите на 2 ^ n предков, которые есть у вас в поколении n, если бы не было перекрытия, то у вас было бы больше предков в 1000 году нашей эры, чем было бы живых людей. Итак, должно быть совпадение.

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

Найти истинные циклы в дереве можно несколькими способами. Неправильный способ состоит в том, чтобы пометить каждого предка от данного человека, и при прохождении, если человек, которому вы собираетесь перейти к следующему, уже отмечен, тогда обрежьте ссылку. Это разорвет потенциально точные отношения. Правильный способ сделать это - начать с каждого человека и пометить каждого предка путем к этому человеку. Если новый путь содержит текущий путь в качестве подпути, то это цикл, и его следует разорвать. Вы можете хранить пути как вектор <bool> (MFMF, MFFFMF и т. Д.), Что делает сравнение и хранение очень быстрым.

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

Также обратите внимание, что вам не нужно фактически разрывать ссылку, вы можете просто изменить ее с обычной ссылки на «слабую», за которой не следуют некоторые ваши алгоритмы. Вы также захотите позаботиться о выборе ссылки, которая будет отмечена как слабая; иногда вы можете выяснить, где цикл должен быть нарушен, посмотрев информацию о дате рождения, но часто вы не можете ничего выяснить, потому что отсутствует так много данных.

tfinniga
источник
Осторожнее с этими предположениями; один мужчина и одна женщина-родитель - это не данность, когда люди адаптируются, или лесбиянки, которые считают себя родителями, в ближайшем будущем они могут даже стать биологически родителями, по крайней мере, девочек. В этом отношении, если мы применяем куколку к людям, даже предположение «у человека есть два отличных родителя», отсутствует.
Agrajag
1
@Agrajag, да, поэтому я определил "биологически говоря" для обнаружения цикла. Даже в биологическом отношении существует множество возможных проблем, таких как суррогатные матери и искусственное оплодотворение. Если вы также разрешаете усыновление и другие небиологические методы определения родителей, то возможно иметь действительный истинный цикл в дереве - например, может быть, кто-то усыновляет своего прародителя, когда он стареет и больше не может заботиться о себе , Делать предположения о семейной жизни людей всегда сложно. Но при написании программного обеспечения вы должны сделать некоторые предположения ..
tfinniga
36

Еще один серьезный серьезный ответ на глупый вопрос:

Реальный ответ: используйте соответствующую структуру данных. Человеческая родословная не может быть полностью выражена с использованием чистого дерева без циклов. Вы должны использовать какой-то график. Кроме того, поговорите с антропологом, прежде чем идти дальше с этим, потому что во многих других местах подобные ошибки могут быть допущены при моделировании генеалогии, даже в самом простом случае «западно-патриархального моногамного брака».

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

Например: http://en.wikipedia.org/wiki/Cousin_marriage

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

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

clvrmnky
источник
9
Ваш комментарий заставил меня задуматься о многоженстве. Для генеалогического программного обеспечения, которое моделирует только половое размножение, может потребоваться имя, прикрепленное к сперме и яйцеклетке, но в более широких определениях структуры семьи нет.
Стив Калемкевич
Генеалогическое программное обеспечение часто позволяет использовать в модели более одного супруга. То, как вы отображаете модель в представлении, широко варьируется, даже в пределах одной программы, в зависимости от предоставленного «режима».
Тодд Хопкинсон
20

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

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

Будет ли
источник
13

Несколько ответов показали способы сохранить утверждения / инварианты, но это выглядит как неправильное использование утверждений / инвариантов. Утверждения должны гарантировать, что то, что должно быть правдой, является истинным, а инварианты должны гарантировать, что то, что не должно измениться, не изменяется.

Здесь вы утверждаете, что кровосмесительных отношений не существует. Ясно , что они делают существует, так что ваше утверждение является недействительным. Вы можете обойти это утверждение, но настоящая ошибка заключается в самом утверждении. Утверждение должно быть удалено.

kerkeslager
источник
8

Ваше генеалогическое древо должно использовать направленные отношения. Таким образом, у вас не будет цикла.

Патрик Корнелиссен
источник
5

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

Способ обработки этого в представлении без создания настраиваемого представления состоит в том, чтобы обрабатывать циклический родительский элемент как «призрачный» родительский элемент. Другими словами, когда человек является и отцом, и дедом для одного и того же человека, тогда узел дедушки отображается нормально, но узел отца отображается как «призрачный» узел, который имеет простую метку, например («см. Дед» ) и указывает на дедушку.

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

Тайлер Дурден
источник
4

Самое главное avoid creating a problem, поэтому я считаю, что вы должны использовать прямое отношение, чтобы избежать цикла.

Как сказал @markmywords, #include "fritzl.h".

Наконец я должен сказать recheck your data structure. Возможно, что-то там не так (возможно, двунаправленный связанный список решает вашу проблему).

Насер Хаджлоо
источник
4

Утверждения не выживают в реальности

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

Циклические семейные графы

Относительно семейных «деревьев» (на самом деле это полноразмерные графы, включая циклы), есть хороший анекдот:

Я женился на вдове, у которой была взрослая дочь. Мой отец, который часто посещал нас, влюбился в мою падчерицу и женился на ней. В результате мой отец стал моим сыном, а моя дочь стала моей матерью. Некоторое время спустя я подарил своей жене сына, который был братом моего отца, и моего дядю. У жены моего отца (которая также является моей дочерью и моей матерью) родился сын. В результате я получил брата и внука в одном лице. Моя жена теперь моя бабушка, потому что она мама моей мамы. Итак, я муж моей жены и одновременно внук моей жены. Другими словами, я мой собственный дедушка.

Все становится еще более странным, если принять во внимание суррогаты или «нечеткое отцовство».

Как с этим бороться

Определить циклы как выходящие за рамки

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

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

Разрешить ручные отношения

Вы можете позволить пользователю добавлять ручные отношения. Эти отношения не являются «первоклассными гражданами», то есть программное обеспечение принимает их как есть, не проверяет их и не обрабатывает их в основной модели данных.

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

Будьте осторожны с ручными отношениями. Существует соблазн сделать их полностью настраиваемыми и, следовательно, создать полностью настраиваемую модель данных. Это не будет работать: ваше программное обеспечение не будет масштабироваться, вы получите странные ошибки и, наконец, пользовательский интерфейс станет непригодным для использования. Этот анти-паттерн называется «мягким кодированием» , и «Ежедневный WTF» полон примеров для этого.

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

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

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

Используйте генератор тестовых данных для проверки необычных тестовых случаев. Есть быстрые библиотеки проверки на Haskell , Erlang или C . Для Java / Scala есть ScalaCheck и ньяя . Одной из проверочных идей будет симуляция случайной популяции, случайное скрещивание, затем сначала ваше программное обеспечение импортирует, а затем экспортирует результат. Ожидалось бы, что все соединения на выходе также находятся на входе и наоборот.

Случай, когда свойство остается неизменным, называется инвариантом. В этом случае инвариант - это набор «романтических отношений» между индивидами в моделируемой популяции. Постарайтесь найти как можно больше инвариантов и протестируйте их со случайно сгенерированными данными. Инварианты могут быть функциональными, например:

  • дядя остается дядей, даже когда вы добавляете больше "романтических отношений"
  • у каждого ребенка есть родитель
  • население с двумя поколениями имеет по крайней мере одного прародителя

Или они могут быть техническими:

  • Ваше программное обеспечение не будет зависать на графике до 10 миллиардов участников (независимо от того, сколько соединений)
  • Ваше программное обеспечение масштабируется с O (количество узлов) и O (количество ребер ^ 2)
  • Ваше программное обеспечение может сохранять и перезагружать каждый семейный граф до 10 миллиардов участников.

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

stefan.schwetschke
источник
3

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

Я бы сохранял данные в векторе с постоянным целым числом для каждого человека и сохранял бы родителей и детей в объектах person, где указанное int является индексом вектора. Это было бы довольно быстро, чтобы идти между поколениями (но медленно для таких вещей, как поиск по имени). Объекты будут в порядке, когда они были созданы.

ctype.h
источник
-3

Дублируйте отца (или используйте символическую ссылку / ссылку).

Например, если вы используете иерархическую базу данных:

$ #each person node has two nodes representing its parents.
$ mkdir Family
$ mkdir Family/Son
$ mkdir Family/Son/Daughter
$ mkdir Family/Son/Father
$ mkdir Family/Son/Daughter/Father
$ ln -s Family/Son/Daughter/Father Family/Son/Father
$ mkdir Family/Son/Daughter/Wife
$ tree Family
Family
└── Son
    ├── Daughter
       ├── Father
       └── Wife
    └── Father -> Family/Son/Daughter/Father

4 directories, 1 file
числовой
источник
3
Команда ln -sне работает таким образом; разрешение ссылки Family/Son/Fatherбудет искать Family/Son/Daughter/Fatherиз-под того места Family/Son, где находится ссылка, а не из того места, .где вы дали ln -sкоманду.
Musiphil
48
клонирование запрещено
Женевскими