void naryRandom::generateTernCtr( int i, int j, int k, long nogoods, Cost costMin, Cost costMax )
{
    int a,b,c,dice;
    EnumeratedVariable* x = (EnumeratedVariable*) wcsp.getVar(i);
    EnumeratedVariable* y = (EnumeratedVariable*) wcsp.getVar(j);
    EnumeratedVariable* z = (EnumeratedVariable*) wcsp.getVar(k);
    int mx = x->getDomainInitSize();
    int my = y->getDomainInitSize();
    int mz = z->getDomainInitSize();
    long total_nogoods = mx*my*mz;

    vector<Cost> costs;
    for (a = 0; a < mx; a++)
        for (b = 0; b < my; b++)
            for (c = 0; c < mz; c++)
                costs.push_back(MIN_COST);

    while(nogoods>0) {
        dice = myrand() % total_nogoods;
        for(a=0;a<mx;a++)
            for(b=0;b<my;b++)
                for(c=0;c<mz;c++) {
                    if(costs[my*mz*a + b*mz + c] == MIN_COST) {
                        if(dice == 0) {
                            costs[my*mz*a + b*mz + c] = ToulBar2::costMultiplier * randomCost(costMin, costMax);
                            nogoods--;
                            total_nogoods--;
                            a=mx;b=my;c=mz;
                        }
                        dice--;
                    }
                }
    }
    wcsp.postTernaryConstraint(i,j,k,costs);
}
void naryRandom::generateSubModularBinCtr( int i, int j, Cost costMin, Cost costMax )
{
    int a,b;
    EnumeratedVariable* x = (EnumeratedVariable*) wcsp.getVar(i);
    EnumeratedVariable* y = (EnumeratedVariable*) wcsp.getVar(j);
    int mx = x->getDomainInitSize();
    int my = y->getDomainInitSize();

    vector<Cost> costs;
    for (a = 0; a < mx; a++)
        for (b = 0; b < my; b++)
            costs.push_back(MIN_COST);

    // row generation
    for (a = 0; a < mx; a++) {
        if(myrand() % 2) {
            Cost c = ToulBar2::costMultiplier * randomCost(costMin, costMax);
            for (b = 0; b < my; b++) costs[my*a+b] += c;
        }
    }
    // col generation
    for (b = 0; b < my; b++) {
        if(myrand() % 2) {
            Cost c = ToulBar2::costMultiplier * randomCost(costMin, costMax);
            for (a = 0; a < mx; a++) costs[my*a+b] += c;

        }
    }

    // rectangle generation
    int nrect = myrand() % mx;
    while(nrect) {
        Cost c = ToulBar2::costMultiplier * randomCost(costMin, costMax);
        int lx = myrand() % (mx-1);
        int ly = myrand() % (my-1);
        for (a = 0; a < lx; a++)
            for (b = 0; b < ly; b++) {
                costs[my*(mx-a-1) + b] += c;
            }
        nrect--;
    }

    wcsp.postBinaryConstraint(i,j,costs);
}
void AllDiffConstraint::decompose() {
	deconnect();
	for (int i=0;i<arity_;i++) {
		for (int j=i+1;j<arity_;j++) {
			EnumeratedVariable* x = (EnumeratedVariable*)getVar(i);
			EnumeratedVariable* y = (EnumeratedVariable*)getVar(j);
			vector<Cost> costs;
			for (unsigned int a = 0; a < x->getDomainInitSize(); a++) {
				for (unsigned int b = 0; b < y->getDomainInitSize(); b++) {
					if (a == b) {
						costs.push_back(def);
					} else {
						costs.push_back(0);
					}
				}
			}
			if(ToulBar2::vac) {
				for (unsigned int a = 0; a < x->getDomainInitSize(); a++) {
					for (unsigned int b = 0; b < y->getDomainInitSize(); b++) {
						Cost c = costs[a * y->getDomainInitSize() + b];
						wcsp->histogram(c);
					}
				}               	
			}
			BinaryConstraint* ctr = x->getConstr(y);   		
			if(ctr)	{
				ctr->reconnect();
				ctr->addCosts(x,y,costs);
				ctr->propagate();
			}
			else {
				if (!ToulBar2::vac) {
					ctr = new BinaryConstraint(wcsp, x, y, costs, &wcsp->getStore()->storeCost);
				} else {
					ctr = new VACBinaryConstraint(wcsp, x, y, costs, &wcsp->getStore()->storeCost);
				}
			}
		}
	}
}
void naryRandom::Input( int in_n, int in_m, vector<int>& p, bool forceSubModular )
{
    n = in_n;
    m = in_m;

    assert(p.size() >= 2);

    int i,arity;
    vector<int>  indexs;
    vector<long> totalCtrs;
    vector<long> numCtrs;

    int maxa = p.size();

    for(arity=0; arity <= maxa; arity++) {
        if(arity < 2) numCtrs.push_back(0);
        else 	      numCtrs.push_back(p[arity-1]);
    }

    if (forceSubModular) {
        numCtrs[maxa] = (numCtrs[maxa-1] * numCtrs[maxa]) / 100;
        maxa--;
    }

    for(i=0;i<n;i++) {
        string varname = to_string(i);
        wcsp.makeEnumeratedVariable(varname,0,m-1);
    }

    for(arity=maxa;arity>1;arity--) {
        long nogoods =  (long) (((double)p[0] / 100.) * pow((double)m, arity));
        //long totalarraysize = (long) pow( (double)n, arity);
        long tCtrs = 1;
        set<long> scopes;
        for(i=0; i < arity; i++)  tCtrs *= (n - i);
        for(i=2; i <= arity; i++)  tCtrs /= i;

        if(numCtrs[arity] > tCtrs) {
            cout << numCtrs[arity] << "  " << arity << "ary constraints and the maximum is " << tCtrs << endl;
            numCtrs[arity] = tCtrs;
        }

        while(numCtrs[arity]) {
            bool oneadded = false;
            int dice = myrand() % tCtrs;
            ini(indexs,arity);
            do {
                if(scopes.end() == scopes.find(toIndex(indexs))) {
                    if(dice == 0) {
                        scopes.insert( toIndex(indexs) );
                        if(arity > 1) {
                            switch(arity) {
                            case 2:
                                if(!forceSubModular || numCtrs[arity] > numCtrs[maxa+1]) generateBinCtr(indexs[0],indexs[1],nogoods);
                                else  generateSubModularBinCtr(indexs[0],indexs[1],SMALL_COST,MEDIUM_COST);
                                break;
                            case 3:
                                generateTernCtr(indexs[0],indexs[1],indexs[2],nogoods);
                                break;
                            default: generateNaryCtr(indexs,nogoods);
                            }
                        }
                        tCtrs--;
                        numCtrs[arity]--;
                        oneadded = true;
                    }
                    dice--;
                }
            } while(inc(indexs) && !oneadded);
        }
    }


    for(i=0;i<n;i++) {
        EnumeratedVariable* x = (EnumeratedVariable*) wcsp.getVar(i);
        for (unsigned int a = 0; a < x->getDomainInitSize(); a++)
        {
            x->project(x->toValue(a), ToulBar2::costMultiplier * randomCost(MIN_COST, MEDIUM_COST));
        }
        x->findSupport();
    }

    if(forceSubModular) {
        for(i=0;i<n;i++) {
            EnumeratedVariable* x = (EnumeratedVariable*) wcsp.getVar(i);
            x->permuteDomain(10);
        }
    }
}