1 % b_arithmetic_expressions.pl
2 % returns for arithmetic expressions a symbolic value that can be called in CLP(FD)
3
4 % :- use_module(kernel_waitflags,[add_error_wf/5]). included in b_interpreter
5
6 b_compute_arith_expression(b(Expr,Type,Info),LS,S,R,WF) :- !,
7 (ground(Type), Type == integer -> true
8 ; ajoin(['Integer arithmetic expression has illegal type ',Type,': '],Msg),
9 add_error_wf(b_compute_arith_expression,Msg,b(Expr,Type,Info),Info,WF)
10 ),
11 b_compute_arith_expression2(Expr,Info,LS,S,R,WF).
12
13 b_compute_arith_expression(Expr,LS,S,R,WF) :-
14 add_error_wf(b_compute_arith_expression,'Expression not properly wrapped: ',Expr,Expr,WF),
15 b_compute_arith_expression2(Expr,unknown,LS,S,R,WF).
16
17
18 b_compute_arith_expression2(unary_minus(Arg1),_I,LocalState,State,Value,WF) :- !,
19 b_compute_arith_expression(Arg1,LocalState,State,SV1,WF),
20 Value = '-'(SV1).
21 b_compute_arith_expression2(add(Arg1,Arg2),_I,LocalState,State,Value,WF) :- !,
22 b_compute_arith_expression(Arg1,LocalState,State,SV1,WF),
23 b_compute_arith_expression(Arg2,LocalState,State,SV2,WF),
24 Value = '+'(SV1,SV2).
25 b_compute_arith_expression2(minus(Arg1,Arg2),_I,LocalState,State,Value,WF) :- !,
26 b_compute_arith_expression(Arg1,LocalState,State,SV1,WF),
27 b_compute_arith_expression(Arg2,LocalState,State,SV2,WF),
28 Value = '-'(SV1,SV2).
29 b_compute_arith_expression2(multiplication(Arg1,Arg2),_I,LocalState,State,Value,WF) :- !,
30 b_compute_arith_expression(Arg1,LocalState,State,SV1,WF),
31 b_compute_arith_expression(Arg2,LocalState,State,SV2,WF),
32 Value = '*'(SV1,SV2).
33 b_compute_arith_expression2(external_function_call(XFUN,[Arg1]),_Info,LocalState,State,Value,WF) :-
34 unary_external_function_to_clpfd(XFUN,SV1,ClpfdExpr),!,
35 b_compute_arith_expression(Arg1,LocalState,State,SV1,WF),
36 Value = ClpfdExpr.
37 b_compute_arith_expression2(Expr,Info,LocalState,State,Value,WF) :-
38 b_compute_expression2(Expr,integer,Info,LocalState,State,int(Value),WF).
39 %b_compute_expression2(Expr,integer,Info,LocalState,State,R,WF), R=int(Value). % this version does not seem faster
40 % kernel_objects:basic_type2(integer,int(Value)).
41
42 unary_external_function_to_clpfd('ABS',Arg1,abs(Arg1)).
43 % TO DO: floor/ceiling/...
44
45
46 % Note: calling b_compute_arith_expression will also instantiate a variable to at least the int(_) skeleton; thereby enabling propagation
47 % this is potentially better than calling the default versions of the predicates, which may wait until the int(_) skeleton is set up before propagation
48
49
50 :- use_module(clpfd_interface,[clpfd_eq_expr_optimized/2]).
51
52 b_test_arith_equal_boolean_expression(Arg1,Arg2,LocalState,State,WF) :-
53 b_compute_arith_expression(Arg1,LocalState,State,CLPFD_Expr1,WF),
54 b_compute_arith_expression(Arg2,LocalState,State,CLPFD_Expr2,WF),
55 clpfd_eq_expr_optimized(CLPFD_Expr1,CLPFD_Expr2).
56
57 %(preferences:preference(use_smt_mode,true)-> clpfd_eq_expr_optimized(CLPFD_Expr1,CLPFD_Expr2)
58 % ; clpfd_eq_expr(CLPFD_Expr1,CLPFD_Expr2)).
59 % maybe we should call clpfd_eq_expr_optimized only in SMT mode and call clpfd_eq_expr otherwise ??
60 % initially test 1077 ran considerably slower with clpfd_eq_expr_optimized
61
62 % ------------------------------------
63 % Now similar code for reals
64 % ------------------------------------
65
66 % should only be used when kernel_reals:use_clpfd_real_solver is true
67 % and when kernel_reals:do_not_double_check_solution is true
68 % Note: we could add double checking to the code below,
69 % but SICStus Prolog itself leaves uninstantiated intermediate variables (see SPRM-21557)
70
71 b_compute_real_arith_expression(b(Expr,Type,Info),LS,S,R,WF) :- !,
72 (ground(Type), Type == real -> true
73 ; ajoin(['Real arithmetic expression has illegal type ',Type,': '],Msg),
74 add_error_wf(b_compute_arith_expression,Msg,b(Expr,Type,Info),Info,WF)
75 ),
76 b_compute_real_arith_expression2(Expr,Info,LS,S,R,WF).
77
78 b_compute_real_arith_expression2(unary_minus_real(Arg1),_I,LocalState,State,Value,WF) :- !,
79 b_compute_real_arith_expression(Arg1,LocalState,State,SV1,WF),
80 Value = '-'(SV1).
81 b_compute_real_arith_expression2(add_real(Arg1,Arg2),_I,LocalState,State,Value,WF) :- !,
82 b_compute_real_arith_expression(Arg1,LocalState,State,SV1,WF),
83 b_compute_real_arith_expression(Arg2,LocalState,State,SV2,WF),
84 Value = '+'(SV1,SV2).
85 b_compute_real_arith_expression2(minus_real(Arg1,Arg2),_I,LocalState,State,Value,WF) :- !,
86 b_compute_real_arith_expression(Arg1,LocalState,State,SV1,WF),
87 b_compute_real_arith_expression(Arg2,LocalState,State,SV2,WF),
88 Value = '-'(SV1,SV2).
89 b_compute_real_arith_expression2(multiplication_real(Arg1,Arg2),_I,LocalState,State,Value,WF) :- !,
90 b_compute_real_arith_expression(Arg1,LocalState,State,SV1,WF),
91 b_compute_real_arith_expression(Arg2,LocalState,State,SV2,WF),
92 Value = '*'(SV1,SV2).
93 b_compute_real_arith_expression2(power_of_real(Arg1,Arg2),_I,LocalState,State,Value,WF) :- !,
94 b_compute_real_arith_expression(Arg1,LocalState,State,SV1,WF),
95 b_compute_real_arith_expression(Arg2,LocalState,State,SV2,WF), % integer value but converted to real
96 Value = '^'(SV1,SV2).
97 b_compute_real_arith_expression2(external_function_call(XFUN,[Arg1]),_Info,LocalState,State,Value,WF) :-
98 unary_external_function_to_clpfd_real(XFUN,SV1,ClpfdExpr),!,
99 b_compute_real_arith_expression(Arg1,LocalState,State,SV1,WF),
100 Value = ClpfdExpr.
101 b_compute_real_arith_expression2(Expr,Info,LocalState,State,Value,WF) :-
102 b_compute_expression2(Expr,real,Info,LocalState,State,BValue,WF),
103 is_real(BValue,Value).
104
105 unary_external_function_to_clpfd_real('RABS',Arg1,abs(Arg1)).
106 % TODO: convert_real(.)
107
108 :- use_module(kernel_reals,[post_real_equal_expr_wf/4]).
109 b_test_real_arith_equal_boolean_expression(Arg1,Arg2,Info,LocalState,State,WF) :-
110 b_compute_real_arith_expression(Arg1,LocalState,State,CLPFD_Expr1,WF),
111 b_compute_real_arith_expression(Arg2,LocalState,State,CLPFD_Expr2,WF),
112 %write(post_eq(CLPFD_Expr1,CLPFD_Expr2)),nl,
113 post_real_equal_expr_wf(CLPFD_Expr1,CLPFD_Expr2,Info,WF).
114