[gecode-users] Help: Howto combine sets and value constraints?

Holger Winnemoeller holger.winnemoeller at gmail.com
Tue Dec 15 02:01:19 CET 2009


I am trying to create a solver that (as a toy explanation) can create sets
with
certain properties, such as:

1) The resulting set size is specified
2) The resulting set contains a certain number of items that belong to a
  "special" group
3) The total "weight" of items is below a certain threshold

I can easily enough create constraints for 1) and 2), but I would love to
get
some help in how I integrate constraint 3) into the mix. Supposedly I would
create a set of variables for the weights and specify a constraint on the
sum of
these weights. But I have no idea about how to express in Gecode that I want
to
sum up the weights of exactly the ids that are in the currently selected
set.

My approach to doing 1)&2) is attached below. The question is: How do I
specify
that the total weight of selected items should be less than, say
"maxWeight".

(Note: This is not a homework problem :-) It's an abstraction of a set
selector
that I want to include in a user interface for suggesting available sets to
users)

Thanks for your time,
Holger.
========================< main.cpp >===========================
#include <gecode/set.hh>
#include <gecode/support.hh>
#include <gecode/kernel.hh>
#include <gecode/search.hh>

using namespace Gecode;

// Some data to play with
int numItems = 10;                    // total number of items in inventory
int numSpecialItems = 4;            // number of items in inventory with
"special" attribute
int numRequestedSize = 6;            // requested size of result set
int numRequestedSpecialSize = 2;    // requested size of "special" items in
result set
float maxWeight = 1.8f;                // requested maximum weight of all
items in result set (NOT IMPLEMENTED!)

int allItems[] = {0,1,2,3,4,5,6,7,8,9}; // 10 items (their id's)
float itemWeights[] = {0.1f, 0.5f, 0.2f, 0.2f, 0.6f, 0.8f, 1.0f, 0.3f, 0.7f,
0.6f}; // their associated weights
int specialItems[] = {2,5,8,9}; // a subset of items having the attribute
"special"

// Little helper function
bool isInSet(int id, int set[], int setSize)
{
    for(int i=0; i<setSize; ++i)
        if(id == set[i]) return true;
    return false;
}

// A "Minimal" space definition for the problem
class MiniSpace: public Space
{
        SetVarArray mSetStore;
public:
    MiniSpace(){
        // Create a SetVariable array (only need one element really, but
this allows me to define the domain in one step)
        mSetStore = SetVarArray(*this, 1, IntSet::empty, 0, numItems);
        SetVar resultSet = mSetStore[0]; // get the one variable that was
defined in the above line

        // impose the constraint that we only want "numRequestedSize" items
in the result set
        cardinality(*this, resultSet, numRequestedSize, numRequestedSize);

        // now impose the fact that we want exactly
"numRequestedSpecialSize" items coming from the special set
        // 1.) Create a new set domain that represents the "special" items
        IntSet specialSet(specialItems, numSpecialItems);
        // 2.) Create a set variable that we'll associate with that set
later on
        SetVar specialSelected(*this);
        // 3.) Set "specialSelected" to the intersection of whatever a
possible solution is, and
        //     the "specialSet". This ensures that we can talk about items
that are included
        //     in the solution, but also belong to the special set
        rel(*this, resultSet, SOT_INTER, specialSet, SRT_EQ,
specialSelected);
        // 4.) Now ensure that we only have "numRequestedSpecialSize" of
these overlapping items
        cardinality(*this, specialSelected, numRequestedSpecialSize,
numRequestedSpecialSize);

        // Given these constraints, branch
        branch(*this, mSetStore, SET_VAR_NONE, SET_VAL_MIN_INC);
    }
    MiniSpace(bool share, MiniSpace& s) : Space(share, s)
{mSetStore.update(*this, share, s.mSetStore);}
    virtual Space* copy(bool share) {return new MiniSpace(share, *this);}
    void print() const
    {
        int countAsSpecial = 0;
        for(SetVarGlbValues d(mSetStore[0]);d();++d)
        {
            int id = d.val();
            if(isInSet(id, specialItems, numSpecialItems)) countAsSpecial++;
            std::cout << id << " ";
        } // for
        std::cout << ". Nr. of specials: " << countAsSpecial;
    }
};

int main(int argc, char* argv[])
{
    // Run the problem
    MiniSpace problem; // space instance
    //Search::Options options
    DFS<MiniSpace> solver (&problem);
    int count=0;
    while(true){
        MiniSpace* solution = solver.next();
        if(!solution) break;
        std::cout << "Solution Nr." << count++ << std::endl;
        solution->print();
        std::cout << std::endl;
        delete solution;
    }
    std::cout << "Done..." << std::endl;
    return 0;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.gecode.org/pipermail/users/attachments/20091214/4c6293a9/attachment-0001.htm>


More information about the users mailing list