热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

家谱软件中的循环

我是一些家庭树软件的开发者(用C​​和Qt编写)。在我的一位客户向我邮寄错误报告之前,我没有遇到任何问题。问题是客户有两个孩子和自己的女儿

我是一些家庭树软件的开发者(用C ​​++和Qt编写)。 在我的一位客户向我邮寄错误报告之前,我没有遇到任何问题。 问题是客户有两个孩子和自己的女儿,因此,他因错误而无法使用我的软件。

这些错误是我处理家族图的各种断言和不变量的结果(例如,在走一个循环之后,程序声明X不能同时是Y的父亲和祖父)。

如何在不删除所有数据断言的情况下解决这些错误?




#1楼

系谱数据是循环的,不适合非循环图,所以如果你有针对周期的断言,你应该删除它们。

在不创建自定义视图的情况下在视图中处理此方法的方法是将循环父级视为“ghost”父级。 换句话说,当一个人同时是同一个人的父亲和祖父时,则正常显示祖父节点,但父节点被渲染为具有简单标签的“幽灵”节点(“看到祖父”) )并指向祖父。

为了进行计算,您可能需要改进逻辑以处理循环图,以便在存在循环时不会多次访问节点。




#2楼


断言不能在现实中存活下来

通常断言在与现实世界数据的接触中无法生存。 它是软件工程过程的一部分,用于决定您要处理哪些数据以及哪些数据超出范围。


循环家庭图

关于家庭“树”(实际上它是完整的图表,包括周期),有一个很好的轶事:


我娶了一个有一个成年女儿的寡妇。 经常拜访我们的父亲爱上了我的继女,并娶了她。 结果,我的父亲成了我的儿子,我的女儿成了我的母亲。 一段时间后,我给了我的妻子一个儿子,他是我父亲的兄弟,还有我的叔叔。 我父亲的妻子(也是我的女儿和母亲)有一个儿子。 结果,我和同一个人有了一个兄弟和一个孙子。 我的妻子现在是我的祖母,因为她是我母亲的母亲。 所以我是我妻子的丈夫,同时也是我妻子的继孙。 换句话说,我是我自己的爷爷。


当你考虑到代理人或“模糊的父亲”时,事情变得更加奇怪。


如何处理


将周期定义为超出范围

您可以决定您的软件不应该处理这种罕见的情况。 如果发生这种情况,用户应使用不同的产品。 这使得处理更常见的情况更加健壮,因为您可以保留更多的断言和更简单的数据模型。

在这种情况下,请为您的软件添加一些良好的导入和导出功能,以便用户可以在必要时轻松迁移到其他产品。


允许手动关系

您可以允许用户添加手动关系。 这些关系不是“一等公民”,即软件按原样使用它们,不检查它们,也不在主数据模型中处理它们。

然后,用户可以手动处理罕见情况。 您的数据模型仍将非常简单,您的断言将继续存在。

小心手动关系。 有一种诱惑,使它们完全可配置,从而创建一个完全可配置的数据模型。 这不起作用:您的软件无法扩展,您将遇到奇怪的错误,最后用户界面将无法使用。 这种反模式被称为“软编码” ,而“每日WTF”则充满了这样的例子。


使您的数据模型更灵活,跳过断言,测试不变量

最后的手段是使您的数据模型更加灵活。 您必须跳过几乎所有断言并将数据模型建立在完整的图表上。 如上例所示,很容易成为你自己的祖父,所以你甚至可以有周期。

在这种情况下,您应该广泛测试您的软件。 您必须跳过几乎所有断言,因此很有可能会出现其他错误。

使用测试数据生成器检查异常测试用例。 有Haskell , Erlang或C的快速检查库。 对于Java / Scala,有ScalaCheck和Nyaya 。 一个测试的想法是模拟随机群体,让它随机杂交,然后让你的软件首先导入,然后导出结果。 期望的是,输出中的所有连接也在输入中,反之亦然。

属性保持不变的情况称为不变量。 在这种情况下,不变量是模拟群体中个体之间的“浪漫关系”集。 尝试尽可能多地找到不变量,并使用随机生成的数据对其进行测试。 不变量可以起作用,例如:


  • 即使你增加了更多的“浪漫关系”,叔叔也会留下叔叔
  • 每个孩子都有父母
  • 两代人口中至少有一个祖父母

或者他们可以是技术性的:


  • 您的软件不会在高达100亿成员的图表上崩溃(无论有多少互连)
  • 您的软件按O(节点数)和O(边数= 2)进行扩展
  • 您的软件可以保存并重新加载每个家庭图表,最多可达100亿成员

通过运行模拟测试,您会发现许多奇怪的角落情况。 修复它们将花费大量时间。 此外,您将失去很多优化,您的软件运行速度会慢得多。 您必须决定,是否值得,以及这是否属于您的软件范围。




#3楼

除了潜在的法律含义之外,您肯定需要将家族树上的“节点”视为前任人,而不是假设该节点可以是唯一的人。

让树节点包含一个人以及后继者 - 然后您可以在树的下方有另一个节点,其中包含具有不同后继者的同一个人。




#4楼

我猜你有一些价值,可以唯一地识别你可以作为支票基础的人。

这是一个棘手的问题。 假设你想保持结构为树,我建议:

假设: A有孩子和他自己的女儿。

A将自己添加到AB 。 一旦担任父亲的角色,我们称之为男朋友。

添加一个is_same_for_out()函数,该函数告诉程序的输出生成部分,所有进入B内部的链接应该在数据呈现时转到A

这将为用户做一些额外的工作,但我想IT的实施和维护相对容易。

从中构建,您可以使用代码同步AB来避免不一致。

这个解决方案肯定不是完美的,但这是第一种方法。




#5楼

我讨厌对这种搞砸的情况发表评论,但不重新调整所有不变量的最简单方法是在图形中创建一个虚拟顶点,作为代理回到乱伦的父亲身上。




#6楼

放松你的断言。

不是通过更改规则,这些规则很可能对99.9%的客户在输入数据时发现错误非常有帮助。

相反,将其从错误“无法添加关系”更改为带有“无论如何添加”的警告。




#7楼

这就是为什么像“Go”这样的语言没有断言的原因之一。 它们习惯于处理你可能没有想过的案例。 你应该只断言不可能的,而不仅仅是不可能的 。 做后者是断言声誉不好的原因。 每次你输入assert(走开十分钟并真正考虑它。

在你特别令人不安的情况下,这种说法在罕见但可能的情况下是虚假的,这是可以想象的,也是令人震惊的。 因此,在您的应用程序中处理它,如果只是说“此软件不是为处理您提供的场景而设计的”。

断言你的伟大,伟大,伟大的祖父是你的父亲是不可能的是一个合理的事情。

如果我在一家受雇于测试软件的测试公司工作,我当然会提出这种情况。 为什么? 每个少年而又聪明的“用户”都会做同样的事情,并在最终的“错误报告”中津津乐道。




#8楼

看来你(和/或你的公司)对家谱应该是什么有一个根本的误解。

让我澄清一点,我也为一家公司(其中一个产品)的产品组合中的家族树工作,我们一直在努力解决类似的问题。

在我们的案例中,问题,我也假设你的情况,来自GEDCOM格式,该格式对于一个家庭应该是什么非常自以为是。 然而,这种格式包含了一些关于家谱真正看起来的严重错误观念。

GEDCOM有许多问题,例如与同性关系,乱伦等不相容......在现实生活中发生的事情比你想象的更频繁(尤其是回到1700-1800时)。

我们已经将我们的家谱模型化为现实世界中发生的事件:事件(例如,出生,婚礼,订婚,工会,死亡,收养等)。 我们对这些没有任何限制,除了逻辑上不可能的(例如,一个不能是一个人自己的父母,关系需要两个人等等)

缺乏验证为我们提供了一个更“现实世界”,更简单,更灵活的解决方案。

至于这个具体的情况,我建议删除断言,因为它们并不普遍存在。

为了显示问题(将出现),我建议根据需要多次绘制相同的节点,通过在选择其中一个副本时点亮所有副本来暗示重复。




#9楼

您应该专注于真正为您的软件创造价值的东西 。 花在为一个消费者工作的时间是否值得许可证的价格? 可能不是。

我建议你向这位客户道歉,告诉他他的情况超出了你的软件的范围并向他退款。




#10楼

这是家庭树的问题:它们不是树木。 它们是有向无环图或DAG。 如果我正确理解人类生殖生物学的原理,就不会有任何循环。

据我所知,即使是基督徒也接受堂兄弟之间的婚姻(以及子女),这会将家谱变成家庭DAG。

故事的寓意是:选择正确的数据结构。




#11楼

你的家谱应该使用直接关系。 这样你就不会有一个循环。




#12楼

愚蠢问题的另一个模拟严肃答案:

真正的答案是,使用适当的数据结构。 使用没有循环的纯树无法完全表达人类谱系。 你应该使用某种图形。 此外,在进一步讨论之前,先与人类学家交谈,因为即使在最简单的“西方父权制一夫一妻婚姻”案例中,也有很多其他地方可以尝试类似的家谱模型。

即使我们想忽略这里讨论的本地禁忌关系,也有很多完全合法且完全出乎意料的方法将循环引入家谱。

例如: http : //en.wikipedia.org/wiki/Cousin_marriage

基本上,表亲婚姻不仅是普遍的和预期的,它是人类从数千个小家庭群体变成全球60亿人口的原因。 它不能以任何其他方式工作。

在家谱,家庭和血统方面,确实很少有普遍性。 几乎任何关于规范的严格假设都暗示着阿姨可以成为谁,或者谁可以嫁给谁,或者如何将儿童合法化为继承目的,可能会被世界或历史上的某个例外所困扰。




#13楼

您应该将Atreides系列(现代, Dune或古代, Oedipus Rex )设置为测试用例。 通过使用已清理的数据作为测试用例,您找不到错误。




#14楼

所以,我在家庭树软件方面做了一些工作。 我认为你要解决的问题是你需要能够在不进入无限循环的情况下走树 - 换句话说,树需要是非周期性的。

然而,看起来你断言一个人和他们的祖先之间只有一条路。 这将保证没有周期,但是太严格了。 从生物学角度讲,后代是有向无环图 (DAG)。 你所拥有的案例当然是一个堕落的案例,但这种事情一直发生在较大的树上。

例如,如果你看一下n代的2 ^ n个祖先,如果没有重叠,那么你在公元1000年就会有更多的祖先,而不是有人活着。 所以,必须有重叠。

但是,您也倾向于获得无效的循环,只是错误的数据。 如果您正在遍历树,则必须处理循环。 您可以在每个单独的算法中或在加载时执行此操作。 我是在加载时做的。

在树中查找真实循环可以通过几种方式完成。 错误的方法是从给定的个体标记每个祖先,并且当遍历时,如果已经标记了要进入下一个的人,则切断链接。 这将切断潜在的准确关系。 正确的方法是从每个人开始,并用每个人的路径标记每个祖先。 如果新路径包含当前路径作为子路径,那么它是一个循环,应该被打破。 您可以将路径存储为vector (MFMF,MFFFMF等),这使得比较和存储非常快。

还有一些其他方法可以检测周期,例如发送两个迭代器并查看它们是否与子集测试发生冲突,但我最终使用了本地存储方法。

另请注意,您不需要实际切断链接,只需将其从普通链接更改为“弱”链接,而不是某些算法。 在选择标记为弱的链接时,您还需要注意; 有时你可以通过查看出生日期信息来确定周期应该被打破的地方,但是由于缺少这么多数据,你常常无法弄清楚。




#15楼

一些答案已经显示了保持断言/不变量的方法,但这似乎是对断言/不变量的误用。 断言是为了确保应该为真的东西是真的,并且不变量是为了确保不应该改变的东西不会改变。

你在这里断言的是,不存在乱伦关系。 显然它们确实存在,所以你的断言是无效的。 你可以解决这个断言,但真正的错误在于断言本身。 断言应该被删除。




#16楼

最重要的是avoid creating a problem ,所以我认为你应该使用直接关系来避免出现问题。

正如@markmywords所说, #include“fritzl.h”。

最后我要说recheck your data structure 。 也许那里出了问题(也许双向链表解决了你的问题)。




#17楼

你应该仍然检查一个人是他/她自己的父母或其他不可能的情况,并提出错误,而不是删除所有的断言。 如果用户不太可能仍然检测到常见的输入错误,可能会发出警告,但如果一切正确,它都会起作用。

我将数据存储在一个带有每个人的永久整数的向量中,并将父对象和子对象存储在人对象中,其中所述int是向量的索引。 这在几代人之间会很快(但对于名字搜索这样的事情来说很慢)。 对象将按照创建时的顺序排列。




#18楼

复制父(或使用符号链接/引用)。

例如,如果您使用的是分层数据库:

$ #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/Father4 directories, 1 file

推荐阅读
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • 浏览器作为我们日常不可或缺的软件工具,其背后的运作机制却鲜为人知。本文将深入探讨浏览器内核及其版本的演变历程,帮助读者更好地理解这一关键技术组件,揭示其内部运作的奥秘。 ... [详细]
  • 在当前的软件开发领域,Lua 作为一种轻量级脚本语言,在 .NET 生态系统中的应用逐渐受到关注。本文探讨了 Lua 在 .NET 环境下的集成方法及其面临的挑战,包括性能优化、互操作性和生态支持等方面。尽管存在一定的技术障碍,但通过不断的学习和实践,开发者能够克服这些困难,拓展 Lua 在 .NET 中的应用场景。 ... [详细]
  • 如何精通编程语言:全面指南与实用技巧
    如何精通编程语言:全面指南与实用技巧 ... [详细]
  • 如何高效启动大数据应用之旅?
    在前一篇文章中,我探讨了大数据的定义及其与数据挖掘的区别。本文将重点介绍如何高效启动大数据应用项目,涵盖关键步骤和最佳实践,帮助读者快速踏上大数据之旅。 ... [详细]
  • 在《Cocos2d-x学习笔记:基础概念解析与内存管理机制深入探讨》中,详细介绍了Cocos2d-x的基础概念,并深入分析了其内存管理机制。特别是针对Boost库引入的智能指针管理方法进行了详细的讲解,例如在处理鱼的运动过程中,可以通过编写自定义函数来动态计算角度变化,利用CallFunc回调机制实现高效的游戏逻辑控制。此外,文章还探讨了如何通过智能指针优化资源管理和避免内存泄漏,为开发者提供了实用的编程技巧和最佳实践。 ... [详细]
  • 您的数据库配置是否安全?DBSAT工具助您一臂之力!
    本文探讨了Oracle提供的免费工具DBSAT,该工具能够有效协助用户检测和优化数据库配置的安全性。通过全面的分析和报告,DBSAT帮助用户识别潜在的安全漏洞,并提供针对性的改进建议,确保数据库系统的稳定性和安全性。 ... [详细]
  • 本文详细解析了Java类加载系统的父子委托机制。在Java程序中,.java源代码文件编译后会生成对应的.class字节码文件,这些字节码文件需要通过类加载器(ClassLoader)进行加载。ClassLoader采用双亲委派模型,确保类的加载过程既高效又安全,避免了类的重复加载和潜在的安全风险。该机制在Java虚拟机中扮演着至关重要的角色,确保了类加载的一致性和可靠性。 ... [详细]
  • 该大学网站采用PHP和MySQL技术,在校内可免费访问某些外部收费资料数据库。为了方便学生校外访问,建议通过学校账号登录实现免费访问。具体方案可包括利用学校服务器作为代理,结合身份验证机制,确保合法用户在校外也能享受免费资源。 ... [详细]
  • 使用 ListView 浏览安卓系统中的回收站文件 ... [详细]
  • Milvus 获邀参加 2020 开源软件供应链峰会,探讨大数据领域的创新应用与实践
    2020年11月14日至15日,由中国科学软件研究所和openEuler社区联合主办的开源软件供应链峰会在南京玄武苏宁诺富特酒店隆重召开。作为开源社区的重要成员,Milvus受邀参加了此次盛会,与业界专家共同探讨了大数据领域的创新应用与实践经验。会上,Milvus分享了其在高性能向量搜索引擎方面的最新进展和技术突破,为大数据处理和分析提供了新的解决方案。 ... [详细]
  • 2018 HDU 多校联合第五场 G题:Glad You Game(线段树优化解法)
    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6356在《Glad You Game》中,Steve 面临一个复杂的区间操作问题。该题可以通过线段树进行高效优化。具体来说,线段树能够快速处理区间更新和查询操作,从而大大提高了算法的效率。本文详细介绍了线段树的构建和维护方法,并给出了具体的代码实现,帮助读者更好地理解和应用这一数据结构。 ... [详细]
  • 为开发者提供了一系列实用的参考网站和资源链接,包括HTML速查手册( 和 ),帮助开发者快速查找和学习相关技术知识。此外,还涵盖了其他重要的开发工具和文档,为编程工作提供全面支持。 ... [详细]
  • 提升 Kubernetes 集群管理效率的七大专业工具
    Kubernetes 在云原生环境中的应用日益广泛,然而集群管理的复杂性也随之增加。为了提高管理效率,本文推荐了七款专业工具,这些工具不仅能够简化日常操作,还能提升系统的稳定性和安全性。从自动化部署到监控和故障排查,这些工具覆盖了集群管理的各个方面,帮助管理员更好地应对挑战。 ... [详细]
  • 深入探讨:Java 8 中 HashMap 链表为何选择红黑树而非 AVL 树
    深入探讨:Java 8 中 HashMap 链表为何选择红黑树而非 AVL 树 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有