1%----------------------------------------------------------------------
2% BEGIN LICENSE BLOCK
3% Version: CMPL 1.1
4%
5% The contents of this file are subject to the Cisco-style Mozilla Public
6% License Version 1.1 (the "License"); you may not use this file except
7% in compliance with the License.  You may obtain a copy of the License
8% at www.eclipse-clp.org/license.
9% 
10% Software distributed under the License is distributed on an "AS IS"
11% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
12% the License for the specific language governing rights and limitations
13% under the License. 
14% 
15% The Original Code is  The Zinc Modelling Interface for ECLiPSe
16% The Initial Developer of the Original Code is  Joachim Schimpf
17% Portions created by the Initial Developer are
18% Copyright (C) 2007 Cisco Systems, Inc.  All Rights Reserved.
19% 
20% Contributor(s): Joachim Schimpf
21% 
22% END LICENSE BLOCK
23%----------------------------------------------------------------------
24
25:- module(fzn_eplex).
26
27:- comment(categories, ["Interfacing","Constraints"]).
28:- comment(summary, "Mapping from FlatZinc to lib(eplex)").
29:- comment(author, "Joachim Schimpf, supported by Cisco Systems and NICTA Victoria").
30:- comment(copyright, "Cisco Systems Inc, licensed under CMPL").
31:- comment(date, "$Date: 2009/07/16 09:11:24 $").
32:- comment(see_also, [library(flatzinc),library(eplex)]).
33:- comment(desc, html("
34This module defines a mapping from FlatZinc operations to lib(eplex)
35and is intended to be used in conjunction with lib(flatzinc).
36</P><P>
37TODO:	Add a mapping for sets as array of booleans.
38Add an appropriate globals.mzn.
39<P>
40")).
41
42
43% Lazy person's way of exporting (almost) all locally defined predicates:
44:- local initialization(
45    (
46	current_module_predicate(local, Pred),
47	get_flag(Pred, auxiliary, off),
48	nonmember(Pred, [eplex_opt/3, vector_sum/3]),
49	export(Pred),
50	fail
51    ;
52	true
53    )).
54
55:- lib(eplex).			% the actual solver library
56
57:- import
58	fzn_write/2,
59	fzn_error/2
60    from flatzinc.
61
62
63% Declarations -----------------------------------------------
64
65% Single variable declarations
66bool_declare(X) :- X $:: 0..1, integers(X).
67int_declare(X) :- integers(X).
68float_declare(X) :- reals([X]).
69int_declare(X, Min, Max) :- X $:: Min..Max, integers(X).
70float_declare(X, Min, Max) :- X $:: Min..Max.
71
72% Variable array declarations
73% Unfortunately not all primitives can handle arrays
74bool_declare_array(Xs) :- ( foreacharg(X,Xs) do X $:: 0..1, integers(X) ).
75int_declare_array(Xs) :- ( foreacharg(X,Xs) do integers(X) ).
76float_declare_array(Xs) :- ( foreacharg(X,Xs) do reals(X) ).
77int_declare_array(Xs, Min, Max) :-
78	( foreacharg(X,Xs), param(Min,Max) do X $:: Min..Max, integers(X) ).
79float_declare_array(Xs, Min, Max) :- 
80	( foreacharg(X,Xs), param(Min,Max) do X $:: Min..Max ).
81
82
83% Comparisons -----------------------------------------------
84
85% int_??(var int, var int)
86int_eq(X, Y) :- X $= Y.
87int_le(X, Y) :- X $=< Y.
88int_ge(X, Y) :- X $>= Y.
89
90% float_??(var float, var float)
91float_eq(X, Y) :- X $= Y.
92float_le(X, Y) :- X $=< Y.
93float_ge(X, Y) :- X $>= Y.
94
95% bool_??(var bool, var bool)
96bool_eq(X, Y) :- X $= Y.
97bool_le(X, Y) :- X $=< Y.
98bool_ge(X, Y) :- X $>= Y.
99
100
101% int_lin_??(array[int] of int, array[int] of var int, int)
102int_lin_eq(Cs, Xs, Rhs) :- vector_sum(Cs, Xs, CXs), sum(CXs) $= Rhs.
103int_lin_le(Cs, Xs, Rhs) :- vector_sum(Cs, Xs, CXs), sum(CXs) $=< Rhs.
104int_lin_ge(Cs, Xs, Rhs) :- vector_sum(Cs, Xs, CXs), sum(CXs) $>= Rhs.
105
106% float_lin_??(array[int] of float, array[int] of var float, float)
107float_lin_eq(Cs, Xs, Rhs) :- vector_sum(Cs, Xs, CXs), sum(CXs) $= Rhs.
108float_lin_le(Cs, Xs, Rhs) :- vector_sum(Cs, Xs, CXs), sum(CXs) $=< Rhs.
109float_lin_ge(Cs, Xs, Rhs) :- vector_sum(Cs, Xs, CXs), sum(CXs) $>= Rhs.
110
111    vector_sum(Cs, Xs, CXs) :-
112	arity(Cs, N),
113	( arity(Xs, N) ->
114	    ( for(I,1,N), foreach(C*X,CXs), param(Cs,Xs) do
115		arg(I, Cs, C), arg(I, Xs, X)
116	    )
117	;
118	    fzn_error("Mismatched vector product %w %w", [Cs, Xs])
119	).
120
121
122% Arithmetic operations -----------------------------------------------
123
124% int_???(var int, var int, var int)
125int_negate(X, Z) :- Z $= -X.
126int_plus(X, Y, Z) :- Z $= X+Y.
127int_minus(X, Y, Z) :- Z $= X-Y.
128
129% float_???(var float, var float, var float)
130float_negate(X, Z) :- Z $= -X.
131float_plus(X, Y, Z) :- Z $= X+Y.
132float_minus(X, Y, Z) :- Z $= X-Y.
133
134
135% Logical operations -----------------------------------------------
136
137
138% Set operations -----------------------------------------------
139
140
141% Array operations -----------------------------------------------
142
143
144% Coercion operations -----------------------------------------------
145
146int2float(I, F) :- ( var(I) -> F=I ; F is float(I) ).
147bool2int(X, X).
148
149
150% FZN data <-> ECLiPSe data -----------------------------------------------
151
152bool_fzn_to_solver(false, 0).
153bool_fzn_to_solver(true, 1).
154
155bool_solver_to_fzn(0, false).
156bool_solver_to_fzn(1, true).
157
158% model floats are just solver floats
159float_fzn_to_solver(X, X) :- float(X).
160
161float_solver_to_fzn(X, X) :- real(X).
162
163% Set constants are ordered lists (pars only)
164set_fzn_to_solver(List, Set) :-
165	sort(List, Set).
166
167set_solver_to_fzn(List, List) :- is_list(List).
168
169% Set constants are ordered lists (pars only)
170range_fzn_to_solver(Min, Max, Set) :-
171	( for(I,Min,Max), foreach(I,Set) do true ).
172
173
174% Search -----------------------------------------------
175
176satisfy(Anns) :-
177	eplex_opt(min(0), Anns, _Cost).
178
179minimize(Expr, Anns, Cost) :-
180	eplex_opt(min(Expr), Anns, Cost).
181
182maximize(Expr, Anns, Cost) :-
183	eplex_opt(max(Expr), Anns, Cost).
184
185    eplex_opt(Obj, _Anns, Cost) :-
186	eplex_solver_setup(Obj),
187	eplex_solve(Cost),
188	eplex_get(vars, Vars),
189	eplex_get(typed_solution, Vals),
190	eplex_cleanup,
191	Vars=Vals.
192
193