/*******************************************************************************
 * Copyright (c) 2015-2017 ONERA and IRT AESE (IRT Saint Exupéry).
 * Ce logiciel est la propriété de l’ONERA (the French Aerospace Lab) et de
 * l'IRT AESE (IRT Saint Exupéry).
 * Tous droits réservés.
 *
 * Ce programme et les éléments qui l'accompagnent sont mis à disposition
 * aux conditions définies par le contrat de licence logiciel CeCILL-C soumise
 * au droit français et respectant les principes de diffusion des logiciels libres.
 * Vous pouvez utiliser, modifier et/ou redistribuer ce programme
 * sous les conditions de la licence CeCILL-C (http://www.cecill.info).

 * This software is property of ONERA (the French Aerospace Lab) and of
 * the IRT AESE (IRT Saint Exupéry).
 * All rights reserved.
 *
 * This program and the accompanying materials are made available under
 * the terms of the CeCILL-C license under French law and
 * abiding by the rules of distribution of free software.
 * You can  use, modify and/ or redistribute the software under the terms of
 * the CeCILL-C license (http://www.cecill.info).
 *
 * Contributeurs/contributors:
 *     Guillaume Infantes (ONERA - Centre de Toulouse) - initial API and implementation
 *     Alexandre Albore (IRT Saint-Exupéry) - Altarica/Fiacre translation
 *
 *******************************************************************************/

#include "ExpressionEvaluatorLandmark.hh"
#include "Expressions.hh"
#include "../AltaricaState.hh"
#include "../Node.hh"
#include "../AltaricaModel.hh"
#include "../Values.hh"
#include "../Variable.hh"
#include "iostream"

using namespace epoch::altarica;

std::pair<Value*,landmarkType*> *  ExpressionEvaluatorLandmark::visitLM(const Expression *e) {
    Value * oldV = val_;
    landmarkType * oldLM = lm_;
    lm_ = NULL;
    val_ = NULL;
    e->accept(this);
    Value * newV = val_;
    landmarkType * newLM = lm_;
    val_ = oldV;
    lm_ = oldLM;
    return new std::pair<Value*,landmarkType*>(newV,newLM);
}

bool ExpressionEvaluatorLandmark::hasLM(landmarkType * lm, Value*v) {
    if (lm == NULL)
	return false;
    std::map<Value*,AltaricaState*>::iterator i = lm->find(v);
    std::map<Value*,AltaricaState*>::iterator end = lm->end();
    
    return (i!=end);
}

void ExpressionEvaluatorLandmark::addOrIntersectLM(landmarkType *lm1, Value *v1, landmarkType*lm2, Value *v2) {
    if (!hasLM(lm2,v2))
	 return;
    if (hasLM(lm1,v1)) 
	(*lm1)[v1]->mergeIntersectState((*lm2)[v2]);	
    else
	lm1->insert(std::pair<Value*,AltaricaState*>(v1,(*lm2)[v2]->clone()));
}

void ExpressionEvaluatorLandmark::addOrIntersectLM(landmarkType *lm1, Value *v1, AltaricaState* l) {
    if (l == NULL)
	return;
     if (hasLM(lm1,v1))
	(*lm1)[v1]->mergeIntersectState(l);
    else
	lm1->insert(std::pair<Value*,AltaricaState*>(v1,l->clone()));
}



void ExpressionEvaluatorLandmark::printLM(landmarkType*lm) {
    if (lm == NULL) {
	std::cout << "NO LM...." << std::endl;
	return; 
    }
    for (std::map<Value*, AltaricaState*>::iterator i = lm->begin(); i!=lm->end(); ++i) {
	std::cout << "val: " << i->first->toString() << std::endl << i->second->toString(true,false,false,false) << std::endl;
    }
}



void ExpressionEvaluatorLandmark::visitADD(const ExpressionADD *e){
    std::cout << "VISITING " << e->toString();
    std::cout << "LMS" << std::endl << lms_->toString();
    std::pair<Value*, landmarkType*> * lv = visitLM(e->getLeft());
    std::pair<Value*, landmarkType*> * rv = visitLM(e->getRight());
	
    if (lv->first->isBool() || rv->first->isBool() || lv->first->isSymbol() || rv->first->isSymbol()) {
	BOOST_THROW_EXCEPTION(std::runtime_error("PLUS/MINUS asked on bools or symbols"));
    }


    ValueInt * res = new ValueInt();
    res->clear();
    lm_ = new landmarkType();

    std::vector<Value*> * ls = lv->first->getSingletons();
    std::vector<Value*> * rs = rv->first->getSingletons();

    for (std::vector<Value*>::iterator i = ls->begin(); i!=ls->end(); ++i) {
	for (std::vector<Value*>::iterator j = rs->begin(); j!=rs->end(); ++j) {
	    ValueInt * li = (ValueInt*) (*i);
	    ValueInt * ri = (ValueInt*) (*j);
	    int bidon;
	    if (e->getType() == 0)
		bidon = li->toInt()+ri->toInt();
	    else
		bidon = li->toInt()-ri->toInt();
	    res->addValues(bidon,bidon);
	    (*lm_)[new ValueInt(bidon)] = (*(lv->second))[li];
	    (*lm_)[new ValueInt(bidon)]->mergeIntersectState((*(rv->second))[ri]);
	}
    }

    Value::deleteIfPossible(rv->first);
    Value::deleteIfPossible(lv->first);
    delete rv->second;


    val_ = res;
    std::cout << "END OF VISIT OF " << e->toString() ;
    std::cout << "LM_ "; printLM(lm_);
    std::cout << "LMS :" << lms_->toString();
}

void ExpressionEvaluatorLandmark::visitAND(const ExpressionAND *e){
    std::cout << "VISITING " << e->toString();
    std::cout << "LMS" << std::endl << lms_->toString();
    std::pair<Value*, landmarkType*> * lv = visitLM(e->getLeft());    
    std::pair<Value*, landmarkType*> * rv = visitLM(e->getRight());    

    if (!lv->first->isBool() ||! rv->first->isBool()) {
	std::cerr<< state_->toString(true,true,true,true);
	BOOST_THROW_EXCEPTION(std::runtime_error("AND left and right argument are not bool " + e->toString())); 
	Value::deleteIfPossible(lv->first);
	Value::deleteIfPossible(rv->first);
    }

    Value * res;
    lm_ = new landmarkType();
    
    ValueBool * lb = (ValueBool*) lv->first;
    ValueBool * rb = (ValueBool*) rv->first;
    res = lb->clone();
    ValueBool * boolRes = (ValueBool*)res;
    boolRes->land(rb);
   if (boolRes->allowedTop()) {
	ValueBool *top  = new ValueBool(true,false);
	addOrIntersectLM(lm_, top, lv->second,top);
	addOrIntersectLM(lm_, top, rv->second,top);
    } 
    if (boolRes->allowedBottom()) {
	ValueBool *bottom  = new ValueBool(false,true);
	if (lb->allowedBottom()) 
	    addOrIntersectLM(lm_,bottom,lv->second,bottom);		
	if (rb->allowedBottom()) 
	    addOrIntersectLM(lm_,bottom,rv->second,bottom);			       	    
    }
    
    Value::deleteIfPossible(rv->first);   
    Value::deleteIfPossible(lv->first);
    delete rv->second;
    delete lv->second;
    val_ = res;
    std::cout << "END OF VISIT OF " << e->toString() ;
    std::cout << "LM_ "; printLM(lm_);
    std::cout << "LMS :" << lms_->toString();

}

/// This method does as less as possible
void ExpressionEvaluatorLandmark::visitINTERVAL(const ExpressionINTERVAL *e) {
    std::cout << "VISITING " << e->toString();
    std::cout << "LMS" << std::endl << lms_->toString();
    std::pair<Value*, landmarkType*> * lv = visitLM(e->getLeft());
    std::pair<Value*, landmarkType*> * rv = visitLM(e->getRight());


    if (!lv->first->isReal() || !rv->first->isReal()) {
	BOOST_THROW_EXCEPTION(std::runtime_error("INTERVAL ON NOT REALs...."));
	return;
    }
    ValueReal * li = (ValueReal*) lv->first;
    ValueReal * ri = (ValueReal*) rv->first;
    lm_ = new landmarkType();

	ValueReal * v;
	val_ = new ValueReal(ri->toDouble());

	Value::deleteIfPossible(lv->first);
	Value::deleteIfPossible(rv->first);

    delete lv->second;
    delete rv->second;

    std::cout << "END OF VISIT OF " << e->toString() ;
    std::cout << "LM_ "; printLM(lm_);
    std::cout << "LMS :" << lms_->toString();
}



void ExpressionEvaluatorLandmark::visitARITH(const ExpressionARITH *e)  {
    std::cout << "VISITING " << e->toString();
    std::cout << "LMS" << std::endl << lms_->toString();
    std::pair<Value*, landmarkType*> * lv = visitLM(e->getLeft());    
    std::pair<Value*, landmarkType*> * rv = visitLM(e->getRight());    


    if (!lv->first->isInt() || !rv->first->isInt()) {
	BOOST_THROW_EXCEPTION(std::runtime_error("ARITHMETIC OPERATION ON NOT INTs...."));		
	return;		
    }

    ValueInt * li = (ValueInt*) lv->first;
    ValueInt * ri = (ValueInt*) rv->first;
    lm_ = new landmarkType();

    if (assert_) {
	bool constrained = li->constrained();
	if (li->ro()) 
	    li = (ValueInt*) li->clone();	

	switch(e->getType()) {
	case 0:     li->setToInfThan(ri);    break;
	case 1:     li->setToSupThan(ri);    break; 
	case 2:     li->setToInfEqThan(ri);  break;
	case 3:     li->setToSupEqThan(ri);  break;
	}
	Value::deleteIfPossible(ri);
	if (!constrained) {
	    const ExpressionMEMBER * em = dynamic_cast<const ExpressionMEMBER*>(e->getLeft());      
	    if (em != NULL)  // we have to do the affectation
        state_->setValue(em->getVariable(node_, amodel_),li);
	    std::vector<Value*> * newVals = li->getSingletons();
	    landmarkType * toChange = (*(lms_->getFlowLabels()))[em->getVariable(node_, amodel_)->getIndex()];
	    for (std::vector<Value*>::const_iterator i = newVals->begin(); i!= newVals->end(); ++i) {
		switch (e->getType()) {
		case 0: 
		case 2: addOrIntersectLM(toChange,*i,rv->second,new ValueInt(ri->getMin())); break;		    
		case 1:
		case 3: addOrIntersectLM(toChange,*i,rv->second,new ValueInt(ri->getMax())); break;
		}
	    }
	}
	val_ = new ValueBool(true,false);
	if (e->getType() == 0 || e->getType() == 2)
	    addOrIntersectLM(lm_,val_, rv->second,new ValueInt(ri->getMin()));
	else 
	    addOrIntersectLM(lm_,val_, rv->second,new ValueInt(ri->getMax()));
    } else {  
	switch(e->getType()) {
	case 0:    val_ = new ValueBool(li->getMin()<ri->getMax(),li->getMax()>=ri->getMin());    break;
	case 1:    val_ = new ValueBool(li->getMin()>ri->getMax(),li->getMax()<=ri->getMin());    break;
	case 2:    val_ = new ValueBool(li->getMin()<=ri->getMax(),li->getMax()>ri->getMin());    break;
	case 3:    val_ = new ValueBool(li->getMin()>=ri->getMax(),li->getMax()<ri->getMin());    break;
	}
	if (((ValueBool*)val_)->allowedTop()) {
	    ValueBool * top = new ValueBool(true,false);
	    addOrIntersectLM(lm_, top, lv->second, new ValueInt(li->getMin()));
	    addOrIntersectLM(lm_, top, rv->second, new ValueInt(ri->getMax()));
	} 
	if (((ValueBool*)val_)->allowedBottom()) {
	    ValueBool * bottom = new ValueBool(false,true);
	    addOrIntersectLM(lm_, bottom, lv->second, new ValueInt(li->getMax()));
	    addOrIntersectLM(lm_, bottom, rv->second, new ValueInt(ri->getMin()));
	}
	
	Value::deleteIfPossible(lv->first);
	Value::deleteIfPossible(rv->first);	
    }
    delete lv->second;
    delete rv->second;
    std::cout << "END OF VISIT OF " << e->toString() ;
    std::cout << "LM_ "; printLM(lm_);
    std::cout << "LMS :" << lms_->toString();

}

void ExpressionEvaluatorLandmark::visitBOOLCONSTANT(const ExpressionBOOLCONSTANT *e)  {
    std::cout << "VISITING " << e->toString();
    std::cout << "LMS" << std::endl << lms_->toString();
    val_ =  e->get();
    lm_ = NULL;
    std::cout << "END OF VISIT OF " << e->toString() ;
    std::cout << "LM_ "; printLM(lm_);
    std::cout << "LMS :" << lms_->toString();

}

void ExpressionEvaluatorLandmark::visitCARD(const ExpressionCARD *e)  {
    std::cout << "VISITING " << e->toString();
    std::cout << "LMS" << std::endl << lms_->toString();
    int i = 0;
    AltaricaState * unionLM = new AltaricaState(false, lms_->getState()->getAModel(),lms_->getState()->getAModel()->getInitInfo());
    for (std::vector<Expression*>::const_iterator ei = e->getExprs()->begin(); ei != e->getExprs()->end(); ++ei) {
	std::pair<Value *, landmarkType*> *v = visitLM(*ei);
	i+= v->first->card();
	Value::deleteIfPossible(v->first);
	for (std::map<Value*,AltaricaState*>::iterator j = v->second->begin(); j!=v->second->end(); ++j)
	    j->second->mergeToState(unionLM);
    }
    val_ = new ValueInt(i);
    lm_ = new landmarkType();
    lm_->insert(std::pair<Value*,AltaricaState*>(val_, unionLM));
    std::cout << "END OF VISIT OF " << e->toString() ;
    std::cout << "LM_ "; printLM(lm_);
    std::cout << "LMS :" << lms_->toString();

}
void ExpressionEvaluatorLandmark::visitCONSTARRAY(const ExpressionCONSTARRAY *e)  {
  BOOST_THROW_EXCEPTION(std::runtime_error("Const Array eval not implemented!!!"));
}

void ExpressionEvaluatorLandmark::visitCONSTSTRUCT(const ExpressionCONSTSTRUCT *e)  {
    BOOST_THROW_EXCEPTION(std::runtime_error("Const Struct eval not implemented!!!"));
}

void ExpressionEvaluatorLandmark::visitCASE(const ExpressionCASE *e)  {
    std::cout << "VISITING " << e->toString();
    std::cout << "LMS" << std::endl << lms_->toString();
    bool doElse = false;
    bool doCase = false;
    const std::vector<Expression*> * conds = e->getConds();
    const std::vector<Expression*> * thens = e->getThens();
    ValueBool * top = new ValueBool(true,false);
    ValueBool * bottom = new ValueBool(false,true);
    AltaricaState * tempLM = new AltaricaState(false, lms_->getState()->getAModel(),lms_->getState()->getAModel()->getInitInfo());
    lm_ = new landmarkType();
    for (unsigned int i = 0; i< conds->size(); ++i) {	
	std::pair<Value *, landmarkType*> * c = visitLM((*conds)[i]);
	if (!c->first->isBool()) {
	    Value::deleteIfPossible(c->first);
	    BOOST_THROW_EXCEPTION(std::runtime_error("condition of case is not a bool!")); 
	}
	
	ValueBool *c2 = (ValueBool*)c->first;
	if (c2->allowedTop()) {
	    doCase = true;
	    std::pair<Value *,landmarkType*>*v = visitLM((*thens)[i]);
	    if (val_ == NULL) {
		val_ = v->first;
		std::vector<Value*> * vals = v->first->getSingletons();
		for (std::vector<Value*>::const_iterator i = vals->begin(); i!=vals->end(); ++i) 
		    addOrIntersectLM(lm_,*i,v->second, *i);
	    } else {
		val_->merge(v->first);
		std::vector<Value*> * vals = v->first->getSingletons();
		for (std::vector<Value*>::const_iterator i = vals->begin(); i!=vals->end(); ++i) {
		    addOrIntersectLM(lm_,*i, v->second, *i);
		}
		Value::deleteIfPossible(v->first);
		delete v->second;
	    }
	    std::vector<Value*> * vals = val_->getSingletons();
	    for (std::vector<Value*>::const_iterator i = vals->begin(); i!=vals->end(); ++i) {
		addOrIntersectLM(lm_, *i,c->second, top);
	    }
	}
	if (c2->allowedBottom()) {
	    if (hasLM(c->second,bottom)) {
		if (tempLM ==NULL) {
		    tempLM = (*(c->second))[bottom];
		} else {
		    tempLM->mergeIntersectState((*(c->second))[bottom]);
		}
	    }

	    doElse = true;	  
	}  
	Value::deleteIfPossible(c2);
    } 
    
    if (e->getElse() != NULL && (doElse || !doCase)) {
	std::pair<Value *,landmarkType*> *v = visitLM(e->getElse());
	if (val_ == NULL) {
	    val_ = v->first;
	    std::vector<Value*> * vals = v->first->getSingletons();
	    for (std::vector<Value*>::const_iterator i = vals->begin(); i!=vals->end(); ++i) {
		addOrIntersectLM(lm_, *i, v->second, *i);
		addOrIntersectLM(lm_,*i, tempLM);
	    }
	    
	} else {
	    val_->merge(v->first);
	    std::vector<Value*> * vals = v->first->getSingletons();
	    for (std::vector<Value*>::const_iterator i = vals->begin(); i!=vals->end(); ++i) {
		addOrIntersectLM(lm_,*i, v->second, *i);
		addOrIntersectLM(lm_,*i, tempLM);		
	    }
	    Value::deleteIfPossible(v->first);
	    delete v->second;
	}

    }
    std::cout << "END OF VISIT OF " << e->toString() ;
    std::cout << "LM_ "; printLM(lm_);
    std::cout << "LMS :" << lms_->toString();

}

void ExpressionEvaluatorLandmark::visitFUNCTIONCALL(const ExpressionFUNCTIONCALL *e)  { 
    BOOST_THROW_EXCEPTION(std::runtime_error("function eval  not implemented"));
}

void ExpressionEvaluatorLandmark::visitIfThenElse(const ExpressionIfThenElse *e)  {
    std::cout << "VISITING " << e->toString();
    std::cout << "LMS" << std::endl << lms_->toString();
    std::pair<Value *,landmarkType*> * c =visitLM(e->getIf());

    ValueBool * top = new ValueBool(true,false);
    ValueBool * bottom = new ValueBool(false,true);
    if (!c->first->isBool()) {
	Value::deleteIfPossible(c->first);
	BOOST_THROW_EXCEPTION(std::runtime_error("conditon of ifthenelse is not a bool!"));		
    }
    lm_ = new landmarkType();
    ValueBool * c2 = (ValueBool*) c->first;

    if (c2->allowedTop()) {
	std::pair<Value*,landmarkType*> * res = visitLM(e->getThen());
	val_ = res->first;
	std::vector<Value*> * vals = val_->getSingletons();
	for (std::vector<Value*>::const_iterator i = vals->begin(); i!=vals->end(); ++i) {
	    addOrIntersectLM(lm_,*i, res->second, *i);
	    addOrIntersectLM(lm_, *i, c->second, top);
	}
	
	
    }
    if (c2->allowedBottom()) {
	std::pair<Value *,landmarkType*> *  v = visitLM(e->getElse());
	if (val_ == NULL) {
	    val_ = v->first;
	    std::vector<Value*> * vals = val_->getSingletons();
	    for (std::vector<Value*>::const_iterator i = vals->begin(); i!=vals->end(); ++i) {
		addOrIntersectLM(lm_,*i, v->second, *i);
		addOrIntersectLM(lm_,*i, c->second, bottom);
	    }
	} else {
	    val_->merge(v->first);   
	    std::vector<Value*> * vals = v->first->getSingletons();
	    for (std::vector<Value*>::const_iterator i = vals->begin(); i!=vals->end(); ++i) {
		addOrIntersectLM(lm_,*i, v->second, *i);
		addOrIntersectLM(lm_,*i, c->second, bottom);
	    }
	    Value::deleteIfPossible(v->first);
	    delete v->second;
	    delete v;
	}
    }
    Value::deleteIfPossible(c->first);
    std::cout << "END OF VISIT OF " << e->toString() ;
    std::cout << "LM_ "; printLM(lm_);
    std::cout << "LMS :" << lms_->toString();

}


void ExpressionEvaluatorLandmark::visitMEMBER(const ExpressionMEMBER *e)  {
    std::cout << "VISITING " << e->toString();
    std::cout << "LMS" << std::endl << lms_->toString();
    Variable * v;
    Value * vv;
    std::vector<Value*> * vals;
    lm_ = new landmarkType();
    //cached version (dig expressions.old or svn for uncached versions)
    switch (e->getIsSymbol()) {
    case -1:
	if (node_->isSymbol(e->getSymbol())) {
	    e->setIsSymbol(0);
	    e->setSymbol();
	    val_ = e->getSymbolValue();
	    lm_ = NULL;
	} else {
	    e->resizeCache(state_->getAModel()->getNNodes());
	    v = node_->findStateVariableByName(e->getMA());
	    if (v != NULL) {
		e->setIsSymbol(1);
		e->setCache(node_->getIndex(), v);
		vv = state_->getValue(v);
		vv->setDomain(v->getDomain());
		val_ = vv;
		vals = vv->getSingletons();
		for (std::vector<Value*>::iterator i = vals->begin(); i!= vals->end(); ++i)
		    addOrIntersectLM(lm_, *i, lms_->getLabel(v,*i));
	    } else {
		v = node_->findFlowVariableByName(e->getMA());
		if (v != NULL) {
		    e->setIsSymbol(2);
		    e->setCache(node_->getIndex(), v);
		    v->evaluateLM(amodel_, lms_);
		    val_ = state_->getValue(v);
		    vals = val_->getSingletons();
		    for (std::vector<Value*>::iterator i = vals->begin(); i!= vals->end(); ++i) {
			AltaricaState * label = lms_->getLabel(v,*i);
			addOrIntersectLM(lm_, *i, label);
		    }
		} else {
		    // in this case, symbol that is not in n->symbolCache ( -> symbol of subnode....)
		    e->setIsSymbol(0); 
		    e->setSymbol();
		    val_ = e->getSymbolValue();	    
		}
	    }
	}
	break;
    case 0: 
	val_ = e->getSymbolValue();	    
	break;
    case 1: 
	v = e->getVarFromCache(node_->getIndex());
	if (v == NULL) {
	    v = node_->findStateVariableByName(e->getMA());
	    e->setCache(node_->getIndex(),v);
	}
    	vv = state_->getValue(v);
    	vv->setDomain(v->getDomain());
	val_ = vv;
	vals = vv->getSingletons();
	for (std::vector<Value*>::iterator i = vals->begin(); i!= vals->end(); ++i)
	    addOrIntersectLM(lm_, *i, lms_->getLabel(v,*i));
	break;
    case 2:
	v = e->getVarFromCache(node_->getIndex());
	if (v == NULL) {
	    v = node_->findFlowVariableByName(e->getMA());
	    e->setCache(node_->getIndex(),v);
	}
	v->evaluateLM(amodel_, lms_);
	val_ = state_->getValue(v);
	vals = val_->getSingletons();
	for (std::vector<Value*>::iterator i = vals->begin(); i!= vals->end(); ++i)
	    addOrIntersectLM(lm_, *i, lms_->getLabel(v,*i));
	break;
    default:     
	ValueSymbol *os = new ValueSymbol(e->getSymbol());
	val_ = os;
    }
    std::cout << "END OF VISIT OF " << e->toString() ;
    std::cout << "LM_ "; printLM(lm_);
    std::cout << "LMS :" << lms_->toString();

}


void ExpressionEvaluatorLandmark::visitMINMAX(const ExpressionMINMAX *e)  {
    std::cout << "VISITING " << e->toString();
    std::cout << "LMS" << std::endl << lms_->toString();
    const std::vector<Expression*> * exprs = e->getExprs();
    
    std::pair<Value *,landmarkType*> * optV = visitLM(*(exprs->begin()));
    if (!optV->first->isInt()) {
	delete(optV);
	BOOST_THROW_EXCEPTION(std::runtime_error("MIN/MAX on a bool!!")); 
    }
    
    ValueInt * optI = (ValueInt*)(optV->first);
    if (e->max()) {
	int max = optI->max();
	Value::deleteIfPossible(optI);
	for (std::vector<Expression*>::const_iterator eIT = exprs->begin(); eIT != exprs->end(); ++eIT) {
	    std::pair<Value *,landmarkType*>* v = visitLM((*eIT));
	    if (!v->first->isInt()) {
		Value::deleteIfPossible(v->first);
		BOOST_THROW_EXCEPTION(std::runtime_error("MIN/MAX on not an int!!")); 
	    } else {
		ValueInt* vi = (ValueInt*)(v);
		int cmax = vi->max();
		if (cmax > max) {
		    max = cmax;	
		    lm_ = v->second;
		}	
		Value::deleteIfPossible(v->first);
	    }	    
	}
	val_ = new ValueInt(max);
    } else {
	int min = optI->min();
	for (std::vector<Expression*>::const_iterator eIT = exprs->begin();  eIT != exprs->end(); ++eIT) {
	    std::pair<Value *,landmarkType*> * v = visitLM(*eIT);
	    if (!v->first->isInt()) {
		Value::deleteIfPossible(v->first);
		BOOST_THROW_EXCEPTION(std::runtime_error("MIN/MAX on not an int!!"+e->toString())); 
	    } else {
		ValueInt * vi = (ValueInt*)(v->first);
		int cmin = vi->min();
		if (cmin < min) {
		    min = cmin;	
		    lm_ = v->second;
		}	
		Value::deleteIfPossible(v->first);
	    }
	}		
	val_ =  new ValueInt(min);
    }
    std::cout << "END OF VISIT OF " << e->toString() ;
    std::cout << "LM_ "; printLM(lm_);
    std::cout << "LMS :" << lms_->toString();

}
void ExpressionEvaluatorLandmark::visitMUL(const ExpressionMUL *e)  {
    std::cout << "VISITING " << e->toString();
    std::cout << "LMS" << std::endl << lms_->toString();
    std::pair<Value *,landmarkType*> * lv = visitLM(e->getLeft());
    std::pair<Value *,landmarkType*> * rv = visitLM(e->getRight());
	
    if (!lv->first->isInt() || !rv->first->isInt()) {
	Value::deleteIfPossible(lv->first);
	Value::deleteIfPossible(rv->first);
	BOOST_THROW_EXCEPTION(std::runtime_error("TIMES/DIV asked on bools"));
    }

    ValueInt * li = (ValueInt*) lv->first;
    ValueInt * ri = (ValueInt*) rv->first;

    ValueInt * res = new ValueInt();
    res->clear();
    lm_ = new landmarkType();
    std::vector<Value*> * ls = li->getSingletons();
    std::vector<Value*> * rs = ri->getSingletons();

    // switch (e->getType()) {
    // case 0: 	val_->times(ri);     break;
    // case 1:  	val_->div(ri);        break;
    // default:    val_->mod(ri);        break;
    // }
    for (std::vector<Value*>::iterator i = ls->begin(); i!=ls->end(); ++i) {
	for (std::vector<Value*>::iterator j = rs->begin(); j!=rs->end(); ++j) {
	    ValueInt * li = (ValueInt*) (*i);
	    ValueInt * ri = (ValueInt*) (*j);
	    int bidon;
	    if (e->getType() == 0)
		bidon = li->toInt()*ri->toInt();
	    else if (e->getType() == 1)
		bidon = li->toInt()/ri->toInt();
	    else 
		bidon = li->toInt()%ri->toInt();
	    res->addValues(bidon,bidon);
	    (*lm_)[new ValueInt(bidon)] = (*(lv->second))[li];
	    (*lm_)[new ValueInt(bidon)]->mergeIntersectState((*(rv->second))[ri]);
	}
    }
     
    Value::deleteIfPossible(rv->first);
    Value::deleteIfPossible(li);
    val_ = res;
    std::cout << "END OF VISIT OF " << e->toString() ;
    std::cout << "LM_ "; printLM(lm_);
    std::cout << "LMS :" << lms_->toString();

}

void ExpressionEvaluatorLandmark::visitPAREN(const ExpressionPAREN *e)  {
    std::cout << "VISITING " << e->toString();
    std::cout << "LMS" << std::endl << lms_->toString();
    std::pair<Value*,landmarkType*> * res = visitLM(e->getExpr());
    val_ = res->first;
    lm_ = res->second;
    std::cout << "END OF VISIT OF " << e->toString() ;
    std::cout << "LM_ "; printLM(lm_);
    std::cout << "LMS :" << lms_->toString();

}

void ExpressionEvaluatorLandmark::visitUNSIGNEDINT(const ExpressionUNSIGNEDINT *e)  {
    std::cout << "VISITING " << e->toString();
    std::cout << "LMS" << std::endl << lms_->toString();
    val_ = e->getValue();
    lm_ = NULL;
    std::cout << "END OF VISIT OF " << e->toString() ;
    std::cout << "LM_ "; printLM(lm_);
    std::cout << "LMS :" << lms_->toString();

}


void ExpressionEvaluatorLandmark::visitREAL(const ExpressionREAL *e)  {
    std::cout << "VISITING " << e->toString();
    std::cout << "LMS" << std::endl << lms_->toString();
    val_ = e->getValue();
    lm_ = NULL;
    std::cout << "END OF VISIT OF " << e->toString() ;
    std::cout << "LM_ "; printLM(lm_);
    std::cout << "LMS :" << lms_->toString();

}


void ExpressionEvaluatorLandmark::visitUNARY(const ExpressionUNARY *e)  {
    std::cout << "VISITING " << e->toString();
    std::cout << "LMS" << std::endl << lms_->toString();
    std::pair<Value *,landmarkType*> * c = visitLM(e->getBelow());
    std::vector<Value*> * vals;
    lm_ = new landmarkType();
    ValueBool * b;
    switch(e->getType()) {
    case 0:  // MINUS 
	if (!c->first->isInt()) {
	    Value::deleteIfPossible(c->first);
	    BOOST_THROW_EXCEPTION(std::runtime_error("unary MINUS on not an int!!" + e->toString()));   
	}	
	if (c->first->ro()) 
	    val_ =  c->first->clone();
	else
	    val_ = c->first;
	val_->inverse();
	vals = val_->getSingletons();
	for (std::vector<Value*>::iterator i = vals->begin(); i!= vals->end(); ++i) {
	    Value * inv = (*i)->clone();
	    inv->inverse();
	    addOrIntersectLM(lm_, *i, c->second, inv);
	}
	break;
    case 1: //NOT
	if (!c->first->isBool()) {
	    Value::deleteIfPossible(c->first);
	    BOOST_THROW_EXCEPTION(std::runtime_error("NOT on a not bool!!" +e->toString()));   
	}
	b = new ValueBool(false,false);
	if (((ValueBool*)c->first)->allowedTop()) {
	    b->allowBottom(true);
	    addOrIntersectLM(lm_, new ValueBool(false,true), c->second, new ValueBool(true,false));
	}
	if (((ValueBool*)c->first)->allowedBottom()) {
	    b->allowTop(true);
	    addOrIntersectLM(lm_, new ValueBool(true,false), c->second, new ValueBool(false,true));
	}
	val_ = b;
	break;
    case 2: //COMPL
	if (c->first->ro())
	    val_ =c->first->clone();
	else 
	    val_ =c->first;
	val_->inverse();
	lm_ = NULL;
	break;
    }
    std::cout << "END OF VISIT OF " << e->toString() ;
    std::cout << "LM_ "; printLM(lm_);
    std::cout << "LMS :" << lms_->toString();

}



void ExpressionEvaluatorLandmark::visitOR(const ExpressionOR *e)  {
    std::cout << "VISITING " << e->toString();
    std::cout << "LMS" << std::endl << lms_->toString();
    std::pair<Value *, landmarkType*> * lv = visitLM(e->getLeft());
    std::pair<Value *, landmarkType*> * rv = visitLM(e->getRight());
    lm_ = new landmarkType();

    if (lv->first->isBool()) { 
	if (!rv->first->isBool())
	    BOOST_THROW_EXCEPTION(std::runtime_error("OR left if bool and right is not -> do not know if i have to do a unification or a logical comparison" + e->toString()));
	ValueBool * res;

	ValueBool * lb = (ValueBool*) lv->first;
	ValueBool * rb = (ValueBool*) rv->first;
	res = lb->clone();
	res->lor(rb);
	ValueBool * top = new ValueBool(true,false);
	ValueBool * bottom = new ValueBool(false,true);
	if (lb->allowedTop()) 
	    addOrIntersectLM(lm_,top,lv->second,top);	
	if (rb->allowedTop()) 
	    addOrIntersectLM(lm_,top,rv->second,top);
	if (lb->allowedBottom() && rb->allowedBottom()) {
	    addOrIntersectLM(lm_,bottom,lv->second,bottom);
	    addOrIntersectLM(lm_,bottom,rv->second,bottom);
	}
	    
	Value::deleteIfPossible(rb);
	Value::deleteIfPossible(lb);
	val_ = res;
    } else if (lv->first->isInt()) {
	if (!rv->first->isInt())
	    BOOST_THROW_EXCEPTION(std::runtime_error("OR left if int and right is not -> do not know if i have to do a unification or a logical comparison" + e->toString()));	
	ValueInt * lb = (ValueInt*) lv->first;
	ValueInt * rb = (ValueInt*) rv->first;
	ValueInt * res;
	res = lb->clone();
	res->intUnion(rb);
	std::vector<Value*> * vals = lb->getSingletons();
	for (std::vector<Value*>::iterator i = vals->begin(); i!= vals->end(); ++i) {
	    addOrIntersectLM(lm_, *i, lv->second, *i);
	}
	vals = rb->getSingletons();
	for (std::vector<Value*>::iterator i = vals->begin(); i!= vals->end(); ++i) {
	    addOrIntersectLM(lm_, *i, rv->second, *i);
	}
	Value::deleteIfPossible(rb);
	Value::deleteIfPossible(lb);
	val_ = res;
    } else {
	ValueSymbol * lb = (ValueSymbol*) lv;
	ValueSymbol * rb = (ValueSymbol*) rv;
	ValueSymbol * res = lb->clone();
	res->merge(rb);	
	std::vector<Value*> * vals = lb->getSingletons();
	for (std::vector<Value*>::iterator i = vals->begin(); i!= vals->end(); ++i) {
	    addOrIntersectLM(lm_, *i, lv->second, *i);
	}
	vals = rb->getSingletons();
	for (std::vector<Value*>::iterator i = vals->begin(); i!= vals->end(); ++i) {
	    addOrIntersectLM(lm_, *i, rv->second, *i);
	}
	Value::deleteIfPossible(rb);
	Value::deleteIfPossible(lb);
	val_ = res;
    }
    std::cout << "END OF VISIT OF " << e->toString() ;
    std::cout << "LM_ "; printLM(lm_);
    std::cout << "LMS :" << lms_->toString();

}

void ExpressionEvaluatorLandmark::visitQUANTIFIED(const ExpressionQUANTIFIED *e)  {
    std::cout << "VISITING " << e->toString();
    std::cout << "LMS" << std::endl << lms_->toString();
    std::vector<Variable*> vars;
    const std::vector<std::string> * qVars = e->getQVars();
    const std::vector<Domain*> * dVars = e->getDVars();
    
    for (unsigned int i= 0; i<qVars->size(); ++i) {
	Variable * v = new Variable((*qVars)[i],(*dVars)[i],true);
	v->setNode(node_);
	vars.push_back(v);    
    }
    
    std::vector<std::vector<Value*>*> * combinations = buildCombinations(&vars);
    val_ = new ValueBool();
    bool top;
    bool bottom;
    ValueBool * vtop = new ValueBool(true,false);
    ValueBool * vbot = new ValueBool(false,true);
    lm_ = new landmarkType();
    landmarkType * tempLM = new landmarkType();
    

    if (e->forAll()) {
	top = true;
	bottom = false;
	for (std::vector<std::vector<Value*>*>::iterator combi = combinations->begin(); 
	     combi != combinations->end(); ++combi) {
	    AltaricaState *ss = state_->clone();
	    for (unsigned int i = 0; i<qVars->size(); ++i) {
		ss->setValue(vars[i], (**combi)[i]);
	    }
	    std::pair<Value *,landmarkType*> * v = visitLM(e->getExpr());
	    if (v->first->isBool()) {
		ValueBool * vb = (ValueBool*)v->first;
		if (!vb->allowedTop()) {
		    top = false;
		    bottom = true;
		} else {
		    addOrIntersectLM(tempLM, vtop, v->second,vtop);
		}
		if (vb->allowedBottom()) {
		    bottom = true;
		    addOrIntersectLM(lm_, vbot, v->second,vbot);
		}
	    }
	}
	val_ =  new ValueBool(top,bottom);	
	if (top)
	    addOrIntersectLM(lm_, vtop, tempLM, vtop);
    } else {	
	top = false;
	bottom = true;
	for (std::vector<std::vector<Value*>*>::iterator combi = combinations->begin(); 
	     combi != combinations->end() ; ++combi) {
	    AltaricaState *ss = state_->clone();
	    for (unsigned int i = 0; i<qVars->size(); ++i) {
		ss->setValue(vars[i], (**combi)[i]);
	    }
	    std::pair<Value *, landmarkType*> * v = visitLM(e->getExpr());
	    if (v->first->isBool()) {
		ValueBool * vb = (ValueBool*) v->first;
		if (vb->allowedTop()) {
		    top = true;
		    addOrIntersectLM(lm_, vtop, v->second, vtop);
		}
		if (!vb->allowedBottom()) {
		    bottom = false;	
		} else {
		    addOrIntersectLM(tempLM, vbot, v->second, vbot);
		}	    
	    }
	}	
	
	val_ = new ValueBool(top,bottom);
	if (bottom)
	     addOrIntersectLM(lm_, vbot, tempLM, vbot);
    }
    //clean combinations
    combinations->clear();
    delete(combinations);
}


void ExpressionEvaluatorLandmark::visitLOG(const ExpressionLOG *e)  {
    std::cout << "VISITING " << e->toString();
    std::cout << "LMS" << std::endl << lms_->toString();
    bool oldAssert = assert_;
    assert_ = false;
    std::pair<Value *,landmarkType*> * lv = visitLM(e->getLeft());
    std::pair<Value *,landmarkType*> * rv = visitLM(e->getRight());
    assert_ = oldAssert;
    lm_ = new landmarkType();    
    std::vector<Value*> * vals, *vals2;
    ValueBool * top = new ValueBool(true,false);
    ValueBool * bottom = new ValueBool(false,true);
    Value * temp;
    bool erased;
    if (!assert_) {
	switch (e->getType()) {
	case 0: 
	    val_ = new ValueBool(lv->first->hasIntersection(rv->first),lv->first->pDifferent(rv->first));
	    if (((ValueBool*)val_)->allowedTop()) {
		temp = lv->first->clone();
		temp->intersectValue(rv->first);
		vals = temp->getSingletons();
		for (std::vector<Value*>::iterator i = vals->begin(); i!=vals->end(); ++i) {
		    addOrIntersectLM(lm_, top, lv->second, *i);
		    addOrIntersectLM(lm_, top, rv->second, *i);
		}
		delete temp;
	    }
	    if (((ValueBool*)val_)->allowedBottom()) {
		vals = lv->first->getSingletons();		
		vals2 = rv->first->getSingletons();
		
		erased = false;
		for (std::vector<Value*>::iterator j = vals2->begin(); j!=vals2->end();++j) {
		    for (std::vector<Value*>::iterator i = vals->begin(); i!=vals->end() && !erased;++i) {
			if ((*i)->equals(*j)) {
			    i = vals->erase(i);
			    erased = true;
			}			    
		    }
		    if (!erased)
			vals->push_back(*j);
		}		    

		for (std::vector<Value*>::iterator i = vals->begin(); i!=vals->end(); ++i) {
		    addOrIntersectLM(lm_, bottom, lv->second, *i);
		    addOrIntersectLM(lm_, bottom, rv->second, *i);
		}
	    }
	    
	    Value::deleteIfPossible(lv->first);
	    Value::deleteIfPossible(rv->first);
	    break;
	case 1: 
	    val_ = new ValueBool(lv->first->pDifferent(rv->first), lv->first->hasIntersection(rv->first));
	    if (((ValueBool*)val_)->allowedBottom()) {
		temp = lv->first;
		temp->intersectValue(rv->first);
		vals = temp->getSingletons();
		for (std::vector<Value*>::iterator i = vals->begin(); i!=vals->end(); ++i) {
		    addOrIntersectLM(lm_, bottom, lv->second, *i);
		    addOrIntersectLM(lm_, bottom, rv->second, *i);
		}
		delete temp;
	    }
	    if (((ValueBool*)val_)->allowedTop()) {		
		vals = lv->first->getSingletons();		
		vals2 = rv->first->getSingletons();		
		erased = false;
		for (std::vector<Value*>::iterator j = vals2->begin(); j!=vals2->end();++j) {
		    for (std::vector<Value*>::iterator i = vals->begin(); i!=vals->end() && !erased;++i) {
			if ((*i)->equals(*j)) {
			    i = vals->erase(i);
			    erased = true;
			}			    
		    }
		    if (!erased)
			vals->push_back(*j);
		}		    

		for (std::vector<Value*>::iterator i = vals->begin(); i!=vals->end(); ++i) {
		    addOrIntersectLM(lm_, top, rv->second, *i);
		    addOrIntersectLM(lm_, top, lv->second, *i);
		}
	    }
	    Value::deleteIfPossible(lv->first);
	    Value::deleteIfPossible(rv->first);
	    break;
	case 2: 
	    if (lv->first->isBool()) {
		ValueBool * vb = (ValueBool*) lv;
		if (vb->allowedTop() && !vb->allowedBottom()) {
		    val_ =  rv->first;	
		    vals = val_->getSingletons();
		    for (std::vector<Value*>::iterator i = vals->begin(); i!= vals->end(); ++i) {
			addOrIntersectLM(lm_, *i, rv->second, *i);
			addOrIntersectLM(lm_, *i, lv->second, vb);
		    }
		} else {
		    val_ = new ValueBool(true,false);
		    vb = new ValueBool(false,true);
		    addOrIntersectLM(lm_, val_, lv->second, vb);
		    Value::deleteIfPossible(rv->first);		
		}
		Value::deleteIfPossible(lv->first);
	    } else {
		BOOST_THROW_EXCEPTION(std::runtime_error("non boolean at left of implies"  +e->toString()));
	    }
	    break;
	}
	
    } else {
	bool doAffect = false;
	const ExpressionMEMBER * em;
	std::vector<Variable*> * v;
	Value * res;

	if (e->getType() != 2 && (rv->first->isBool() != lv->first->isBool() || 
				  rv->first->isInt() != lv->first->isInt() || 
				  rv->first->isSymbol() != lv->first->isSymbol())) {
	    BOOST_THROW_EXCEPTION(std::runtime_error("LOGICAL op on different types" + e->toString()));	
	     return;
	}
	    

	switch (e->getType()) {
	case 0: 
	    if (lv->first->constrained()) {  
		val_ = new ValueBool(lv->first->hasIntersection(rv->first),lv->first->pDifferent(rv->first)); 
		if (((ValueBool*)val_)->allowedTop()) {
		    temp = lv->first;
		    temp->intersectValue(rv->first);
		    vals = temp->getSingletons();
		    for (std::vector<Value*>::iterator i = vals->begin(); i!=vals->end(); ++i) {
			addOrIntersectLM(lm_, top, lv->second, *i);
			addOrIntersectLM(lm_, top, rv->second, *i);
		    }
		    delete temp;
		}
		if (((ValueBool*)val_)->allowedBottom()) {
		    vals = lv->first->getSingletons();		
		    vals2 = rv->first->getSingletons();	       
		    erased = false;
		    for (std::vector<Value*>::iterator j = vals2->begin(); j!=vals2->end();++j) {
			for (std::vector<Value*>::iterator i = vals->begin(); i!=vals->end() && !erased;++i) {
			    if ((*i)->equals(*j)) {
				i = vals->erase(i);
			    erased = true;
			    }			    
			}
			if (!erased)
			    vals->push_back(*j);
		    }		    
		    

		    for (std::vector<Value*>::iterator i = vals->begin(); i!=vals->end(); ++i) {
			addOrIntersectLM(lm_, bottom, rv->second, *i);
			addOrIntersectLM(lm_, bottom, lv->second, *i);
		    }
		    Value::deleteIfPossible(rv->first);
		    Value::deleteIfPossible(lv->first);
		    doAffect = false;
		}
	    } else {
		res = lv->first->clone();
		res->intersectValue(rv->first);
		doAffect = true;
		Value::deleteIfPossible(rv->first);		
		Value::deleteIfPossible(lv->first);
		lm_ = rv->second;
		val_ = res;
	    } 		    	    
	    if (doAffect) {
		em = dynamic_cast<const ExpressionMEMBER*>(e->getLeft());      
		if (em != NULL)  // we have to do the affectation
      state_->setValue(em->getVariable(node_,amodel_),val_);
		std::vector<Value*> * newVals = val_->getSingletons();
		landmarkType * toChange = (*(lms_->getFlowLabels()))[em->getVariable(node_,amodel_)->getIndex()];
		for (std::vector<Value*>::const_iterator i = newVals->begin(); i!= newVals->end(); ++i) {
		    addOrIntersectLM(toChange,*i,rv->second,*i);
		}
		
		
	    }
	    break;
	case 1: 
	    if (lv->first->constrained()) {
		val_ = new ValueBool(lv->first->pDifferent(rv->first), lv->first->hasIntersection(rv->first));
		Value::deleteIfPossible(rv->first);
		Value::deleteIfPossible(lv->first);
		doAffect = false;
		
		if (((ValueBool*)val_)->allowedBottom()) {
		    temp = lv->first;
		    temp->intersectValue(rv->first);
		    vals = temp->getSingletons();
		    for (std::vector<Value*>::iterator i = vals->begin(); i!=vals->end(); ++i) {
			addOrIntersectLM(lm_, bottom, lv->second, *i);
			addOrIntersectLM(lm_, bottom, rv->second, *i);
		    }
		    delete temp;
		}
		if (((ValueBool*)val_)->allowedTop()) {
		    vals = lv->first->getSingletons();		
		    vals2 = rv->first->getSingletons();	       
		    erased = false;
		    for (std::vector<Value*>::iterator j = vals2->begin(); j!=vals2->end();++j) {
			for (std::vector<Value*>::iterator i = vals->begin(); i!=vals->end() && !erased;++i) {
			    if ((*i)->equals(*j)) {
				i = vals->erase(i);
			    erased = true;
			    }			    
			}
			if (!erased)
			    vals->push_back(*j);
		    }		    		    

		    for (std::vector<Value*>::iterator i = vals->begin(); i!=vals->end(); ++i) {
			addOrIntersectLM(lm_, bottom, rv->second, *i);
			addOrIntersectLM(lm_, bottom, lv->second, *i);
		    }
		}
		    
		    
	    } else {
		val_ = rv->first->getComplement();
		lm_ = NULL;
		Value::deleteIfPossible(rv->first);
		Value::deleteIfPossible(lv->first);
		
		doAffect = true;
	    }
	    
	    
	    
		
	    if (doAffect) {
		em = dynamic_cast <const ExpressionMEMBER*> (e->getLeft());
		if (em != NULL) 
      state_->setValue(em->getVariable(node_,amodel_),val_);
		std::vector<Value*> * newVals = val_->getSingletons();
		landmarkType * toChange = (*(lms_->getFlowLabels()))[em->getVariable(node_,amodel_)->getIndex()];
		for (std::vector<Value*>::const_iterator i = newVals->begin(); i!= newVals->end(); ++i) {
		    addOrIntersectLM(toChange,*i,rv->second,*i);
		}
		
	    }
	    break;
	case 2: 
	    if (lv->first->isBool()) {
		ValueBool * lb = (ValueBool*) lv;
		if (lb->allowedTop() && !lb->allowedBottom()) {
		    Value::deleteIfPossible(lb);
		    val_ = rv->first;
		    vals = val_->getSingletons();
		    for (std::vector<Value*>::iterator i = vals->begin(); i!= vals->end(); ++i) {
			addOrIntersectLM(lm_, *i, rv->second, *i);
			addOrIntersectLM(lm_, *i, lv->second, lb);
		    }
		} else {
		    Value::deleteIfPossible(lb);
		    Value::deleteIfPossible(rv->first);
		    val_=  new ValueBool(true,false); 
		    lb = new ValueBool(false,true);
		    addOrIntersectLM(lm_, val_, lv->second, lb);
		}
	    } else 
		BOOST_THROW_EXCEPTION(std::runtime_error("LOGICAL => with non-bool left argument"));		    
	    break;
	default: BOOST_THROW_EXCEPTION(std::runtime_error("BAD COMPARISON TYPE IN LOG COMP"));	
	}
    }    
    std::cout << "END OF VISIT OF " << e->toString() ;
    std::cout << "LM_ "; printLM(lm_);
    std::cout << "LMS :" << lms_->toString();

}
	





std::vector<std::vector<Value*>*> * ExpressionEvaluatorLandmark::buildCombinations(std::vector<Variable*> * vars) {
    if (vars->size() == 0)
	return new std::vector<std::vector<Value*>*>();
    Variable * v = vars->front();
    vars->erase(vars->begin());
    std::vector<std::vector<Value*>*> * comb = buildCombinations(vars);
    unsigned int s = comb->size();
    DiscreteDomain * dd = (DiscreteDomain*) v->getDomain();
    for (int j = dd->getMin(); j<dd->getMax(); ++j)
	for (unsigned int i = 0; i<s; ++i) 
	    comb->push_back(new std::vector<Value*>((*comb)[i]->begin(),(*comb)[i]->end()));
    int j = dd->getMin();
    for (unsigned int i =0; i<comb->size(); ++i) {
	(*comb)[i]->insert((*comb)[i]->begin(), dd->getValue(j++));	
    }
    return comb;       
}
