Моделирование семейных отношений с использованием графа - PullRequest
0 голосов
/ 10 июня 2019

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

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

enter image description here

Вот так я и начал.

public class Person
{
    public string Name { get; set; }
    List<IEdge> Children { get; set; }
    IEdge Spouse { get; set; }
    IEdge Father { get; set; }
    IEdge Mother { get; set; }
}

public class Edge
{
    Person From { get; set; }
    Person To { get; set; }
    public string RelationshipType { get; set; }
}
public class Family
{
    Dictionary<string, Person> familyGraph = new Dictionary<string, Person>();
}

Представление списка смежности будет сохранено в ключе, паре значений, а все ребра человека будут сохранены в соответствующем узле Person.

Так что добавить отношения с этим просто.

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

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

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

List<string> FindNeice(string username)
{
    currentPerson = GerPerson(username)
    siblings = currentPerson.Mother.Children;
    niece = siblings.Where(mbox => mbox.Gender == "F").SelectMany(m => m.Children);
}

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

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

1 Ответ

1 голос
/ 11 июня 2019

Семейные отношения кажутся такими простыми, но они становятся сложными в спешке.Вы упоминаете отношения в законе (вы - мать жены), но даже более близкие отношения сложны.Рассмотрим братьев и сестер, например.Технически:

  • Брат или сестра - это человек, с которым у вас одна и та же биологическая мать и отец.
  • Полубрат - это человек, с которым вы делитесьта же биологическая мать или отец.
  • Сводный брат - это человек, чья биологическая мать мать или отец состоит в браке с вашей биологической матерью или отцом.

И даже не заводите меня на усыновительные отношения.

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

Самый гибкий способ смоделировать это - иметь запись Person, которая содержит информацию об этом человеке, но не о каких-либо отношениях.Эта информация будет, например, имя, дата рождения и т. Д. И этот человек имеет уникальный идентификатор, который никогда не изменится.Скажем, 64-битное число.У вас есть большая таблица Person записей.

У вас также есть большая таблица Relationship записей.Каждая запись содержит источник, цель и тип отношения.Существует два типа отношений: родитель и супруг.

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

Так что, если ваша ближайшая семья состоит из вас (Джордж), ваших родителей (Мэри и Дейв) и двух ваших братьев и сестер (Боб и Салли), отношения будут такими:

Mary, George, Parent
Dave, George, Parent
Mary, Bob, Parent
Dave, Bob, Parent
Mary, Sally, Parent
Dave, Sally, Parent
Mary, Dave, Spouse
Dave, Mary, Spouse

Прочитайте это как «Мария - родитель Джорджа».

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

Поэтому, если вы хотите найти братьев и сестер человека, вы делаете это:

  1. Запросите таблицу отношений для всехотношения, где идентификатором этого человека является цель, а тип отношения родительский.Это дает вам список идентификаторов родителей человека.
  2. Запросите таблицу Отношений для всех отношений, где один из идентификаторов родителей - это Источник, а тип отношения - родительский.Это дает вам список всех родителей родителей.Этот список будет включать в себя оригинальную личность и всех детей родителей: по определению родные братья и сестры оригинальной личности.

Затем вы можете выбрать, хотите ли вы написать код для более сложных отношений или разработатьпростые подобные сценарию определения для тех.Обратите внимание:

parents - intrinsic function
children - intrinsic function
spouse - intrinsic function
siblings - (parents children) (probably should be an intrinsic, to eliminate self)
grandparents - (parents parents)
uncles/aunts - (parents siblings)
cousins - (parents siblings children)
parents-in-law - (spouse parents)
siblings-in-law - (spouse siblings)
nieces/nephews - (siblings children) + (siblings-in-law children)

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

Кодирование становится вопросом написания четырех встроенных функций (Parents, Children, Siblings и Spouse), каждый из которых принимает в качестве параметра IEnumerable<PersonId> и возвращает IEnumerable<PersonId>, а затем объединяет эти функции.Функция Siblings должна исключать из результата любые значения, которые были во входном параметре.Двоюродные братья становятся:

var person = new List<PersonId> {personId};
var cousins = person.Parents().Siblings().Children();

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

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

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

brother - (siblings male)
grandmother - (parents parents female)
maternal-uncle - (parents female siblings male)
spouse-step-sister - (spouse siblings step female)
...