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 Cardinal Constraint Solver for ECLiPSe.
16% The Initial Developer of the Original Code is  Francisco M.C.A. Azevedo.
17% Portions created by the Initial Developer are  Copyright (C) 2000-2004.
18% All Rights Reserved.
19%
20% Contributor(s): Francisco M. C. A. Azevedo <fa@di.fct.unl.pt>.
21%
22% Alternatively, the contents of this file may be used under the terms of
23% either of the GNU General Public License Version 2 or later (the "GPL"),
24% or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
25% in which case the provisions of the GPL or the LGPL are applicable instead
26% of those above. If you wish to allow use of your version of this file only
27% under the terms of either the GPL or the LGPL, and not to allow others to
28% use your version of this file under the terms of the MPL, indicate your
29% decision by deleting the provisions above and replace them with the notice
30% and other provisions required by the GPL or the LGPL. If you do not delete
31% the provisions above, a recipient may use your version of this file under
32% the terms of any one of the MPL, the GPL or the LGPL.
33% END LICENSE BLOCK
34%
35% cardinal_functions.pl      By Francisco Azevedo    2000 - 2004
36%
37% Set optional functions of Cardinal.
38%
39%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
40
41:- [cardinal_union,cardinal_minmax].
42
43
44%--------
45% cardinality_function(+Card, +Set)
46%  Inferences for Set's cardinality function.
47%--
48cardinality_function(Card, Set):-
49	domain(Set, [_:NIn,_:NMax]),
50	(var(Card) -> Card::NIn..NMax,
51		set_cardinality(Set, Card),
52		check_cardinality(Card, Set)
53	;CardVar::Card, CardVar::NIn..NMax,
54	 set_cardinality(Set, CardVar),
55	 check_cardinality(CardVar, Set)
56	).
57
58%--------
59% check_cardinality(+Cardinality, ?Set)
60%  Suspend until Cardinality of Set is ground. Then, if it is equal to
61% the cardinality of one of its bounds, assign Set to that bound.
62% Else suspend until Set further constrained.
63%--
64check_cardinality(C, S):- var(C), !, suspend(check_cardinality(C,S), 2, C->inst).
65check_cardinality(C, S):-
66	domain(S, C, [Glb:NIn,Poss:NMax]),
67	(C==NIn -> S=Glb
68	;C==NMax -> lub(Glb, Poss, Lub), S=Lub
69	;suspend(check_cardinality(C,S), 2, S->cardinal:bounded)
70	).
71
72
73%--------
74% check_ground_functions(+Functions, +Set)
75%  Check if each of the optional Functions agrees with ground Set.
76%--
77check_ground_functions(Functions, Set):-
78	(member_remove(Functions, cardinality:Card, Fs1) ->
79		length(Set, C),
80		(Card=C ; member(M,Card), (M=C ; M=A..B,number(A),number(B),C>=A,C=<B)), !
81	;Fs1=Functions
82	),
83	(member_remove(Fs1, minimum:Min, Fs2) -> Set=[Min|_] ; Fs2=Fs1),
84	(member_remove(Fs2, maximum:Max, Fs3) -> reverse(Set, [Max|_]) ; Fs3=Fs2),
85	(member_remove(Fs3, union:Union, _) ->
86		(var(Union) -> all_sets_union(Set, [],U), U=Union
87		;Union=GlbU+PossU -> verify_inclusion(Set,GlbU,PossU,[])
88		;all_sets_union(Set, [],Union)
89		)
90	;true
91	).
92
93%--------
94% check_functions(+Functions, +SetVar)
95%  Check if each optional function is in Functions to update SetVar's functions
96% and domain attributes.
97%--
98check_functions(Functions, SetVar):-
99	(member_remove(Functions,cardinality:Card,Fs1) -> true ; Fs1=Functions),
100	cardinality_function(Card, SetVar),
101	(member_remove(Fs1, minimum:Min, Fs2) -> minimum_function(Min,SetVar) ; Fs2=Fs1),
102	(member_remove(Fs2, maximum:Max, Fs3) -> maximum_function(Max,SetVar) ; Fs3=Fs2),
103	(member_remove(Fs3, union:Union, _) -> union_function(Union,SetVar) ; true).
104
105%--------
106% check_new_functions(+Functions, +SetVar)
107%  Check if each optional function is in (new) Functions, to update SetVar's functions
108% and domain attributes.
109%--
110check_new_functions(Functions, S):-
111	(member_remove(Functions, cardinality:Card, Fs1) ->
112		cardinality(S, C1),
113		(ground(Card), is_list(Card) -> C1::Card ; C1#=Card)
114	;Fs1=Functions
115	),
116	(member_remove(Fs1, minimum:Min, Fs2) ->
117		minimum(S, MinS),
118		(is_domain(MinS) -> (is_domain(Min) -> MinS=Min ; MinS::Min)
119		;minimum_function(Min,S)
120		)
121	;Fs2=Fs1
122	),
123	(member_remove(Fs2, maximum:Max, Fs3) ->
124		maximum(S, MaxS),
125		(is_domain(MaxS) -> (is_domain(Min) -> MaxS=Max ; MaxS::Max)
126		;maximum_function(Max,S)
127		)
128	;Fs3=Fs2
129	),
130	(member_remove(Fs3, union:Union, _) ->
131		union_att(S, U),
132		(var(U) -> union_function(Union, S)
133		;var(Union) -> U=[Union|_]
134		;Union=GlbUVar+PossUVar ->
135			sort(GlbUVar,SGlbUVar), sort(PossUVar,SPossUVar),
136			U=[SVar|_],
137			contains(SVar, SGlbUVar),
138			lub(SGlbUVar, SPossUVar, LubUVar),
139			contains(LubUVar, SVar)
140		;is_list(Union), sort(Union,SUnion), U=[SUnion|_]
141		)
142	;true
143	).
144
145