如何将 Prolog CLP(R) 与实向量连接起来?
How to interface Prolog CLP(R) with real vectors?
我正在使用 Prolog 求解简单的几何方程。
例如,我可以将通过两个点 p1
和 p2
的直线上的所有点 p3
定义为:
line((X1, Y1, Z1), (X2, Y2, Z2), T, (X3, Y3, Z3)) :-
{(X2 - X1) * T = X3},
{(Y2 - Y1) * T = Y3},
{(Z2 - Z1) * T = Z3}.
然后像 line((0, 0, 0), (1, 1, 1), _, (2, 2, 2))
这样的谓词为真。
但我真正想要的是写下这样的东西:
line(P1, P2, T, P3) :- {(P2 - P1) * T = P3}.
其中 P1、P2 和 P3 是实数向量。
达成类似目标的最佳方式是什么?到目前为止,我发现最好的方法是重写我自己的 add
、subtract
和 multiply
谓词,但这并不方便。
这是一个解决方案,您仍然需要为每个要处理的运算符编写一些代码,但它仍然在使用时提供了很好的语法。
让我们从将向量上的算术表达式计算为向量的概念开始。这本质上是逐个应用算术运算。 (但您可以添加点积或任何您喜欢的内容。)
:- use_module(library(clpr)).
vectorexpr_value((X,Y,Z), (X,Y,Z)).
vectorexpr_value(V * T, (X,Y,Z)) :-
vectorexpr_value(V, (XV,YV,ZV)),
{ X = XV * T },
{ Y = YV * T },
{ Z = ZV * T }.
vectorexpr_value(L + R, (X,Y,Z)) :-
vectorexpr_value(L, (XL,YL,ZL)),
vectorexpr_value(R, (XR,YR,ZR)),
{ X = XL + XR },
{ Y = YL + YR },
{ Z = ZL + ZR }.
vectorexpr_value(L - R, (X,Y,Z)) :-
vectorexpr_value(L, (XL,YL,ZL)),
vectorexpr_value(R, (XR,YR,ZR)),
{ X = XL - XR },
{ Y = YL - YR },
{ Z = ZL - ZR }.
例如:
?- vectorexpr_value(A + B, Result).
A = (_1784, _1790, _1792),
B = (_1808, _1814, _1816),
Result = (_1832, _1838, _1840),
{_1808=_1832-_1784},
{_1814=_1838-_1790},
{_1816=_1840-_1792} .
鉴于此,我们现在可以通过 "evaluating" 定义 "equality" 向量表达式,并对结果断言逐点相等。为了让它看起来漂亮,我们可以为它定义一个运算符:
:- op(700, xfx, ===).
这将 ===
定义为与其他相等运算符 =
、=:=
等具有相同优先级的中缀运算符。Prolog 不允许您重载运算符,因此我们做了一个新的。您可以将运算符中的三个 =
符号视为在 三个 维度上表示相等。
这里是相应的谓词定义:
ExprL === ExprR :-
vectorexpr_value(ExprL, (XL,YL,ZL)),
vectorexpr_value(ExprR, (XR,YR,ZR)),
{ XL = XR },
{ YL = YR },
{ ZL = ZR }.
我们现在几乎可以按照您的要求定义 line/4
:
line(P1, P2, T, P3) :-
(P2 - P1) * T === P3.
测试:
?- line((0,0,0), (1,1,1), Alpha, (2,2,2)).
Alpha = 2.0 ;
false.
?- line((0,0,0), (1,1,1), Alpha, (2,3,4)).
false.
我正在使用 Prolog 求解简单的几何方程。
例如,我可以将通过两个点 p1
和 p2
的直线上的所有点 p3
定义为:
line((X1, Y1, Z1), (X2, Y2, Z2), T, (X3, Y3, Z3)) :-
{(X2 - X1) * T = X3},
{(Y2 - Y1) * T = Y3},
{(Z2 - Z1) * T = Z3}.
然后像 line((0, 0, 0), (1, 1, 1), _, (2, 2, 2))
这样的谓词为真。
但我真正想要的是写下这样的东西:
line(P1, P2, T, P3) :- {(P2 - P1) * T = P3}.
其中 P1、P2 和 P3 是实数向量。
达成类似目标的最佳方式是什么?到目前为止,我发现最好的方法是重写我自己的 add
、subtract
和 multiply
谓词,但这并不方便。
这是一个解决方案,您仍然需要为每个要处理的运算符编写一些代码,但它仍然在使用时提供了很好的语法。
让我们从将向量上的算术表达式计算为向量的概念开始。这本质上是逐个应用算术运算。 (但您可以添加点积或任何您喜欢的内容。)
:- use_module(library(clpr)).
vectorexpr_value((X,Y,Z), (X,Y,Z)).
vectorexpr_value(V * T, (X,Y,Z)) :-
vectorexpr_value(V, (XV,YV,ZV)),
{ X = XV * T },
{ Y = YV * T },
{ Z = ZV * T }.
vectorexpr_value(L + R, (X,Y,Z)) :-
vectorexpr_value(L, (XL,YL,ZL)),
vectorexpr_value(R, (XR,YR,ZR)),
{ X = XL + XR },
{ Y = YL + YR },
{ Z = ZL + ZR }.
vectorexpr_value(L - R, (X,Y,Z)) :-
vectorexpr_value(L, (XL,YL,ZL)),
vectorexpr_value(R, (XR,YR,ZR)),
{ X = XL - XR },
{ Y = YL - YR },
{ Z = ZL - ZR }.
例如:
?- vectorexpr_value(A + B, Result).
A = (_1784, _1790, _1792),
B = (_1808, _1814, _1816),
Result = (_1832, _1838, _1840),
{_1808=_1832-_1784},
{_1814=_1838-_1790},
{_1816=_1840-_1792} .
鉴于此,我们现在可以通过 "evaluating" 定义 "equality" 向量表达式,并对结果断言逐点相等。为了让它看起来漂亮,我们可以为它定义一个运算符:
:- op(700, xfx, ===).
这将 ===
定义为与其他相等运算符 =
、=:=
等具有相同优先级的中缀运算符。Prolog 不允许您重载运算符,因此我们做了一个新的。您可以将运算符中的三个 =
符号视为在 三个 维度上表示相等。
这里是相应的谓词定义:
ExprL === ExprR :-
vectorexpr_value(ExprL, (XL,YL,ZL)),
vectorexpr_value(ExprR, (XR,YR,ZR)),
{ XL = XR },
{ YL = YR },
{ ZL = ZR }.
我们现在几乎可以按照您的要求定义 line/4
:
line(P1, P2, T, P3) :-
(P2 - P1) * T === P3.
测试:
?- line((0,0,0), (1,1,1), Alpha, (2,2,2)).
Alpha = 2.0 ;
false.
?- line((0,0,0), (1,1,1), Alpha, (2,3,4)).
false.