|
@@ -0,0 +1,675 @@
|
|
|
+/*
|
|
|
+ * CFormula.cpp
|
|
|
+ *
|
|
|
+ * Created on: Oct 1, 2016
|
|
|
+ * Author: Sina M.Baharlou
|
|
|
+ */
|
|
|
+
|
|
|
+#include "CFormula.hpp"
|
|
|
+
|
|
|
+CFormula::CFormula():
|
|
|
+nVars(0),
|
|
|
+nClauses(0),
|
|
|
+fStats{0,0,0},
|
|
|
+fVars(NULL),
|
|
|
+fPortions(NULL),
|
|
|
+tPortion(0),
|
|
|
+nLit(NULL),
|
|
|
+evalArray(NULL),
|
|
|
+
|
|
|
+evalClause(NULL),
|
|
|
+varMap(NULL),
|
|
|
+
|
|
|
+clCounter(0),
|
|
|
+
|
|
|
+greedyFactor(DEFAULT_GREEDY_FACTOR),
|
|
|
+arrayFiller(NULL),
|
|
|
+nbSatisfiedClausesFill(0),
|
|
|
+nbSatisfiedClausesSolve(0),
|
|
|
+lastFillMethod(0),
|
|
|
+lastHeuristic(0),
|
|
|
+ite(0)
|
|
|
+{
|
|
|
+
|
|
|
+ this->fType.clear();
|
|
|
+ this->fComments.clear();
|
|
|
+
|
|
|
+ // -- Initializing distribution variables --
|
|
|
+
|
|
|
+ rndReal=std::uniform_real_distribution<float>(0.0,1.0);
|
|
|
+ rndMethod=std::uniform_int_distribution<int>(FIRST_FILL_METHOD,LAST_FILL_METHOD);
|
|
|
+ rndHeuristic=std::uniform_int_distribution<int>(FIRST_H_METHOD,LAST_H_METHOD);
|
|
|
+
|
|
|
+ // -- Init random engine --
|
|
|
+
|
|
|
+ struct timespec ts;
|
|
|
+ unsigned theTick = 0U;
|
|
|
+ clock_gettime( CLOCK_REALTIME, &ts );
|
|
|
+ theTick = ts.tv_nsec / 1000000;
|
|
|
+ theTick += ts.tv_sec * 1000;
|
|
|
+ rndEngine.seed(theTick);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+bool CFormula::initFormula(const char* filename)
|
|
|
+{
|
|
|
+
|
|
|
+ // -- Initialize variables --
|
|
|
+
|
|
|
+ this->cFormula.empty();
|
|
|
+ this->fComments.empty();
|
|
|
+ this->fType.empty();
|
|
|
+ this->fStats={0,0,0};
|
|
|
+ this->clCounter=0;
|
|
|
+ bool fReached=false;
|
|
|
+
|
|
|
+
|
|
|
+ // -- Free previously allocated variables --
|
|
|
+
|
|
|
+ if (this->fVars) free(this->fVars);
|
|
|
+ if (this->fPortions) free(this->fPortions);
|
|
|
+ if (this->nLit) free(this->nLit);
|
|
|
+ if (this->evalArray) free(this->evalArray);
|
|
|
+ if (this->arrayFiller) free(this->arrayFiller);
|
|
|
+ if (this->varMap) free(this->varMap);
|
|
|
+ if (this->evalClause) free(this->evalClause);
|
|
|
+
|
|
|
+ // -- Open input file --
|
|
|
+
|
|
|
+ ifstream input_file;
|
|
|
+ input_file.open(filename);
|
|
|
+
|
|
|
+ if (!input_file.is_open())
|
|
|
+ {
|
|
|
+ printf("STD Error: cannot open '%s'.",filename);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // -- Parse the provided file --
|
|
|
+
|
|
|
+ std::string line;
|
|
|
+ while (std::getline(input_file, line))
|
|
|
+ {
|
|
|
+ // -- get the flag (can be 'c' or 'p') --
|
|
|
+ char flag=line[0];
|
|
|
+ std::vector<string> tokens;
|
|
|
+
|
|
|
+ switch (flag)
|
|
|
+ {
|
|
|
+
|
|
|
+ case COMMENT_FLAG: // -- Comment line has reached --
|
|
|
+
|
|
|
+ // -- Add to comment string --
|
|
|
+ this->fComments.append(&line[1]);
|
|
|
+ this->fComments.append("\n");
|
|
|
+ break;
|
|
|
+
|
|
|
+
|
|
|
+ case PROBLEM_FLAG: // -- Problem line has reached --
|
|
|
+
|
|
|
+ // -- Tokenize current line --
|
|
|
+ tokens.empty();
|
|
|
+ tokens=tokenize(&line[1]," ");
|
|
|
+
|
|
|
+ // -- Check if the syntax if correct in order to parse the parameters --
|
|
|
+ if (tokens.size()<3)
|
|
|
+ {
|
|
|
+ printf("There is a syntax error in the problem definition.");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // -- Assign the variables --
|
|
|
+ this->fType=tokens[0];
|
|
|
+ this->nVars=stoi(tokens[1])+1; // -- starts from 1
|
|
|
+ this->nClauses=stoi(tokens[2]);
|
|
|
+ fReached=true;
|
|
|
+
|
|
|
+ // -- allocate the arrays
|
|
|
+ this->fVars=new bool[this->nVars];
|
|
|
+ this->fPortions= new float[this->nVars];
|
|
|
+ this->nLit=new int[this->nVars];
|
|
|
+ this->evalArray=new int[this->nVars];
|
|
|
+ this->evalClause=new bool[this->nClauses];
|
|
|
+ this->varMap=new std::vector<int>[this->nVars];
|
|
|
+
|
|
|
+ // -- initialize the arrays
|
|
|
+ memset(this->fVars,0,this->nVars*sizeof(bool));
|
|
|
+ memset(this->fPortions,0,this->nVars*sizeof(float));
|
|
|
+ memset(this->nLit,0,this->nVars*sizeof(int));
|
|
|
+ memset(this->evalArray,0,this->nVars*sizeof(int));
|
|
|
+ memset(this->evalClause,0,this->nClauses*sizeof(bool));
|
|
|
+
|
|
|
+ // -- Instantiate the arrayFiller class
|
|
|
+ this->arrayFiller=new ArrayFiller(this->fVars,this->nVars);
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+
|
|
|
+ case END_FLAG: // -- End of the formula has reached --
|
|
|
+ input_file.close();
|
|
|
+
|
|
|
+ // -- Ppdate stats --
|
|
|
+ this->tPortion=(float)this->fStats.nPosLits/this->fStats.nLits;
|
|
|
+ for (unsigned int i=1;i<this->nVars;i++)
|
|
|
+ this->fPortions[i]/=(float)this->nLit[i];
|
|
|
+
|
|
|
+ // -- Init random filler --
|
|
|
+ this->arrayFiller->setPortionRate(this->tPortion);
|
|
|
+ this->arrayFiller->setPortionArray(this->fPortions);
|
|
|
+ this->arrayFiller->fillArray(PORTION_EL_FILL);
|
|
|
+ return true;
|
|
|
+ break;
|
|
|
+
|
|
|
+ default: // -- Clause line has reached--
|
|
|
+ if (!fReached)
|
|
|
+ continue;
|
|
|
+ this->cFormula.push_back(parseClause(&line[0]," "));
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+bool CFormula::evalFormulaQ(unsigned int varIndex,int& clNum)
|
|
|
+{
|
|
|
+
|
|
|
+ bool fEval=true;
|
|
|
+ clNum=0;
|
|
|
+
|
|
|
+ // -- check through the modified clauses --
|
|
|
+ for (unsigned int i=0;i<this->varMap[varIndex].size();i++)
|
|
|
+ {
|
|
|
+ // -- get the clause --
|
|
|
+ int cIndex=this->varMap[varIndex].at(i);
|
|
|
+ Clause cl=this->cFormula[cIndex];
|
|
|
+
|
|
|
+ // -- for each literal
|
|
|
+ for (unsigned int j=0;j<cl.size();j++)
|
|
|
+ {
|
|
|
+
|
|
|
+ Literal lit=cl[j];
|
|
|
+
|
|
|
+ // -- get the index and sign
|
|
|
+ bool neg=(lit<0);
|
|
|
+ int index=abs(lit);
|
|
|
+ // -- evaluate the literal
|
|
|
+ bool litEval=neg^this->fVars[index];
|
|
|
+ this->evalClause[cIndex]=litEval; // -- update clause truth list
|
|
|
+
|
|
|
+ // -- if positive -> clause will be evaluated as positive
|
|
|
+ if (litEval)
|
|
|
+ break;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // -- evaluate the whole formula --
|
|
|
+
|
|
|
+ for (unsigned int i=0;i<this->cFormula.size();i++)
|
|
|
+ {
|
|
|
+ bool evalClause=this->evalClause[i];
|
|
|
+ fEval&=evalClause;
|
|
|
+ if (evalClause)clNum++;
|
|
|
+ }
|
|
|
+ return fEval;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+bool CFormula::evalFormula(int& clNum)
|
|
|
+{
|
|
|
+
|
|
|
+
|
|
|
+ bool fEval=true;
|
|
|
+ clNum=0;
|
|
|
+
|
|
|
+
|
|
|
+ for (unsigned int i=0;i<this->cFormula.size();i++)
|
|
|
+ {
|
|
|
+
|
|
|
+ // -- get the clause --
|
|
|
+ Clause cl=this->cFormula[i];
|
|
|
+ bool clEval=false;
|
|
|
+
|
|
|
+ // -- for each literal
|
|
|
+ for (unsigned int j=0;j<cl.size();j++)
|
|
|
+ {
|
|
|
+
|
|
|
+ Literal lit=cl[j];
|
|
|
+
|
|
|
+ // -- get the index and sign
|
|
|
+ bool neg=(lit<0);
|
|
|
+ int index=abs(lit);
|
|
|
+ // -- evaluate the literal
|
|
|
+ bool litEval=neg^this->fVars[index];
|
|
|
+
|
|
|
+ this->evalClause[i]=litEval;
|
|
|
+
|
|
|
+ // -- if positive -> clause will be evaluated as positive
|
|
|
+ if (litEval)
|
|
|
+ {
|
|
|
+ clEval=true;
|
|
|
+ clNum++;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // -- and it with current evaluation of formula
|
|
|
+ fEval&=clEval;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return fEval;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+bool CFormula::startGSAT(int iterations,int maxTry,int fillMethod,int hMethod)
|
|
|
+{
|
|
|
+ float initGuessMean=0; // -- initial guess average
|
|
|
+ float negClauseMean=0; // -- average number of negative clauses
|
|
|
+ float elaborateMean=0; // -- averate number of elaboration
|
|
|
+ bool fEval=false;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i=0;i<iterations;i++)
|
|
|
+ {
|
|
|
+ int initGuess=0;
|
|
|
+ int clNum=0;
|
|
|
+ fEval=false;
|
|
|
+
|
|
|
+ // -- randomly select the filler method --
|
|
|
+ FillMethod fMethod;
|
|
|
+ if (fillMethod==-1)
|
|
|
+ fMethod=getRandomMethod();
|
|
|
+ else
|
|
|
+ fMethod=(FillMethod)fillMethod;
|
|
|
+ lastFillMethod=fMethod;
|
|
|
+ ite++;
|
|
|
+ // -- randomly select the heuristic method --
|
|
|
+ HeuristicMethod heuristic;
|
|
|
+ if (hMethod==-1)
|
|
|
+ heuristic=getRandomHeuristic();
|
|
|
+ else
|
|
|
+ heuristic=(HeuristicMethod)hMethod;
|
|
|
+ lastHeuristic=heuristic;
|
|
|
+
|
|
|
+ this->arrayFiller->fillArray(fMethod);
|
|
|
+
|
|
|
+ // -- evaluate the function
|
|
|
+ fEval=this->evalFormula(clNum);
|
|
|
+ initGuess=clNum;
|
|
|
+ nbSatisfiedClausesFill=initGuess;
|
|
|
+ initGuessMean+=initGuess;
|
|
|
+
|
|
|
+ // -- return if already found the solution
|
|
|
+ if (fEval)
|
|
|
+ break;
|
|
|
+
|
|
|
+
|
|
|
+ for (int j=0;j<maxTry;j++)
|
|
|
+ {
|
|
|
+ int choice=0;
|
|
|
+
|
|
|
+
|
|
|
+ // -- select the choice with the given heuristics --
|
|
|
+
|
|
|
+ switch (heuristic)
|
|
|
+ {
|
|
|
+
|
|
|
+ case FIRST_BEST:
|
|
|
+ choice=this->getBestChoice(true);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case RND_BEST:
|
|
|
+ choice=this->getBestChoice();
|
|
|
+ break;
|
|
|
+
|
|
|
+ case RND_DIST:
|
|
|
+ choice=this->getRndBest();
|
|
|
+ break;
|
|
|
+
|
|
|
+ case RND:
|
|
|
+ choice=(int)(rndReal(rndEngine)*this->nVars);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case RND_GREEDY:
|
|
|
+ if (this->takeBestChoice())
|
|
|
+ choice=this->getBestChoice();
|
|
|
+ else
|
|
|
+ choice=this->getRndBest();
|
|
|
+ break;
|
|
|
+
|
|
|
+ case WALK_SAT:
|
|
|
+ choice=this->walkSatChoice();
|
|
|
+ break;
|
|
|
+
|
|
|
+ case GSAT_WSAT:
|
|
|
+ if (this->takeGW())
|
|
|
+ choice=this->getBestChoice();
|
|
|
+ else
|
|
|
+ choice=this->walkSatChoice();
|
|
|
+ break;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ toggle(this->fVars[choice]);
|
|
|
+ fEval=this->evalFormulaQ(choice,clNum);//this->evalFormula(clNum);
|
|
|
+
|
|
|
+ if (fEval)
|
|
|
+ break;
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ negClauseMean+=this->nClauses-clNum;
|
|
|
+ elaborateMean+=clNum-initGuess;
|
|
|
+ nbSatisfiedClausesSolve=clNum;
|
|
|
+
|
|
|
+ //printf("[iteration %d, fill :%d, heuristic :%d] - init Guess :%d - final Guess :%d - model found :%d\n",i,fMethod,heuristic,initGuess,clNum,fEval);
|
|
|
+
|
|
|
+ if (fEval)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /*printf("Elaborate mean :%f\n",elaborateMean/(float)i);
|
|
|
+ printf("Initial guess mean :%f\n",initGuessMean/(float)i);
|
|
|
+ printf("Neg clause mean :%f\n",negClauseMean/(float)i);*/
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ return fEval;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void CFormula::setGreedyFactor(float factor)
|
|
|
+{
|
|
|
+ this->greedyFactor=factor;
|
|
|
+}
|
|
|
+
|
|
|
+void CFormula::setGWFactor(float factor)
|
|
|
+{
|
|
|
+ this->gwFactor=factor;
|
|
|
+}
|
|
|
+
|
|
|
+std::vector<string> CFormula::tokenize(char*input,const char*split)
|
|
|
+{
|
|
|
+ char * token;
|
|
|
+ std::vector<string> token_vec;
|
|
|
+
|
|
|
+ token = strtok (input,split);
|
|
|
+ while (token != NULL)
|
|
|
+ {
|
|
|
+ token_vec.push_back(string(token));
|
|
|
+ token = strtok (NULL, " ");
|
|
|
+ }
|
|
|
+ return token_vec;
|
|
|
+}
|
|
|
+
|
|
|
+Clause CFormula::parseClause(char*input,const char*split)
|
|
|
+{
|
|
|
+ char * token;
|
|
|
+ Clause cl;
|
|
|
+
|
|
|
+ token = strtok (input,split);
|
|
|
+ while (token != NULL)
|
|
|
+ {
|
|
|
+ Literal lit=stoi(token);
|
|
|
+ if (lit!=0)
|
|
|
+ {
|
|
|
+ int index=abs(lit);
|
|
|
+ // -- update the stats
|
|
|
+
|
|
|
+ this->varMap[index].push_back(clCounter);
|
|
|
+
|
|
|
+ if (lit>0)
|
|
|
+ {
|
|
|
+ this->fStats.nPosLits++;
|
|
|
+ this->fPortions[index]+=1;
|
|
|
+ }
|
|
|
+ else this->fStats.nNegLits++;
|
|
|
+ fStats.nLits++;
|
|
|
+ this->nLit[index]++;
|
|
|
+ // --
|
|
|
+
|
|
|
+ cl.push_back(lit);
|
|
|
+ }
|
|
|
+ token = strtok (NULL, " ");
|
|
|
+ }
|
|
|
+
|
|
|
+ this->clCounter++;
|
|
|
+
|
|
|
+ return cl;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+FillMethod CFormula::getRandomMethod()
|
|
|
+{
|
|
|
+ return (FillMethod)rndMethod(rndEngine);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+HeuristicMethod CFormula::getRandomHeuristic()
|
|
|
+{
|
|
|
+ return (HeuristicMethod)rndHeuristic(rndEngine);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+bool CFormula::takeBestChoice()
|
|
|
+{
|
|
|
+
|
|
|
+ double random=rndReal(rndEngine); // -- Get a double random number between 0 and 1
|
|
|
+
|
|
|
+ // -- Check if GSAT should take a best action
|
|
|
+ if (random<=this->greedyFactor)
|
|
|
+ return true;
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+bool CFormula::takeGW()
|
|
|
+{
|
|
|
+
|
|
|
+ double random=rndReal(rndEngine); // -- Get a double random number between 0 and 1
|
|
|
+
|
|
|
+ // -- Check if GSAT should take a best action
|
|
|
+ if (random<=this->gwFactor)
|
|
|
+ return true;
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void CFormula::evalMove(int&min,int&max)
|
|
|
+{
|
|
|
+ min=std::numeric_limits<int>::max();
|
|
|
+ max=0;
|
|
|
+
|
|
|
+ for (unsigned int i=1;i<this->nVars;i++)
|
|
|
+ {
|
|
|
+ int clNum=0;
|
|
|
+ int temp=0;
|
|
|
+ toggle(this->fVars[i]);
|
|
|
+
|
|
|
+ this->evalFormulaQ(i,clNum); //this->evalFormula(clNum);
|
|
|
+ toggle(this->fVars[i]);
|
|
|
+ this->evalFormulaQ(i,temp);
|
|
|
+
|
|
|
+ this->evalArray[i]=clNum;
|
|
|
+ if (clNum>max) max=clNum;
|
|
|
+ if (clNum<min) min=clNum;
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+std::vector<int> CFormula::evalUnsatClause(int clIndex,int&min,int&max)
|
|
|
+{
|
|
|
+ min=std::numeric_limits<int>::max();
|
|
|
+ max=0;
|
|
|
+
|
|
|
+ Clause cl=this->cFormula[clIndex];
|
|
|
+ std::vector<int> evalArray;
|
|
|
+
|
|
|
+ for (unsigned int i=0;i<cl.size();i++)
|
|
|
+ {
|
|
|
+ Literal lit=cl[i];
|
|
|
+ int index=abs(lit);
|
|
|
+
|
|
|
+ int clNum=0;
|
|
|
+ int temp=0;
|
|
|
+
|
|
|
+ // -- evaluate the positive clauses
|
|
|
+ toggle(this->fVars[index]);
|
|
|
+ this->evalFormulaQ(index,clNum); //this->evalFormula(clNum);
|
|
|
+ toggle(this->fVars[index]);
|
|
|
+ this->evalFormulaQ(index,temp);
|
|
|
+ // --
|
|
|
+
|
|
|
+ evalArray.push_back(clNum);
|
|
|
+ if (clNum>max) max=clNum;
|
|
|
+ if (clNum<min) min=clNum;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return evalArray;
|
|
|
+}
|
|
|
+
|
|
|
+int CFormula::getBestChoice(bool retFirst)
|
|
|
+{
|
|
|
+ int min,max;
|
|
|
+ this->evalMove(min,max);
|
|
|
+ int bestCount=0;
|
|
|
+ std::vector<int> bestArray;
|
|
|
+
|
|
|
+ for (unsigned int i=1;i<this->nVars;i++)
|
|
|
+ {
|
|
|
+ if (this->evalArray[i]==max)
|
|
|
+ {
|
|
|
+ if (retFirst) return i; // -- return immediately the first choice
|
|
|
+
|
|
|
+ bestArray.push_back(i);
|
|
|
+ bestCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (bestCount==1)
|
|
|
+ return bestArray[0];
|
|
|
+
|
|
|
+ // -- randomly select the best choice
|
|
|
+ int rndIndex=(int)(rndReal(rndEngine)*bestCount);
|
|
|
+ return bestArray[rndIndex];
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+int CFormula::walkSatChoice(bool retFirst)
|
|
|
+{
|
|
|
+
|
|
|
+ // -- Randomly get one unsatisfied clause
|
|
|
+ int clIndex=this->getUnsatClause(retFirst);
|
|
|
+
|
|
|
+ int min,max;
|
|
|
+
|
|
|
+ // -- List the best choices
|
|
|
+ std::vector<int> evalArray=evalUnsatClause( clIndex,min,max);
|
|
|
+
|
|
|
+ // -- select randomly from the best choices
|
|
|
+ int bestCount=0;
|
|
|
+ std::vector<int> bestArray;
|
|
|
+
|
|
|
+ for (unsigned int i=0;i<evalArray.size();i++)
|
|
|
+ {
|
|
|
+ if (evalArray[i]==max)
|
|
|
+ {
|
|
|
+ if (retFirst) return i; // -- return immediately the first choice
|
|
|
+
|
|
|
+ bestArray.push_back(i);
|
|
|
+ bestCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (bestCount==1)
|
|
|
+ return abs(this->cFormula[clIndex].at(bestArray[0]));
|
|
|
+
|
|
|
+ // -- randomly select the best choice
|
|
|
+ int rndIndex=(int)(rndReal(rndEngine)*bestCount);
|
|
|
+
|
|
|
+ return abs(this->cFormula[clIndex].at(bestArray[rndIndex]));
|
|
|
+}
|
|
|
+
|
|
|
+int CFormula::getUnsatClause(bool retFirst)
|
|
|
+{
|
|
|
+
|
|
|
+ int clCount=0;
|
|
|
+ std::vector<int> clArray;
|
|
|
+
|
|
|
+ for (unsigned int i=0;i<this->nClauses;i++)
|
|
|
+ {
|
|
|
+ if (!this->evalClause[i])
|
|
|
+ {
|
|
|
+ if (retFirst) return i; // -- return immediately the first choice
|
|
|
+
|
|
|
+ clArray.push_back(i);
|
|
|
+ clCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (clCount==1)
|
|
|
+ return clArray[0];
|
|
|
+
|
|
|
+ // -- randomly select the best choice
|
|
|
+ int rndIndex=(int)(rndReal(rndEngine)*clCount);
|
|
|
+ return clArray[rndIndex];
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+int CFormula::getRndBest(bool exponential)
|
|
|
+{
|
|
|
+ int min,max;
|
|
|
+ float cum=0;
|
|
|
+ this->evalMove(min,max);
|
|
|
+ float normalizer=0;
|
|
|
+
|
|
|
+ // -- calculate the discrete probability distribution --
|
|
|
+ float probs[this->nVars];
|
|
|
+ float rnd =rndReal(rndEngine);
|
|
|
+
|
|
|
+ for (unsigned int i=1;i<this->nVars;i++)
|
|
|
+ {
|
|
|
+
|
|
|
+ probs[i]=(float)(this->evalArray[i]-min+DEFAULT_BIAS);
|
|
|
+
|
|
|
+ if (exponential)probs[i]=exp(probs[i]);
|
|
|
+ normalizer+=probs[i];
|
|
|
+ }
|
|
|
+
|
|
|
+ // -- sample from the distribution --
|
|
|
+ for (unsigned int i=1;i<this->nVars;i++)
|
|
|
+ {
|
|
|
+ cum+=probs[i]/normalizer;
|
|
|
+
|
|
|
+ if (cum>rnd)
|
|
|
+ return i;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|