I am very new to constraint programming, but by using the MPG have been
able to develop a fairly large Gecode application in a relatively
short period of time. Due to my lack of constraint programming
knowledge, I may not have selected the best methods for solving
my particular problem, but what I have done appears to work
with two exceptions which are shown in the attached program.
This program is the minimum program I could generate to show
what I am doing and to replicate my two problems.

In the attached program, I have an IntVar X which is to
receive ordered values from Y0, Y1, and Y2 along with an
indication of from which Y the value came.

The first problem I am having is that the program stops
after finding 6 of the 10 possible solutions and I don't
understand how to debug this problem.

The second problem I am having is that the program fails
to find any solutions if the constraints on one of the
Y variables results in it not having any solutions even
though there are other solutions for X.

I have this problem with both the 3.7.3 release and the
4.0.0 release.

I would appreciate any assistance you can provide.

Thanks,
Dean

#include <gecode/int.hh>
#include <gecode/search.hh>
#include <gecode/minimodel.hh>

using namespace Gecode;

typedef struct Y_s
{
        IntVar nY;
} Y;

class GecodeTest3 : public Space {
protected:
        int m_nMin;
        int m_nMax;
        int m_nNumY;
        IntVar m_nX;
        IntVarArray m_naX;
        BoolVarArray m_baX;
        int m_nYIndex;
        IntVar m_nY0;
        IntVar m_nY1;
        IntVar m_nY2;
        IntVar *m_vY[3];
        IntVar m_nCost;
        IntVarArray m_nValue;
        IntArgs m_nC;

public:
        void AddY(int* naY, int nSize)
        {
                m_nYIndex++;
                *m_vY[m_nYIndex] = IntVar(*this, m_nMin, m_nMax);
                ConstrainY(naY, nSize);
                rel(*this, m_naX[m_nYIndex] == *m_vY[m_nYIndex]);
                rel(*this, m_baX[m_nYIndex] == (m_naX[m_nYIndex] == m_nX));
                branch(*this, *m_vY[m_nYIndex], INT_VAL_MIN());
        }

        void ConstrainY(int *naY, int nSize)
        {
                IntArgs nTemp;
                for (int i = 0; i < nSize; i++)
                {
                        nTemp << naY[i];
                }
                IntSet nsTemp(nTemp);
                dom(*this, *m_vY[m_nYIndex], nsTemp);
        }

        int GetX(void)
        {
                return m_nX.val();
        }

        int GetWhichY(void)
        {
                return m_nValue[0].val();
        }

        int GetCost(void)
        {
                return m_nCost.val();
        }

        GecodeTest3(int nMin, int nMax, int nNumY) :
        m_nMin(nMin), m_nMax(nMax), m_nNumY(nNumY), m_nYIndex(-1)
        {
                if (m_nMin < 0)
                {
                        std::cout << "m_nMin must not be negative" << std::endl;
                }
                m_vY[0] = &m_nY0;
                m_vY[1] = &m_nY1;
                m_vY[2] = &m_nY2;
                m_nX = IntVar(*this, m_nMin, m_nMax);
                m_naX = IntVarArray(*this, m_nNumY, m_nMin, m_nMax);
                m_baX = BoolVarArray(*this, m_nNumY, 0, 1);
                m_nC << 1;
                m_nC << m_nNumY;
                int nTemp =  m_nNumY * m_nMax + m_nNumY;
                m_nCost = IntVar(*this, 0, nTemp);
                nTemp = m_nMax > nNumY ? m_nMax : nNumY;
                m_nValue = IntVarArray(*this, 2, 0, nTemp);
                rel(*this, m_nX == min(m_naX));
                element(*this, m_baX, m_nValue[0], 1);
                rel(*this, m_nValue[1] == m_nX);
                linear(*this, m_nC, m_nValue, IRT_EQ, m_nCost);
                branch(*this, m_naX, INT_VAR_MIN_MIN(), INT_VAL_MIN());
                branch(*this, m_nX, INT_VAL_MIN());
                branch(*this, m_nValue[0], INT_VAL_MIN());
        }
        // search support
        GecodeTest3(bool share, GecodeTest3& s) : Space(share, s) {
                // s.print(std::cout);
                m_vY[0] = &m_nY0;
                m_vY[1] = &m_nY1;
                m_vY[2] = &m_nY2;
                m_nX.update(*this, share, s.m_nX);
                m_naX.update(*this, share, s.m_naX);
                m_baX.update(*this, share, s.m_baX);
                m_nCost.update(*this, share, s.m_nCost);
                m_nY0.update(*this, share, s.m_nY0);
                m_nY1.update(*this, share, s.m_nY1);
                m_nY2.update(*this, share, s.m_nY2);
                m_nValue.update(*this, share, s.m_nValue);
                for (int i = 0; i < 2; i++)
                {
                        m_nC << s.m_nC[i];
                }
        }
        virtual Space* copy(bool share) {
                return new GecodeTest3(share,*this);
        }
        virtual void constrain(const Space& _b)
        {
                const GecodeTest3& b = static_cast<const GecodeTest3&>(_b);
                rel(*this, m_nCost > b.m_nCost);
        }

        // print solution
        void print(std::ostream& os) const {
                os << "m_nX:         " << m_nX << std::endl;
                for (int i = 0;  i < m_naX.size(); i++)
                {
                        os << "m_naX[" << i << "]:   " << m_naX[i] << "   ";
              os << "m_baX[" << i << "]:   " << m_baX[i] << "   ";
                        os << std::endl;
                }
                for (int i = 0; i < m_nC.size(); i++)
                {
                        os << "m_nC[" << i << "]:  " << m_nC[i] << std::endl;
                }
                for (int i = 0; i < m_nValue.size(); i++)
                {
                        os << "m_nValue[" << i << "]:  " << m_nValue[i] << 
std::endl;
                }
                os << "m_nCost:  " << m_nCost << std::endl;
        }
};

void BuildAndSolve(bool b2Y1)
{
        int Y0[3] = {1, 3, 7};
        int Y1[3] = {2, 4, 5};
        int Y2[4] = {4, 6, 8, 9};
        int Y1a[3] = {1, 3, 8};

        // create model and search engine
        GecodeTest3 *m = new GecodeTest3(0, 20, 3);
        m->AddY(Y0, sizeof(Y0)/sizeof(int));
        m->AddY(Y1, sizeof(Y1)/sizeof(int));
        if (b2Y1)
        {
                m->ConstrainY(Y1a, sizeof(Y1a)/sizeof(int));
        }
        m->AddY(Y2, sizeof(Y2)/sizeof(int));
        // m->print(std::cout);
        bool bFailed = true;
        BAB<GecodeTest3> e(m);
        GecodeTest3 *s;
        while (((s = e.next()) != 0))
        {
                bFailed = false;
                // s->print(std::cout);
                int X = s->GetX();
                int whichY = s->GetWhichY();
                int nCost = s->GetCost();
                std::cout << "X=" << X << " from Y" << whichY << ". Cost=" << nCost 
<<
std::endl;
                // std::cout << std::endl;
                delete s;
        }
        
        if (bFailed)
        {
                std::cout << "Model failed" << std::endl;
        }

        Search::Statistics stat = e.statistics();
        std::cout << "Search Statistics" << std::endl;
        std::cout << "  Propagations: " << stat.propagate << std::endl;
        std::cout << "  Nodes:        " << stat.node << std::endl;
        std::cout << "  Failures:     " << stat.fail << std::endl;
        std::cout << "  Depth:        " << stat.depth << std::endl;
        int nPeakMemoryKB = static_cast<int>((stat.memory+1023) / 1024);
        std::cout << "  Peak Memory   " << nPeakMemoryKB << "KB" << std::endl;
        std::cout << std::endl;
        delete m;
        return;
}

int GecodeTest3Main(int argc, char* argv[])
{
        std::cout << "One Y1 constraint" << std::endl;
        BuildAndSolve(false);
        std::cout << "Two Y1 constraints" << std::endl;
        BuildAndSolve(true);
        return 0;
}

Sample output:
One Y1 constraint
X=1 from Y0. Cost=3
X=2 from Y1. Cost=7
X=3 from Y0. Cost=9
X=4 from Y1. Cost=13
X=4 from Y2. Cost=14
X=5 from Y1. Cost=16
Search Statistics
    Propagations: 149
    Nodes:        21
    Failures:     5
    Depth:        3
    Peak Memory   8KB

Two Y1 constraints
Model failed
Search Statistics
    Propagations: 0
    Nodes:        0
    Failures:     1
    Depth:        0
    Peak Memory   4KB

_______________________________________________
Gecode users mailing list
users@gecode.org
https://www.gecode.org/mailman/listinfo/gecode-users

Reply via email to