Re: [eclipse-clp-users] Using sets ... generating two sets and their sums

From: Joachim Schimpf <jschimpf_at_coninfer.com>
Date: Tue, 06 Dec 2011 03:58:57 +0100
Claudio Cesar de Sá wrote:
> Hi
> 
> Thanks for the helping, really, the problem are the libraries.
> Now the code works, but I need a sum or weight of a set.  The weight 
> predicate has an array as second argument, how to set it for 
> any/arbitrary set? I want just a  elements' sum of a set.
 > Look my newest code:
> 
> Thanks once
> 
> claudio
> 
> :-lib(fd). 
> :-lib(fd_sets).
> %%:-lib(branch_and_bound).
> 
> 
> %% data
> veloc(1,[61,66,63,69]).
> veloc(4,[12,122,18,1,9,7]).
> 
> go :-
>      veloc(1,L1), model(L1).
>      %%veloc(4,L4), model(L4).
>           
> model(L) :-     
>       length(L,N), writeln( n: N), writeln( l: L),
>       sort(L, Dominio),
>       writeln( dom: Dominio),
> 
>       find_2_others(N, N1, N2),
>     
>       writeln( n1: N1) ,
>       writeln( n2: N2) ,
>       Weights = [](1, 1),
> 
>        fd_sets:(L1 :: [] .. Dominio),
>        fd_sets:(L2 :: [] .. Dominio),
>        fd_sets:(L3 :: [] .. Dominio),
>       
>      #(L1, N1),
>      #(L2, N2),
>      #(L3, N),
> 
> %%%%  HOW TO WORKs?
> %%%%  weight(L1, Weights, W),).
> 
>      %% I need for THESE TWO CONSTRAINTS
>      %%sum(L) #= (sum(L1) + sum(L2)),
>      %%(Diff #= abs( sum(L1) - sum(L2) )),
> 
>      fd_sets:(union(L1, L2, L3)),
>      label_sets([L1, L2]),
>      write('Solutions: ........'), nl,
>      writeln( solL1: L1) ,
>      writeln( solL2: L2).
>     
>  
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
> label_sets([]).
>     label_sets([S|Ss]) :-
>     insetdomain(S,_,_,_),
>     %%%Instantiate Set to a possible value
>     label_sets(Ss).
> 
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
>  find_2_others(N,N1,N2):-
>      Int is (N // 2),
>      Rem is rem(N,2),
>      N1 is Int,
>      N2 is (Int + Rem).
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


The idea of the fd_sets/ic_sets libraries is that set elements
are identified by consecutive integers 1..N, and weights are
kept separately in arrays (that way, every element can have more
than one kind of weight, e.g. weight and volume).

So instead of having a set domain of [61,66,63,69], you should
model with a set domain of [1,2,3,4] and have a separate array
[](61,66,63,69) which indicates that element 1 weighs 61,
element 3 weighs 63, etc.

Using this idea, you probably want something like this:

go :-
         Weights = [](61,66,63,69),
         model(Weights, Sets, Diff),
         label_sets(Sets),
         writeln(sets=Sets;diff=Diff).

model(Weights, Sets, Diff) :-
         arity(Weights, N),
         N1 is N//2,
         N2 is N-N1,

         Sets = [L1,L2,L3],
         intsets(Sets, _, 1, N),   % shorthand for :: []..[1,2,...,N]

         #(L1, N1),
         #(L2, N2),
         #(L3, N),

         weight(L1, Weights, W1),
         weight(L2, Weights, W2),
         weight(L3, Weights, W3),

         W3 #= W1+W2,
         Diff #= abs(W1-W2),

         fd_sets:union(L1, L2, L3).

This will compute _all_ solutions that satisfy the constraints.

My guess is that you want to minimize the difference between the
weights of set L1 and L2.  You do that by simply replacing the line

         label_sets(Sets)

by

         minimize(label_sets(Sets), Diff)


-- Joachim
Received on Tue Dec 06 2011 - 03:00:05 CET

This archive was generated by hypermail 2.2.0 : Thu Feb 02 2012 - 02:31:58 CET