我在序言中写了一个谓词: 计算(函数,A,值,表达式) 函数是一个函数可能具有变量A或没有变量 值是A的值,而Expr是Function的表达式。
例如:
Start Date: <input class="txtStartDate" style="font: 13px/1.231 Trebuchet MS;" type="text" id="txtStartDate" name="Start Date" value="<%=currentDate%>" readonly><br><br>
End Date:   <input class="txtEndDate" style="font: 13px/1.231 Trebuchet MS;" type="text" id="txtEndDate" name="txtEndDate" value="<%=defaultDate%>" readonly required/><br><br>
<script>
$(function() {
$(".txtEndDate").datepicker({
changeMonth: true,
changeYear: true,
showOn: 'button',
buttonImage: '../../../images/calendar.png',
buttonImageOnly: true,
title: 'Click to open calendar',
alt: 'Click to open calendar'
});
});
$(function() {
$(".txtStartDate").datepicker({
changeMonth: true,
changeYear: true,
showOn: 'button',
buttonImage: '../../../images/calendar.png',
buttonImageOnly: true,
title: 'Click to open calendar',
alt: 'Click to open calendar'
});
});
$('#txtStartDate').datepicker();
$('#txtEndDate').datepicker();
$('#txtStartDate').change(function() {
var interval = 7;
function convertDateString(p) {
return (p < 10) ? '0' + p : p;
}
var startDate = new Date($(this).val());
startDate.setDate(startDate.getDate() + interval);
$('#txtEndDate').val(startDate.getFullYear() + '/' + convertDateString(startDate.getMonth() + 1) + '/' + convertDateString(startDate.getDate()));
});
</script>
-返回E = 6。
calculate(2*3,x,2,E)
-返回E = 4。
calculate(x+2,x,2,E)
-返回E = 18。
calculate(2*(5+x*x),x,2,E)
-返回E = x * 12。
calculate(x*(3+y*y),y,3,E)
上面的代码可以实现示例1,该示例在函数中没有变量,但是可以在函数具有变量时实现。
答案 0 :(得分:1)
首先,您没有传递函数,而是传递了表达式,结果就是它们的计算结果。由于这是Prolog,并且我们可以自由地进行此类操作,因此我更喜欢传递类似x=2
的一个参数,而不是传递两个x, 2
的参数,因为我觉得它更具可读性。因此,我要查找的谓词看起来将更像evaluate(+Expression, +Var=Value, ?Result)
。
我们在这里应该做的是对表达式形状的归纳。因此,表达式的基本情况就是变量和数字,所以让我们先处理它们:
evaluate(Num, _, Num) :- number(Num).
evaluate(Var, Var=Value, Value).
其中的第一个应该很明显:如果我评估为3,我应该得到3,而我实际上并不在乎变量绑定是什么样子。
第二个可能看起来像是重言式,但是想法是,如果我正在寻找变量x
的值并且我有一个看起来像x=3
的绑定,那么结果是{{1 }}。
现在,您必须进行一些复制和粘贴。令人高兴的是,您可以在此处轻松创建Prolog本身未内置的函数。缺点是,它将有点重复。
3
因此,这里的想法是递归在一个运算符的左右分支上向下移动,然后在这两个边上应用该运算符。这个小小的玩具评估师将在非常简单的情况下工作,例如:
evaluate(A*B, Binding, Value) :-
evaluate(A, Binding, AValue),
evaluate(B, Binding, BValue),
Value is AValue * BValue.
evaluate(A+B, Binding, Value) :-
evaluate(A, Binding, AValue),
evaluate(B, Binding, BValue),
Value is AValue + BValue.
现在,您在这里遇到了一些麻烦,要正确处理会很烦人,这就是您要在此处执行的是对 partial 进行某种评估。有多个变量时的表达式。讨厌的例子是这样的:
?- evaluate(2*(5+x*x), x=2, E).
E = 18
您真的希望它返回?- evaluate(x*(3+y*y), y=3, E).
false.
。现在,玩具评估器有两个问题正在阻止这种情况。首先是,如果您正在寻找变量,并且不具有绑定,则不知道该怎么办,可以通过更改基本情况来解决:
x*12
这将立即导致一些错误:
evaluate(Var, X=Value, Result) :-
atom(Var),
( Var = X ->
Result = Value
;
Result = Var
)
问题是ERROR: Arithmetic: `x/0' is not a function
ERROR: In:
ERROR: [9] _3344 is x*3
ERROR: [7] <user>
ERROR:
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.
要求右边的表达式除数字和运算符外不包含任何其他内容;它永远不会为您提供一棵树。我们可以尝试这样解决这个问题:
is/2
乍一看似乎可行:
evaluate(A*B, Binding, Value) :-
evaluate(A, Binding, AValue),
evaluate(B, Binding, BValue),
(number(AValue), number(BValue) ->
Value is AValue * BValue
;
Value = AValue * BValue
).
evaluate(A+B, Binding, Value) :-
evaluate(A, Binding, AValue),
evaluate(B, Binding, BValue),
(number(AValue), number(BValue) ->
Value is AValue + BValue
;
Value = AValue + BValue
).
但是,您将能够找到许多未发生代数运算的情况,这些情况会融合更多的常量:
?- evaluate(x*(3+y*y), y=3, E).
E = x*12 ;
false.
左常量因子不会与右常量因子相乘,因为这里我们没有任何树重排代码。正确的常数因子由于使用?- evaluate(3*3*x*3*3, y=3, E).
E = 9*x*3*3 ;
可以更清楚地说明原因而未能合并:
write_canonical/1
您可能会由此猜测,最里面的常数被折叠在一起产生9 * x,然后我们尝试将其乘以三。由于?- write_canonical(3*3*x*3*3).
*(*(*(*(3,3),x),3),3)
不是数字,因此不会与9*x
一起折叠。现在,您在左侧有一个树桩,它也不会与下一个*3
一起折叠。
以临时方式在这里解决所有问题将是令人不快的,但如果需要的话,您可以这样做。老实说,我不知道如何建立一个可以处理这些问题的合理完整的代数系统。我怀疑您需要比解析树更有效的数据结构,但是除此之外,我什么都不知道。无论如何,我希望这会有所帮助。
答案 1 :(得分:1)
这需要更多上下文。看来, real 目标是解析“函数”(带变量的算术表达式?)并将其简化。
Prolog免费为您提供大部分解析,这意味着2*x + 3
之类的表达式也是有效的Prolog术语,甚至具有您期望的解析树:
$ swipl
Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.3-31-g32d2d0a1d)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
For online help and background, visit http://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?- T = 2*x + 3*y, display(T).
+(*(2,x),*(3,y))
T = 2*x+3*y.
所以现在您需要弄清楚两件事:
第二点有潜力为您提供最多的工作。您现在似乎遇到的问题相对容易,但是您需要使用其他方法。您只需要遍历树并替换所有出现的“变量”(第二个参数中的值)和一个值(第三个参数中的值)。然后,您仍然必须简化。
要了解如何替换,可以尝试阅读“ Prolog的艺术”第3章“递归编程”。在第70-80页左右,甚至可以找到几乎可以使用的示例程序。也有一个完整的示例程序可以执行派生。这不是您所需要的,但是这种方法非常接近您可能需要的。
还有一个警告:当您在Prolog语境中说“功能”或“变量”时,对于Prolog思维方式的人来说,它们可能意味着不同的事情,因此您将彼此交谈一段时间。如果您可以将问题用较为正式的语言表达,则可能会更容易帮助您。