【问题标题】:Algorithm for Deductions扣除算法
【发布时间】:2013-02-14 03:13:19
【问题描述】:

这就是问题所在。

如果我们有两个语句 p=>qq=>r,也暗示p=>r

给定一组语句,我需要找出给定语句是true 还是false,或者不能从给定语句中得出结论。

示例:
给定语句p=>q, p=>r, q=>s

  • 如果输入是p=>s,我应该得到输出true

  • 如果输入是p=>t,我应该得到输出Cannot be concluded

  • 如果输入是p=> ~p,我应该得到输出false

我的问题是实现这一点的最佳数据结构是什么以及使用什么算法。

谢谢。

【问题讨论】:

  • 您只是担心原子事物之间的“隐含”运算符吗?或者你能不能有更多奇特的东西,比如~p or ~s and r
  • 你的问题有一个漏洞。您缺少某种我们无法猜测的 input 。 p=>q , q=>r 将暗示 p=>r 假设您的代数系统是传递的。仍然要使暗示为真(在正常命题逻辑中),我们需要某些输入。类似 p was true and q was false, what is p=>q ? 的东西。所以请清楚地解释你的问题。
  • p=>q 表示如果 p 为真,则 q 为真。
  • @Deamonpog 这个问题并没有真正的漏洞。它要求一个程序来决定一个句子是否可以在给定理论(公理集)的情况下被正式证明。见en.wikipedia.org/wiki/…
  • @Anil YACAS 实现了这一点,因此您可以查看他们的灵感来源:yacas.sourceforge.net/refchapter14.html。 (如果您为此找到了一个高效算法,您将获得博士学位并被邀请参加世界各地的会议。命题逻辑的可判定性是 co-NP 完成的:en.wikipedia.org/wiki/…

标签: c++ python c algorithm


【解决方案1】:

所以,我仍然不完全清楚您要做什么。冒着被否决的风险,我将把它踢出去,看看人们的想法。

我可能会从构建图表开始。每个实体(p、q 等)都有自己的节点。 “暗示”意味着你在两个节点之间画一条线。那么,任何输入只是看你是否能找到一种遍历图的方法——所以在你的例子中,a => b,b => c,图有三个节点,a 连接到 b,b连接到 c。 a 和 c 之间存在路径这一事实意味着 a 蕴含 c。

我还没有进一步审查这个想法,但这似乎是一个有趣的前景。特别是因为图论很酷,而且很多人都对它感兴趣(即 Facebook 高管)。并且 Python 中有很好的模块用于分析图形。 (我认为 C++ 也是如此。您始终可以使用 Gephi 手动指定它:https://gephi.org/

【讨论】:

  • 只要您在您的语言中允许 only 变量名称和隐含运算符,此方法就可以工作。只要您像 OP 那样引入 NOT ~,它就会突然变得复杂得多!
  • 如果是检查两件事之间是否存在联系是可以的,但我想我的问题不止于此。
  • @Anil 如果您真的只对您给出的一个扣除规则感兴趣,那么上述基于图的简单方法就足够了。原因是您没有任何结构扩展或缩减的规则,例如你没有像 p=>r 这样的规则,因此对于任何 q 都没有 p and q => r。因此,您可以将所有pq 甚至像p and qp=>q 这样的复杂子句视为原子。但是,一旦您在微积分中引入了能够对这些原子进行结构修改的规则,简单的图形就无法工作,因为结构修改规则会动态添加图形节点。
  • @jogojapan 和 us2012:我最近一直在玩图论,这更像是一场头脑风暴。但这是一个好主意,我确信几百年前有人想出了这个主意。话虽这么说,我实际上有点惊讶,没有办法修饰你的图表来解释更复杂的结构。通过与数学家打交道,我知道有些人会竭尽全力挽救一个漂亮的想法:)
【解决方案2】:

很多人多年来一直研究这个问题。您需要的是SAT Solver。查找 ChaffzChaff 或任何其他常用的 SAT 求解器。您想使用 (p->q && q->r) -> (p -> r) 之类的子句并否定它们并确定是否可以满足。如果否定不能满足,那么你就有一个定理,它总是正确的。如果原分句可满足,而分句的否定可满足,则应返回“不能成立”。如果原始条款不能满足,那么你就有了错误的东西。

这实际上是一个经过充分研究的问题。有很好的算法,但是你可以处理多少命题变量是有硬性限制的。 SAT 是 NP 难题的核心。一类未知有效算法的问题。

【讨论】:

【解决方案3】:

我认为鉴于您的问题很简单,您可以使用简单的map。与vector 相比的主要优势在于查找速度更快。

// For "p":  { name: "p", positive: "true" }
// For "~q": { name: "q", positive: "false" }
struct Predicate {
    std::string _name;
    bool _positive;
};

using PredicateSetType = std::unordered_set<Predicate>;
using PredicateMapType = std::unordered_map<Predicate, PredicateSetType>;

您以下列方式使用映射:当给定p =&gt; q 时,您将{ "q", true } 插入到与{ "p", true } 关联的谓词集中。

请注意,这实际上是对有向图进行编码,因此探索图的典型方法适用于证明陈述。

【讨论】:

  • 但是“p”可能不是真的,对吧? p=>q 表示如果 p 为真,则 q 为真。
  • @Anil:我不关心p 是否真实,_positive 属性用于区分p ({ "p", true }) 和~p (@987654332 @) 如评论中所示。
  • 那么告诉我如何遍历地图来判断给定的语句是否可以结束?
  • @Anil:地图只是有向图的物理表示,例如,您可以进行广度优先或深度优先遍历(从 p 开始,在 p =&gt; r 语句中, 直到找到r~r 或用尽所有可能性)。
  • 你读过所有的cmets吗?即使我实现了这一点,我的运行时间也不会改变,这将如何比向量对更快?该算法应该适用于 500 个基本语句。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-02
  • 2020-03-13
  • 1970-01-01
  • 2019-09-11
  • 2023-01-17
  • 1970-01-01
  • 2020-04-20
相关资源
最近更新 更多