如何在 ISO Prolog 中定义(和命名)相应的安全术语比较谓词?

2024-05-23

标准术语顺序(ISO/IEC 13211-1 7.2 术语顺序)针对所有术语(包括变量)进行定义。虽然这有很好的用途——想想实施setof/3,这使得 8.4 术语比较中内置函数的许多其他干净且合乎逻辑的使用成为声明式噩梦,到处都是 imps(命令式构造的缩写形式)。 8.4 术语比较特征:

8.4 术语比较

8.4.1 (@=)/2、 (@>=)/2。
8.4.2 比较/3 http://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#compare.
8.4.3 排序/2 http://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#sort.
8.4.4 键排序/2 http://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#keysort.

举个例子,请考虑:

?- X @< a.
true.

这会成功,因为

7.2 术语顺序

一个订购术语先于(3.181) 定义是否或
不是一个术语X术语在术语之前Y.

If X and Y那么是相同的术语X 术语先于 Y
and Y 术语先于 X都是假的。

If X and Y有不同的类型:X术语先于Y iff the
类型X位于类型之前Y按以下顺序:
variable先于floating point先于integer
先于atom先于compound.

注意 - 测试术语排序的内置谓词
定义见 8.4。
...

因此所有变量都小于a。但有一次X被实例化:

?- X @< a, X = a.
X = a.

结果无效。

所以这就是问题所在。为了克服这个问题,人们可以使用约束,或者只坚持核心行为,从而产生一种instantiation_error http://www.complang.tuwien.ac.at/ulrich/iso-prolog/error_k#error_classes.

7.12.2 错误分类

错误按照形式进行分类Error_term:

a)当一个实例化错误
参数或其组成部分之一是变量,并且
需要实例化的参数或组件。它有
表格instantiation_error.

通过这种方式,只要没有发生实例化错误,我们就可以确定结果是明确定义的。

For (\==)/2,已经有dif/2 https://stackoverflow.com/questions/tagged/prolog-dif它使用约束或dif_si/2 https://stackoverflow.com/a/20238931/772868(以前iso_dif/2)这会产生一个干净的实例化错误。

dif_si(X, Y) :-
   X \== Y,
   ( X \= Y -> true
   ; throw(error(instantiation_error,dif_si/2))
   ).

所以我的问题是:如何定义(和命名)相应的安全术语比较谓词ISO序言 http://www.complang.tuwien.ac.at/ulrich/iso-prolog/prologue#status_quo?理想情况下,没有任何明确的术语遍历。也许需要澄清:以上dif_si/2不使用任何明确的术语遍历。两个都(\==)/2 and (\=)/2内部遍历该术语,但与使用显式遍历相比,这样做的开销非常低(=..)/2 or functor/3, arg/3.


iso_dif/2实现起来比比较简单得多:

  • 内置的\=操作员可用
  • 您现在到底要提供什么论据\=

定义

根据您的评论,安全比较意味着如果两个子项中的变量都被实例化,则顺序不会改变。如果我们命名比较lt,我们有例如:

  • lt(a(X), b(Y)):对于所有 X 和 Y 始终成立,因为a @< b
  • lt(a(X), a(Y)): 我们不确定:intanciation_error
  • lt(a(X), a(X)):总是失败,因为 X @

正如评论中所述,如果在并行遍历两个术语时,第一个(可能)有区别的术语对包含:

  • 两个不相同的变量(lt(X,Y))
  • 一个变量和一个非变量 (lt(X,a), or lt(10,Y))

但首先,让我们回顾一下您不想使用的可能方法:

  • 定义显式的术语遍历比较函数。我知道出于性能原因您不愿意这样做,但这仍然是最直接的方法。无论如何,我建议您这样做,以便您有一个参考实现来与其他方法进行比较。

  • 使用约束进行延迟比较:我不知道如何使用 ISO Prolog 来做到这一点,但是使用例如ECLiPSe,我将暂停对未实例化变量集的实际比较(使用term_variables/2),直到不再有变量为止。之前,我还建议使用协程/0 http://eclipseclp.org/doc/bips/kernel/obsolete/coroutine-0.html谓词,但我忽略了一个事实,即它不影响@<运算符(仅<).

    这种方法并不解决与您描述的完全相同的问题,但它非常接近。一个优点是,如果赋予变量的最终值满足比较,它不会引发异常,而lt当它事先不知道时抛出一个。

显式术语遍历(参考实现)

这是显式术语遍历方法的实现lt,安全版本@<。 请查看它以检查这是否是您所期望的。我可能错过了一些案例。我不确定这是否符合 ISO Prolog,但如果您愿意,也可以修复它。

lt(X,Y) :- X == Y,!,
    fail.

lt(X,Y) :- (var(X);var(Y)),!,
    throw(error(instanciation_error)).

lt(X,Y) :- atomic(X),atomic(Y),!,
    X @< Y.

lt([XH|XT],[YH|YT]) :- !,
    (XH == YH ->
         lt(XT,YT)
     ;   lt(XH,YH)).

lt(X,Y) :-
    functor(X,_,XA),
    functor(Y,_,YA),
    (XA == YA ->
       X =.. XL,
       Y =.. YL,
       lt(XL,YL)
    ;  XA < YA).

(编辑:考虑到 Tudor Berariu 的评论:(i)缺少 var/var 错误情况,(ii)首先按数量排序;此外,修复(i)允许我删除subsumes_term对于列表。谢谢。)

隐式术语遍历(不起作用)

这是我在不解构术语的情况下达到相同效果的尝试。

every([],_).
every([X|L],X) :-
    every(L,X).

lt(X,Y) :-
    copy_term(X,X2),
    copy_term(Y,Y2),
    term_variables(X2,VX),
    term_variables(Y2,VY),
    every(VX,1),
    every(VY,0),
    (X @< Y ->
         (X2 @< Y2 ->
              true
          ;   throw(error(instanciation_error)))
     ;   (X2 @< Y2 ->
              throw(error(instanciation_error))
          ;   false)).

基本原理

假设X @< Y成功了。 我们想要检查关系是否不依赖于某些未初始化的变量。 所以,我制作了各自的副本X2 and Y2 of X and Y,其中所有变量都被实例化:

  • In X2,变量统一为1。
  • In Y2,变量统一为0。

所以,如果关系X2 @< Y2仍然成立,我们知道我们不依赖变量之间的标准术语排序。否则,我们会抛出异常,因为这意味着1 @< 0以前没有发生的关系导致关系失败。

缺点

(基于OP的评论)

  • lt(X+a,X+b)应该成功但会产生错误。

    乍一看,人们可能会认为将两个项中出现的变量统一为具有相同的值,例如val,可能会解决这种情况。但也可能会出现其他情况X相比而言,这会导致错误的判断。

  • lt(X,3)应该会产生错误但会成功。

    In order to fix that case, one should unify X with something that is greater than 3. In the general case, X should take a value that is greater than other any possible term1. Practical limitations aside, the @< relation has no maximum: compound terms are greater than non-compound ones, and by definition, compound terms can be made arbitrarly great.

因此,这种方法并不是决定性的,而且我认为它不容易纠正。


1:但是请注意,对于任何给定的项,我们可以找到局部最大和最小项,这足以满足问题的目的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 ISO Prolog 中定义(和命名)相应的安全术语比较谓词? 的相关文章

随机推荐

  • 覆盖 Android 中的电源按钮

    我正在开发一个应用程序 其中我需要在按下电源按钮时执行一个操作 但不幸的是我无法处理按下电源按钮时的操作 我尝试使用 onKeyDown 和dispatchKeyEvent 方法 但似乎没有任何效果 任何人都可以建议我解决这个问题的任何其他
  • 是否可以直接获取 Puppeteer 音频源和/或输入音频到 Puppeteer?

    我想将 WAV 或 MP3 输入到 puppeteer 作为麦克风 但是在无头模式下应用程序被静音 所以我想知道是否有一种方法可以直接将输入输入到浏览器中 我还想知道是否可以在无头状态下从浏览器获取音频源 和 或录制音频并将其放在文件夹中
  • 限制 Imagemagick 使用的空间和内存

    我在 Rails 应用程序上使用 Imagemagick 使用 rmagick 但我的服务器 Ubuntu 不是很大 当我启动转换进程时 Imagemagick 占据了我的服务器 30GB HDD 的所有位置 内存 我想限制内存和 tmp
  • 将 UTC 格式的 QDateTime 转换为本地系统时间

    我从这样的字符串构造 QDateTime QDateTime date QDateTime fromString 2010 10 25T10 28 58 570Z yyyy MM ddTHH mm ss zzzZ 我知道date是 UTC
  • 从 RSpec 迁移到 Minitest::Spec?

    是否有可遵循的策略或一组步骤来从 RSpec 2 迁移到MiniTest Spec 我想考虑为一个大型项目执行此操作 但我不知道从哪里开始 我已经很久没有使用 MiniTest Spec 了 我正在自己移植一些测试 但以下是我从 RSpec
  • IIS Express 捕获所有子域 url

    我正在寻找 IIS Express 中子域包罗万象 url 的解决方案 基本上 我环顾四周并找到了如何在 IIS Express 中创建域 子域 它很容易找到 我所要做的就是在 IIS Express 的 ApplicationHost c
  • 如何计算CLLocationDistance的中心坐标

    我想计算我的位置和一些注释之间的中心点 到目前为止我已经这样做了 CLLocation myLoc self locMgr location MKPointAnnotation middleAnnotation locationV anno
  • 是否可以对 UILabel 的文本颜色变化进行动画处理? [复制]

    这个问题在这里已经有答案了 UIView animateWithDuration 5 animations myLabel textColor UIColor redColor 标签文本颜色立即改变 Try this UIView tran
  • 如何强制jar使用(或jar运行的jvm)utf-8而不是系统的默认编码

    我的Windows默认编码是GBK 而我的Eclipse完全是utf 8编码 因此 在我的 Eclipse 中运行良好的应用程序崩溃了 因为导出为 jar 文件时这些单词变得不可读 我必须在 bat 文件中写入以下行才能运行该应用程序 st
  • 使用 WebClient C# 添加请求标头

    我有以下代码 用于将网页下载到字节数组中 然后使用 Response Write 打印它 WebClient client new WebClient byte data client DownloadData requestUri Ini
  • 如何将工作表和范围作为变量传递?

    我想在子例程之间传递工作表的名称和范围 以下抛出 下标超出范围 错误 Sub This x Sheet1 y D3 MsgBox x Range y Value End Sub This is 我的项目资源管理器的示例 https i st
  • NHibernate 和 DateTime 映射的问题

    我在查询时遇到问题 我在给定的范围内选择记录 时间跨度 我从中选择的列的类型为日期 我已经映射了这个 列作为 DateTime 属性 查询可以工作 但速度很慢 生成的查询如下所示 由NH分析器 http nhprof com select
  • 致命错误:libavcodec/avcodec.h 没有这样的文件或目录编译终止

    我正在尝试使用 gcc 执行tutorial01 c 并且 gcc 和tutorial01 c 以及 libavcodec 和 libavformat 及其关联文件位于同一文件夹中 它给了我这个错误 致命错误 libavcodec avco
  • 在正确的集合中创建索引

    我用 Index unique true 注释文档 如下所示 public class ADocumentWithUniqueIndex private static final long serialVersionUID 1L Index
  • R闪亮:基于checkboxgroupinput的子集数据

    我想根据复选框输入动态选择的列对数据进行子集 有什么方法可以使我的输入文件在我的代码中全局可用 以便可以方便地进行进一步的操作 以下是我的代码 Server R library shiny shinyServer function inpu
  • Javascript“this”在 IE 中丢失上下文

    以下在 firefox safari chrome 中工作正常 在 IE 中 this 似乎在 handleEvent 函数中丢失上下文 警报的结果是 object Window 这不是我想要的 当从handleEvent 输出时 this
  • 如何使用标准 JavaScript 在 CSS 转换结束后立即重新启动它?

    我构建了一种密码生成器 只要倒计时到期 它就会显示新密码 不幸的是 我只设法弄清楚如何运行我的代码一次 倒计时由一个简单的 CSS 过渡组成 我想保留它 因为它比我的其他尝试平滑得多 其中我尝试使用 JavaScript 重复更新宽度 va
  • 有 Mac 版的 IE 测试器吗? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • WKWebView在后台,几个奇怪的断言

    我想找出iOS中当前浏览器的userAgent 所以在 Xcode 创建的默认项目中我添加了 import ViewController h import
  • 如何在 ISO Prolog 中定义(和命名)相应的安全术语比较谓词?

    标准术语顺序 ISO IEC 13211 1 7 2 术语顺序 针对所有术语 包括变量 进行定义 虽然这有很好的用途 想想实施setof 3 这使得 8 4 术语比较中内置函数的许多其他干净且合乎逻辑的使用成为声明式噩梦 到处都是 imps