hvariablestate.h

00001 /*
00002  * All of the documentation and software included in the
00003  * Alchemy Software is copyrighted by Stanley Kok, Parag
00004  * Singla, Matthew Richardson, Pedro Domingos, Marc
00005  * Sumner, Hoifung Poon, and Daniel Lowd.
00006  * 
00007  * Copyright [2004-07] Stanley Kok, Parag Singla, Matthew
00008  * Richardson, Pedro Domingos, Marc Sumner, Hoifung
00009  * Poon, and Daniel Lowd. All rights reserved.
00010  * 
00011  * Contact: Pedro Domingos, University of Washington
00012  * (pedrod@cs.washington.edu).
00013  * 
00014  * Redistribution and use in source and binary forms, with
00015  * or without modification, are permitted provided that
00016  * the following conditions are met:
00017  * 
00018  * 1. Redistributions of source code must retain the above
00019  * copyright notice, this list of conditions and the
00020  * following disclaimer.
00021  * 
00022  * 2. Redistributions in binary form must reproduce the
00023  * above copyright notice, this list of conditions and the
00024  * following disclaimer in the documentation and/or other
00025  * materials provided with the distribution.
00026  * 
00027  * 3. All advertising materials mentioning features or use
00028  * of this software must display the following
00029  * acknowledgment: "This product includes software
00030  * developed by Stanley Kok, Parag Singla, Matthew
00031  * Richardson, Pedro Domingos, Marc Sumner, Hoifung
00032  * Poon, and Daniel Lowd in the Department of Computer Science and
00033  * Engineering at the University of Washington".
00034  * 
00035  * 4. Your publications acknowledge the use or
00036  * contribution made by the Software to your research
00037  * using the following citation(s): 
00038  * Stanley Kok, Parag Singla, Matthew Richardson and
00039  * Pedro Domingos (2005). "The Alchemy System for
00040  * Statistical Relational AI", Technical Report,
00041  * Department of Computer Science and Engineering,
00042  * University of Washington, Seattle, WA.
00043  * http://www.cs.washington.edu/ai/alchemy.
00044  * 
00045  * 5. Neither the name of the University of Washington nor
00046  * the names of its contributors may be used to endorse or
00047  * promote products derived from this software without
00048  * specific prior written permission.
00049  * 
00050  * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF WASHINGTON
00051  * AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
00052  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00053  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00054  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY
00055  * OF WASHINGTON OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00056  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00057  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00058  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00059  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00060  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00061  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00062  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00063  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00064  * 
00065  */
00066 #ifndef HVARIABLESTATE_H_
00067 #define HVARIABLESTATE_H_
00068 
00069 #include "mrf.h"
00070 #include "Polynomial.h"
00071 #include "lbfgsp.h"
00072 #include "logsigmoid.h"
00073 #include "logichelper.h"
00074 #include <set>
00075 
00076 #define UNSOLVABLE 1010101  // This flag indicates that the constraint is not solvable.
00077 #define FLIPDIS 1010102  // This flag indicates that the discrete part of the constraint needs to be flipped
00078 //#define PICK2VAR 2020202
00079 #define CANNOTSATCURRENT -1000000
00080 
00081 const bool hvsdebug = false;
00082 const bool wjhvsdbg = false;
00083 
00084 const double SMALLVALUE = 0.0000000000001;
00085 double ABSBIG = 1111111111; //domain dependent, generally 10 * maximum abs value
00086 
00087 #define MIN(x,y) (x<y)?x:y
00088 #define MAX(x,y) (x>y)?x:y
00089 
00090 enum UNSATTYPE
00091 {
00092         UNSAT_DIS0,// dis == 0, and th > 0
00093         UNSAT_DIS1, // dis == 1, but cont < th     
00094         UNSAT_UNKNOWN
00095 };
00096 
00097 using namespace std;
00098 
00119 // Variable state containing information about both hybrid and discrete parts.
00120 class HVariableState
00121 {
00122 public:
00141         HVariableState(GroundPredicateHashArray* const& unknownQueries,
00142                 GroundPredicateHashArray* const& knownQueries,
00143                 Array<TruthValue>* const & knownQueryValues,
00144                 const Array<int>* const & allPredGndingsAreQueries,
00145                 const bool& markHardGndClauses,
00146                 const bool& trackParentClauseWts,
00147                 const MLN* const & mln, const Domain* const & domain,
00148                 const bool& lazy)
00149         {
00150       stillActivating_ = true;
00151     Timer timer;
00152     double startTime = timer.time();
00153 
00154                 if (hvsdebug)
00155                 {
00156                         cout << "from hybrid vs" << endl;
00157                 }
00158                 this->mln_ = (MLN*)mln;
00159                 this->domain_ = (Domain*)domain;
00160                 this->lazy_ = lazy;
00161 
00162                 // Instantiate information
00163                 bInitFromEvi_ = false;
00164                 baseNumAtoms_ = 0;
00165                 activeAtoms_ = 0;
00166                 numFalseClauses_ = 0;
00167                 costOfFalseClauses_ = 0.0;
00168                 weightSumDis_ = 0.0;
00169                 weightSumCont_ = 0.0;
00170                 costOfTotalFalseConstraints_ = 0.0;
00171                 totalFalseConstraintNum_ = 0;
00172                 costHybridFalseConstraint_ = 0.0;
00173                 hybridFalseConstraintNum_ = 0;
00174                 lowCost_ = LDBL_MAX;
00175                 lowBad_ = INT_MAX;
00176                 lowCostAll_ = LDBL_MAX;
00177                 lowBadAll_ = INT_MAX;
00178                 lowCostHybrid_ = LDBL_MAX;
00179                 lowBadHybrid_ = INT_MAX;
00180 
00182                 //WJ
00184                 hybridClauseNum_ = 0;
00185                 hybridFormulaNum_ = 0;
00186 
00187                 // Clauses and preds are stored in gndClauses_ and gndPreds_
00188                 gndClauses_ = new Array<GroundClause*>;
00189                 gndPreds_ = new Array<GroundPredicate*>;
00190                 bMaxOnly_ = false;
00191 
00192                 // Set the hard clause weight
00193                 setHardClauseWeight();
00194 
00195                 // Lazy version: Produce state with initial active atoms and clauses
00196                 if (lazy_)
00197                 {
00198         // Set number of non-evidence atoms from domain
00199       domain_->computeNumNonEvidAtoms();
00200       numNonEvAtoms_ = domain_->getNumNonEvidenceAtoms();
00201                         // Unknown preds are treated as false
00202                         domain_->getDB()->setPerformingInference(true);
00203                         clauseLimit_ = INT_MAX;
00204                         noApprox_ = false;
00205                         haveDeactivated_ = false;
00206 
00208                         // Get initial set of active atoms (atoms in unsat. clauses)
00209                         // Assumption is: all atoms are initially false except those in blocks
00210                         // One atom in each block is set to true and activated
00211       initBlocksRandom();
00212 
00213       //bool ignoreActivePreds = false;
00214       bool ignoreActivePreds = true;
00215       cout << "Getting initial active atoms ... " << endl;
00216                         getActiveClauses(newClauses_, ignoreActivePreds);
00217       cout << "done." << endl;
00218                         int defaultCnt = newClauses_.size();
00219                         long double defaultCost = 0;
00220 
00221                         for (int i = 0; i < defaultCnt; i++)
00222                         {
00223                                 if (newClauses_[i]->isHardClause())
00224                                         defaultCost += hardWt_;
00225                                 else
00226                                         defaultCost += abs(newClauses_[i]->getWt());
00227                         }
00228 
00229                         // Clear ground clauses in the ground preds
00230                         for (int i = 0; i < gndPredHashArray_.size(); i++)
00231                                 gndPredHashArray_[i]->removeGndClauses();
00232 
00233                         // Delete new clauses
00234                         for (int i = 0; i < newClauses_.size(); i++)
00235                                 delete newClauses_[i];
00236                         newClauses_.clear();
00237 
00238                         baseNumAtoms_ = gndPredHashArray_.size();
00239       cout << "Number of Baseatoms = " << baseNumAtoms_ << endl;
00240                         cout << "Default => Cost\t" << "******\t" << " Clause Cnt\t" << endl;
00241                         cout << "           " << defaultCost << "\t" << "******\t" << defaultCnt
00242                                 << "\t" << endl << endl;
00243 
00244                         // Set base atoms as active in DB
00245                         for (int i = 0; i < baseNumAtoms_; i++)
00246                         {
00247                                 domain_->getDB()->setActiveStatus(gndPredHashArray_[i], true);
00248                                 activeAtoms_++;        
00249                         }
00250 
00251                         // Get the initial set of active clauses
00252                         ignoreActivePreds = false;
00253       cout << "Getting initial active clauses ... ";
00254                         getActiveClauses(newClauses_, ignoreActivePreds);      
00255       cout << "done." << endl;
00256                 } // End lazy version
00257                 // Eager version: Use KBMC to produce the state
00258                 else
00259                 {
00260                         unePreds_ = unknownQueries;
00261                         knePreds_ = knownQueries;
00262                         knePredValues_ = knownQueryValues;
00263                         // MRF is built on known and unknown queries
00264                         int size = 0;
00265                         if (unknownQueries) size += unknownQueries->size();
00266                         if (knownQueries) size += knownQueries->size();
00267                         GroundPredicateHashArray* queries = new GroundPredicateHashArray(size);
00268                         if (unknownQueries) queries->append(unknownQueries);
00269                         if (knownQueries) queries->append(knownQueries);
00270                         //markHardGndClauses = true;
00271                         mrf_ = new MRF(queries, allPredGndingsAreQueries, domain_,
00272                                 domain_->getDB(), mln_, true,
00273                                 trackParentClauseWts, -1);
00274                         //delete to save space. Can be deleted because no more gndClauses are
00275                         //appended to gndPreds beyond this point
00276 
00277                         mrf_->deleteGndPredsGndClauseSets();
00278 
00279                         //do not delete the intArrRep in gndPreds_;
00280                         delete queries;
00281 
00282                         // Put ground clauses in newClauses_
00283                         newClauses_ = *(Array<GroundClause*>*)mrf_->getGndClauses();
00284 
00285                         // Put ground preds in the hash array
00286                         //const Array<GroundPredicate*>* gndPreds = mrf_->getGndPreds();
00287                         const GroundPredicateHashArray* gndPreds = mrf_->getGndPreds();
00288                         for (int i = 0; i < gndPreds->size(); i++)
00289                                 gndPredHashArray_.append((*gndPreds)[i]);
00290 
00291                         // baseNumAtoms_ are all atoms in eager version
00292                         baseNumAtoms_ = gndPredHashArray_.size();        
00293                 } // End eager version
00294 
00295                 // At this point, ground clauses are held in newClauses_
00296                 // and ground predicates are held in gndPredHashArray_
00297                 // for both versions
00298 
00299                 // Add the clauses and preds and fill info arrays
00300                 bool initial = true;
00301                 addNewClauses(initial);         
00302     
00303         cout << "[VS] ";
00304         Timer::printTime(cout,timer.time()-startTime);
00305         cout << endl;
00306         cout << ">>> DONE: Initial num. of clauses: " << getNumClauses() << endl;
00307         }
00308 
00313         ~HVariableState()
00314         {
00315       if (lazy_)
00316       {
00317         if (gndClauses_)
00318           for (int i = 0; i < gndClauses_->size(); i++)
00319             delete (*gndClauses_)[i];
00320 
00321         for (int i = 0; i < gndPredHashArray_.size(); i++)
00322         {
00323           gndPredHashArray_[i]->removeGndClauses();
00324           delete gndPredHashArray_[i];
00325                 }
00326       }
00327       else
00328       {
00329                         // MRF from eager version is deleted
00330         if (mrf_)
00331         {
00332           delete mrf_;
00333           mrf_ = NULL;
00334         }
00335                         //if (unePreds_) delete unePreds_;
00336                         //if (knePreds_) delete knePreds_;
00337                         //if (knePredValues_) delete knePredValues_;
00338                         for (int i = 0; i < contsolvers_.size(); i++)
00339                         {
00340                                 delete contsolvers_[i];
00341                         }
00342                 }    
00343         }
00344 
00352   void addNewClauses(bool initial)
00353   {
00354     if (initial) addNewClauses(ADD_CLAUSE_INITIAL, newClauses_);
00355     else addNewClauses(ADD_CLAUSE_REGULAR, newClauses_);
00356   }
00357 
00364   void addNewClauses(int addType, Array<GroundClause*> & clauses)
00365   {
00366     if (hvsdebug)
00367       cout << "Adding " << clauses.size() << " new clauses.." << endl;
00368 
00369       // Must be in mc-sat to add dead or sat
00370     if (!useThreshold_ &&
00371         (addType == ADD_CLAUSE_DEAD || addType == ADD_CLAUSE_SAT))
00372     {
00373       cout << ">>> [ERR] add_dead/sat but useThreshold_ is false" << endl;
00374       exit(0);
00375     }
00376 
00377       // Store the old number of clauses and atoms
00378     int oldNumClauses = getNumClauses();
00379     int oldNumAtoms = getNumAtoms();
00380 
00381       //gndClauses_->append(clauses);
00382     for (int i = 0; i < clauses.size(); i++)
00383     {
00384       gndClauses_->append(clauses[i]);
00385       clauses[i]->appendToGndPreds(&gndPredHashArray_);
00386     }
00387 
00388     gndPreds_->growToSize(gndPredHashArray_.size());
00389 
00390     int numAtoms = getNumAtoms();
00391     int numClauses = getNumClauses();
00392       // If no new atoms or clauses have been added, then do nothing
00393     if (numAtoms == oldNumAtoms && numClauses == oldNumClauses) return;
00394 
00395     if (hvsdebug) cout << "Clauses: " << numClauses << endl;
00396       // atomIdx starts at 1
00397     atom_.growToSize(numAtoms + 1, false);
00398 
00399     makeCost_.growToSize(numAtoms + 1, 0.0);
00400     breakCost_.growToSize(numAtoms + 1, 0.0);
00401     lowAtom_.growToSize(numAtoms + 1, false);
00402     fixedAtom_.growToSize(numAtoms + 1, 0);
00403 
00404       // Copy ground preds to gndPreds_ and set values in atom and lowAtom
00405     for (int i = oldNumAtoms; i < gndPredHashArray_.size(); i++)
00406     {
00407       (*gndPreds_)[i] = gndPredHashArray_[i];
00408 
00409       if (hvsdebug)
00410       {
00411         cout << "New pred " << i + 1 << ": ";
00412         (*gndPreds_)[i]->print(cout, domain_);
00413         cout << endl;
00414       }
00415 
00416       lowAtom_[i + 1] = atom_[i + 1] = 
00417         (domain_->getDB()->getValue((*gndPreds_)[i]) == TRUE) ? true : false;
00418     }
00419     clauses.clear();
00420 
00421     clause_.growToSize(numClauses);
00422     clauseCost_.growToSize(numClauses);
00423     falseClause_.growToSize(numClauses);
00424     whereFalse_.growToSize(numClauses);
00425     numTrueLits_.growToSize(numClauses);
00426     falseClauseLow_.growToSize(numClauses);
00427     watch1_.growToSize(numClauses);
00428     watch2_.growToSize(numClauses);
00429     isSatisfied_.growToSize(numClauses, false);
00430     deadClause_.growToSize(numClauses, false);
00431     threshold_.growToSize(numClauses, false);  
00432     occurence_.growToSize(2*numAtoms + 1);
00433 
00434     for (int i = oldNumClauses; i < numClauses; i++)
00435     {
00436       GroundClause* gndClause = (*gndClauses_)[i];
00437 
00438       if (hvsdebug)
00439       {
00440         cout << "New clause " << i << ": ";
00441         gndClause->print(cout, domain_, &gndPredHashArray_);
00442         cout << endl;
00443       }
00444 
00445         // Set thresholds for clause selection
00446       if (gndClause->isHardClause()) threshold_[i] = RAND_MAX;
00447       else
00448       {
00449         double w = gndClause->getWt();
00450         threshold_[i] = RAND_MAX*(1 - exp(-abs(w)));
00451         if (hvsdebug)
00452         {
00453           cout << "Weight: " << w << endl;            
00454         }
00455       }
00456       if (hvsdebug)
00457         cout << "Threshold: " << threshold_[i] << endl;            
00458 
00459       int numGndPreds = gndClause->getNumGroundPredicates();
00460       clause_[i].growToSize(numGndPreds);
00461       for (int j = 0; j < numGndPreds; j++) 
00462       {
00463         int lit = gndClause->getGroundPredicateIndex(j);
00464         clause_[i][j] = lit;
00465         int litIdx = 2*abs(lit) - (lit > 0);
00466         occurence_[litIdx].append(i);
00467       }
00468 
00469         // Hard clause weight has been previously determined
00470       if (inferenceMode_==MODE_SAMPLESAT)
00471       {
00472         if (gndClause->getWt()>0) clauseCost_[i] = 1;
00473         else clauseCost_[i] = -1;
00474       }
00475       else if (gndClause->isHardClause())
00476         clauseCost_[i] = hardWt_;
00477       else
00478         clauseCost_[i] = gndClause->getWt();
00479 
00480         // filter hard clauses
00481       if (inferenceMode_ == MODE_HARD && !gndClause->isHardClause())
00482       {
00483           // mark dead
00484         deadClause_[i] = true;
00485       }
00486     }
00487 
00488     if (addType == ADD_CLAUSE_DEAD)
00489     {
00490         // set to dead: no need for initMakeBreakCost, won't impact anyone
00491       for (int i = oldNumClauses; i < numClauses; i++)
00492       {
00493         deadClause_[i] = true;
00494       }
00495     }
00496     else if (addType == ADD_CLAUSE_SAT)
00497     {
00498         // set to dead: no need for initMakeBreakCost, won't impact anyone
00499       for (int i = oldNumClauses; i < numClauses; i++)
00500       {
00501         isSatisfied_[i]=true;
00502       }
00503     }
00504     else if (addType == ADD_CLAUSE_REGULAR)
00505     {
00506       if (useThreshold_)
00507         killClauses(oldNumClauses);
00508       else
00509         initMakeBreakCostWatch(oldNumClauses);
00510     }
00511 
00512     if (hvsdebug) 
00513       cout << "Done adding new clauses.." << endl;
00514   }
00515 
00523     /*
00524         void addNewClauses(bool initial)
00525         {
00526                 if (hvsdebug)
00527                         cout << "Adding " << newClauses_.size() << " new clauses.." << endl;
00528 
00529                 // Store the old number of clauses and atoms
00530                 int oldNumClauses = getNumClauses();
00531                 int oldNumAtoms = getNumAtoms();
00532 
00533                 gndClauses_->append(newClauses_);
00534                 gndPreds_->growToSize(gndPredHashArray_.size());
00535 
00536                 int numAtoms = getNumAtoms();
00537                 int numClauses = getNumClauses();
00538                 // If no new atoms or clauses have been added, then do nothing
00539                 if (numAtoms == oldNumAtoms && numClauses == oldNumClauses) return;
00540 
00541                 if (hvsdebug) cout << "Clauses num: " << numClauses << endl;
00542 
00543                 // atomIdx starts at 1
00544                 atom_.growToSize(numAtoms + 1, false);
00545                 atomEvi_.growToSize(numAtoms + 1, false);
00546                 atomsLast_.growToSize(numAtoms + 1, false);
00547 
00548                 makeCost_.growToSize(numAtoms + 1, 0.0);
00549                 breakCost_.growToSize(numAtoms + 1, 0.0);
00550                 lowAtom_.growToSize(numAtoms + 1, false);
00551                 fixedAtom_.growToSize(numAtoms + 1, false);
00552 
00553                 // Copy ground preds to gndPreds_ and set values in atom and lowAtom
00554                 for (int i = oldNumAtoms; i < gndPredHashArray_.size(); i++)
00555                 {
00556                         (*gndPreds_)[i] = gndPredHashArray_[i];
00557 
00558                         if (hvsdebug)
00559                         {
00560                                 cout << "New pred: ";
00561                                 (*gndPreds_)[i]->print(cout, domain_);
00562                                 cout << endl;
00563                         }
00564 
00565                         lowAtom_[i + 1] = atom_[i + 1] = 
00566                                 (domain_->getDB()->getValue((*gndPreds_)[i]) == TRUE) ? true : false;
00567                 }
00568 
00569                 newClauses_.clear();
00570                 clause_.growToSize(numClauses);
00571                 clauseCost_.growToSize(numClauses);
00572                 falseClause_.growToSize(numClauses);
00573                 whereFalse_.growToSize(numClauses);
00574                 numTrueLits_.growToSize(numClauses);
00575                 falseClauseLow_.growToSize(numClauses);
00576                 watch1_.growToSize(numClauses);
00577                 watch2_.growToSize(numClauses);
00578                 isSatisfied_.growToSize(numClauses, false);
00579                 deadClause_.growToSize(numClauses, false);
00580                 threshold_.growToSize(numClauses, false);
00581                 occurence_.growToSize(2*numAtoms + 1);
00582 
00583                 for (int i = oldNumClauses; i < numClauses; i++)
00584                 {
00585                         GroundClause* gndClause = (*gndClauses_)[i];
00586 
00587                         if (hvsdebug)
00588                         {
00589                                 cout << "New clause: ";
00590                                 gndClause->print(cout, domain_, &gndPredHashArray_);
00591                                 cout << endl;
00592                         }
00593 
00594                         // Set thresholds for clause selection, threshold for dis clauses could be precomputed
00595                         if (gndClause->isHardClause()) threshold_[i] = RAND_MAX; 
00596                         else
00597                         {
00598                                 double w = gndClause->getWt();
00599                                 threshold_[i] = RAND_MAX*(1 - exp(-abs(w)));
00600                                 if (hvsdebug)
00601                                 {
00602                                         cout << "Weight: " << w << endl;            
00603                                 }
00604                         }
00605                         if (hvsdebug)
00606                                 cout << "Threshold: " << threshold_[i] << endl;            
00607 
00608                         int numGndPreds = gndClause->getNumGroundPredicates();
00609                         clause_[i].growToSize(numGndPreds);
00610 
00611                         for (int j = 0; j < numGndPreds; j++) 
00612                         {
00613                                 // idx in gndClause + 1 (negated if neg. literal)
00614                                 //int idx = gndClause->getGroundPredicateIndex(j);
00615                                 //assert(idx >= 0);
00616                                 //int lit = (gndClause->getGroundPredicateSense(j)) ?
00617                                 //          idx + 1 : -(idx + 1);
00618                                 int lit = gndClause->getGroundPredicateIndex(j);
00619                                 clause_[i][j] = lit;
00620                                 int litIdx = 2*abs(lit) - (lit > 0);
00621                                 occurence_[litIdx].append(i);
00622                         }
00623 
00624                         // Hard clause weight has been previously determined
00625                         if (gndClause->isHardClause())
00626                         {
00627                                 clauseCost_[i] = hardWt_;
00628                         }
00629                         else
00630                         {
00631                                 clauseCost_[i] = gndClause->getWt();
00632                         }
00633                 }
00634 
00635                 if (!initial)
00636                 {
00637                         //initNumSatLiterals(1, oldNumClauses);
00638                         if (useThreshold_)
00639                         {
00640                                 killClauses(oldNumClauses);
00641                         }
00642                         else
00643                         {
00644                                 initMakeBreakCostWatch(oldNumClauses);
00645                         }
00646                 }
00647                 if (hvsdebug) cout << "Done adding new clauses.." << endl;
00648         }
00649 */
00650 
00654         void init()
00655         {
00656                 if (hvsdebug)
00657                 {
00658                         cout << "entering init" << endl;
00659                         cout << "discrete clause number: " << getNumClauses()
00660                  << ", hybrid clause number: " << hybridClauseNum_ << endl;
00661                 }
00662 
00663                 for (int i = 0; i < getNumClauses(); i++) 
00664                 {
00665                         numTrueLits_[i] = 0;
00666                         falseClause_[i] = 0;
00667                         whereFalse_[i] = 0;
00668                 }
00669                 
00670                 totalFalseConstraintNum_ = 0;
00671                 costOfTotalFalseConstraints_ = 0.0;
00672                 numFalseClauses_ = 0;
00673                 costOfFalseClauses_ = 0.0;
00674                 hybridFalseConstraintNum_ = 0;
00675                 costHybridFalseConstraint_ = 0.0;
00676 
00677                 weightSumCont_ = 0.0;
00678                 weightSumDis_ = 0.0;
00679 
00680                 // Initialize info arrays
00681                 initMakeBreakCostWatch();
00682                 initMakeBreakCostWatchCont();
00683                 if (hvsdebug)
00684                 {
00685                         cout << "leaving init" << endl;
00686                 }               
00687         }
00688 
00689         void initLowState()
00690         {
00691                 lowCost_ = LDBL_MAX;
00692                 lowBad_ = INT_MAX;
00693                 lowCostAll_ = LDBL_MAX;
00694                 lowBadAll_ = INT_MAX;
00695                 lowCostHybrid_ = LDBL_MAX;
00696                 lowBadHybrid_ = INT_MAX;
00697         }
00698 
00699         // Initialize variables from evidence.
00700         void setInitFromEvi(bool bInitFromEvi)
00701         {
00702                 bInitFromEvi_ = bInitFromEvi;
00703         }
00704 
00710         void initRandom()
00711         {
00712                 // Initialize variable assignment values
00713                 if (!bInitFromEvi_) // Random initialization rather than initialize from evidence.
00714                 {
00715                         // Random truth value for discrete variables.
00716                         for (int i = 1; i <= baseNumAtoms_; i++)
00717                         {
00718                                 if (hvsdebug) cout << "Atom " << i << " not in block" << endl;
00719                                 setValueOfAtom(i, random() % 2, false, -1);
00720                         }
00721 
00722                         // Random initialize continuous variables.
00723                         initContinuousVariableRandom();
00724 
00725                         if (hvsdebug)
00726                         {
00727                                 cout << "Randomly initializing dis&cont variables to:" << endl;
00728                                 for(int i = 0; i < baseNumAtoms_; i++)
00729                                 {
00730                                         printDisAtom(i+1, cout);
00731                                 }
00732 
00733                                 for(int i = 0; i < contAtomNum_; i++)
00734                                 {
00735                                         printContAtom(i+1, cout);
00736                                 }
00737                         }
00738                 }
00739                 else
00740                 {
00741                         atom_.copyFrom(atomEvi_);
00742                         contAtoms_.copyFrom(contAtomsEvi_);
00743                 }
00744 
00745                 // Initialize other state information.
00746                 init();
00747         }
00748 
00752 /*
00753         void initBlocksRandom()
00754         {
00755                 if (hvsdebug)
00756                 {
00757                         cout << "Initializing blocks randomly" << endl;
00758                         cout << "Num. of blocks: " << blocks_->size() << endl;
00759                 }
00760 
00761                 // For each block: select one to set to true
00762                 for (int i = 0; i < blocks_->size(); i++)
00763                 {
00764                         // True fixed atom in the block: set others to false
00765                         if (int trueFixedAtomInBlock = getTrueFixedAtomInBlock(i) >= 0)
00766                         {
00767                                 if (hvsdebug) cout << "True fixed atom in block " << i << endl;
00768                                 setOthersInBlockToFalse(trueFixedAtomInBlock, i);
00769                                 continue;
00770                         }
00771 
00772                         // If evidence atom exists, then all others are false
00773                         if ((*blockEvidence_)[i])
00774                         {
00775                                 // If first argument is -1, then all are set to false
00776                                 setOthersInBlockToFalse(-1, i);
00777                                 continue;
00778                         }
00779                         // Eager version: pick one at random
00780                         Array<int>& block = (*blocks_)[i];
00781                         bool ok = false;
00782                         while (!ok)
00783                         {
00784                                 int chosen = random() % block.size();
00785                                 // Atom not fixed
00786                                 if (fixedAtom_[block[chosen] + 1] == 0)
00787                                 {
00788                                         if (hvsdebug) cout << "Atom " << block[chosen] + 1 
00789                                                 << " chosen in block" << endl;
00790                                         setValueOfAtom(block[chosen] + 1, true);
00791                                         setOthersInBlockToFalse(chosen, i);
00792                                         ok = true;
00793                                 }
00794                         }
00795                 }
00796                 if (hvsdebug) cout << "Done initializing blocks randomly" << endl;
00797         }      
00798 */
00802   void initBlocksRandom()
00803   {
00804     if (hvsdebug)
00805     {
00806       cout << "Initializing blocks randomly" << endl;
00807       cout << "Num. of blocks: " << domain_->getNumPredBlocks() << endl;
00808     }
00809       // For each block: select one to set to true
00810     for (int i = 0; i < domain_->getNumPredBlocks(); i++)
00811     {
00812       int trueFixedAtom = getTrueFixedAtomInBlock(i);
00813         // True fixed atom in the block: set others to false
00814       if (trueFixedAtom >= 0)
00815       {
00816         if (hvsdebug)
00817         {
00818           cout << "True fixed atom " << trueFixedAtom  << " in block "
00819                << i << endl;
00820         }
00821         setOthersInBlockToFalse(trueFixedAtom, i);
00822         continue;
00823       }
00824 
00825         // If evidence atom exists, then all others are false
00826       if (domain_->getBlockEvidence(i))
00827       {
00828         if (hvsdebug) cout << "Block evidence in block " << i << endl;
00829           // If first argument is -1, then all are set to false
00830         setOthersInBlockToFalse(-1, i);
00831         continue;
00832       }
00833 
00834         // Pick one pred from block at random
00835       bool ok = false;
00836       while (!ok)
00837       {
00838         const Predicate* pred = domain_->getRandomPredInBlock(i);
00839         GroundPredicate* gndPred = new GroundPredicate((Predicate*)pred);
00840         int atomIdx = gndPredHashArray_.find(gndPred);
00841         delete pred;
00842 
00843         assert(lazy_ || atomIdx >= 0);        
00844           // Pred not yet present: add it
00845         if (atomIdx == -1)
00846         {
00847           atomIdx = gndPredHashArray_.append(gndPred);
00848           bool initial = false;
00849           addNewClauses(initial);
00850           ok = true;
00851         }
00852           // Pred already present: check that it's not fixed
00853         else
00854         {
00855           delete gndPred;
00856           if (fixedAtom_[atomIdx + 1] == 0)
00857           {
00858             if (hvsdebug) cout << "Atom " << atomIdx + 1 
00859                               << " chosen in block " << i << endl;
00860             ok = true;
00861           }
00862           else
00863           {
00864             if (hvsdebug) cout << "Atom " << atomIdx + 1 
00865                               << " is fixed to " << fixedAtom_[atomIdx + 1]
00866                               << endl;
00867               // Atom is fixed
00868             continue;
00869           }
00870         }
00871         bool activate = false;
00872         setValueOfAtom(atomIdx + 1, true, activate, i);
00873         setOthersInBlockToFalse(atomIdx, i);
00874       }
00875     }
00876     if (hvsdebug) cout << "Done initializing blocks randomly" << endl;
00877   }      
00878 
00879 
00887         void initMakeBreakCostWatch()
00888         {
00889                 if (hvsdebug)
00890                 {
00891                         cout << "entering intiMakeBreakCostWatch()" << endl;
00892                 }
00893                 assert(makeCost_.size() == breakCost_.size());
00894                 // Reset make and break cost to 0
00895                 for (int i = 0; i < makeCost_.size(); i++)
00896                 {
00897                         makeCost_[i] = breakCost_[i] = 0.0;
00898                 }
00899                 initMakeBreakCostWatch(0);
00900                 if (hvsdebug)
00901                 {
00902                         cout << "leaving intiMakeBreakCostWatch()" << endl;
00903                 }
00904         }
00905 
00906         void printDisAtom(int atomIdx, ostream& os)
00907         {
00908                 os << "<"; (*gndPreds_)[atomIdx - 1]->print(os, domain_); os << "," << atom_[atomIdx] <<">";
00909         }
00910         
00911         // Print the pure discrete clause.
00912         void printDisClause(int i, ostream& os)
00913         {
00914                 GroundClause* pC = getGndClause(i);
00915                 if (pC->isHardClause())
00916                 {
00917                         os << "H " ;
00918                 }
00919                 else
00920                 {
00921                         os << clauseCost_[i] << " ";
00922                 }               
00923                 pC->printWithoutWtWithStrVar(os, domain_, &gndPredHashArray_);
00924                 os << " Atoms are: ";
00925                 for(int j = 0;j < clause_[i].size(); j++)
00926                 {
00927                         int predIdx = abs(clause_[i][j]);
00928                         printDisAtom(predIdx, os);
00929                         os << ", ";
00930                 }
00931                 os << endl;
00932         }
00933 
00934         void initMakeBreakCostWatch(const int& startClause)
00935         {
00936                 if (hvsdebug)
00937                 {
00938                         cout << "entering intiMakeBreakCostWatch(int)" << endl;
00939                 }
00940                 int theTrueLit = -1;
00941                 // Initialize breakCost and makeCost in the following:
00942                 for (int i = startClause; i < getNumClauses(); i++)
00943                 {
00944                         // Don't look at dead clauses
00945                         if (deadClause_[i]) continue;
00946                         int trueLit1 = 0;
00947                         int trueLit2 = 0;
00948                         long double cost = clauseCost_[i];
00949                         numTrueLits_[i] = 0;
00950                         for (int j = 0; j < getClauseSize(i); j++)
00951                         {
00952                                 if (isTrueLiteral(clause_[i][j]))
00953                                 { // ij is true lit
00954                                         numTrueLits_[i]++;
00955                                         theTrueLit = abs(clause_[i][j]);
00956                                         if (!trueLit1) trueLit1 = theTrueLit;
00957                                         else if (trueLit1 && !trueLit2) trueLit2 = theTrueLit;
00958                                 }
00959                         }
00960                         if (numTrueLits_[i] > 0)
00961                         {
00962                                 weightSumDis_ += clauseCost_[i];
00963                         }
00964 
00965                         // Unsatisfied positive-weighted clauses or
00966                         // Satisfied negative-weighted clauses
00967                         if ((numTrueLits_[i] == 0 && cost > 0) ||
00968                                 (numTrueLits_[i] > 0 && cost < 0))
00969                         {
00970                                 whereFalse_[i] = numFalseClauses_;
00971                                 falseClause_[numFalseClauses_] = i;
00972                                 numFalseClauses_++;
00973                                 totalFalseConstraintNum_++;
00974                                 costOfFalseClauses_ += abs(cost);
00975                                 costOfTotalFalseConstraints_ += abs(cost);
00976 
00977                                 // Unsat. pos. clause: increase makeCost_ of all atoms
00978                                 if (numTrueLits_[i] == 0) // cost > 0 is true
00979                                 {
00980                                         for (int j = 0; j < getClauseSize(i); j++)
00981                                         {
00982                                                 makeCost_[abs(clause_[i][j])] += cost;
00983                                         }
00984                                 }
00985 
00986                                 // Sat. neg. clause: increase makeCost_ if one true literal
00987                                 if (numTrueLits_[i] == 1) // cost < 0 is true
00988                                 {
00989                                         // Subtract neg. cost
00990                                         makeCost_[theTrueLit] -= cost;
00991                                         watch1_[i] = theTrueLit;
00992                                 }
00993                                 else if (numTrueLits_[i] > 1)
00994                                 {
00995                                         watch1_[i] = trueLit1;
00996                                         watch2_[i] = trueLit2;
00997                                 }
00998                         }
00999                         // Pos. clauses satisfied by one true literal
01000                         else if (numTrueLits_[i] == 1 && cost > 0)
01001                         {
01002                                 breakCost_[theTrueLit] += cost;
01003                                 watch1_[i] = theTrueLit;
01004                         }
01005                         // Pos. clauses satisfied by 2 or more true literals
01006                         else if (cost > 0)
01007                         { /*if (numtruelit[i] == 2)*/
01008                                 watch1_[i] = trueLit1;
01009                                 watch2_[i] = trueLit2;
01010                         }
01011                         // Unsat. neg. clauses: increase breakCost of all atoms
01012                         else if (numTrueLits_[i] == 0 && cost < 0)
01013                         {
01014                                 for (int j = 0; j < getClauseSize(i); j++)
01015                                         breakCost_[abs(clause_[i][j])] -= cost;
01016                         }
01017                 } // for all clauses
01018                 if (hvsdebug)
01019                 {
01020                         cout << "leaving intiMakeBreakCostWatch(int)" << endl;
01021                 }
01022         }
01023 
01024         int getNumAtoms() { return gndPreds_->size(); }
01025 
01026         int getNumClauses() { return gndClauses_->size(); }
01027 
01028         int getNumDeadClauses()
01029         { 
01030                 int count = 0;
01031                 for (int i = 0; i < deadClause_.size(); i++)
01032                         if (deadClause_[i]) count++;
01033                 return count;
01034         }
01035 
01041         int getIndexOfAtomInRandomFalseClause()
01042         {
01043                 if (numFalseClauses_ == 0) return NOVALUE;
01044                 int clauseIdx = falseClause_[random()%numFalseClauses_];
01045                 // Pos. clause: return index of random atom
01046                 if (clauseCost_[clauseIdx] > 0)
01047                         return abs(clause_[clauseIdx][random()%getClauseSize(clauseIdx)]);
01048                 // Neg. clause: find random true lit
01049                 else
01050                         return getRandomTrueLitInClause(clauseIdx);
01051         }
01052 
01057         int getRandomFalseClauseIndex()//need to be changed to adapt hybrid
01058         {
01059                 if (numFalseClauses_ == 0) return NOVALUE;
01060                 return falseClause_[random()%numFalseClauses_];
01061         }
01062 
01067         int getNumFalseClauses()
01068         {
01069                 return numFalseClauses_;
01070         }
01075         long double getCostOfFalseClauses()
01076         {
01077                 return costOfFalseClauses_;
01078         }
01079 
01080         const double getMaxClauseWeight()
01081         {
01082                 double maxWeight = 0.0;
01083                 for (int i = 0; i < getNumClauses(); i++)
01084                 {
01085                         double weight = abs(clauseCost_[i]);
01086                         if (weight > maxWeight) maxWeight = weight;
01087                 }
01088                 return maxWeight;
01089         }
01090 
01097         bool getValueOfAtom(const int& atomIdx)
01098         {
01099                 return atom_[atomIdx];
01100         }
01101 
01108         bool getValueOfLowAtom(const int& atomIdx)
01109         {
01110                 return lowAtom_[atomIdx];
01111         }
01112 
01120 /*
01121         void setValueOfAtom(const int& atomIdx, const bool& value)
01122         {
01123 
01124                 // If atom already has this value, then do nothing
01125                 if (atom_[atomIdx] == value) return;
01126                 // Propagate assigment to DB
01127                 GroundPredicate* p = gndPredHashArray_[atomIdx - 1];
01128                 if (value)
01129                 {
01130                         domain_->getDB()->setValue(p, TRUE);
01131                 }
01132                 else
01133                 {
01134                         domain_->getDB()->setValue(p, FALSE);
01135                 }
01136                 // If not active, then activate it
01137                 if (lazy_ && !isActive(atomIdx))
01138                 {
01139                         bool ignoreActivePreds = false;
01140                         activateAtom(atomIdx, ignoreActivePreds);
01141                 }
01142                 atom_[atomIdx] = value;
01143 
01144         }
01145 */
01146 
01157   void setValueOfAtom(const int& atomIdx, const bool& value,
01158                       const bool& activate, const int& blockIdx)
01159   {
01160       // If atom already has this value, then do nothing
01161     if (atom_[atomIdx] == value) return;
01162     if (hvsdebug) cout << "Setting value of atom " << atomIdx 
01163                       << " to " << value << endl;
01164       // Propagate assignment to DB
01165     GroundPredicate* p = gndPredHashArray_[atomIdx - 1];
01166     if (value)
01167       domain_->getDB()->setValue(p, TRUE);
01168     else
01169       domain_->getDB()->setValue(p, FALSE);
01170 
01171       // If not active, then activate it
01172     if (activate && lazy_ && !isActive(atomIdx))
01173     {
01174       bool ignoreActivePreds = false;
01175       bool groundOnly = false;
01176       activateAtom(atomIdx, ignoreActivePreds, groundOnly);
01177     }
01178     atom_[atomIdx] = value;
01179 
01180       // If in block and setting to true, tell the domain
01181     if (blockIdx > -1 && value)
01182     {
01183       Predicate* pred = p->createEquivalentPredicate(domain_);
01184       domain_->setTruePredInBlock(blockIdx, pred);
01185       if (hvsdebug)
01186       {
01187         cout << "Set true pred in block " << blockIdx << " to ";
01188         pred->printWithStrVar(cout, domain_);
01189         cout << endl;
01190       }
01191     }
01192   }
01193 
01197         Array<int>& getNegOccurenceArray(const int& atomIdx)
01198         {
01199                 int litIdx = 2*atomIdx;
01200                 return getOccurenceArray(litIdx);
01201         }
01202 
01206         Array<int>& getPosOccurenceArray(const int& atomIdx)
01207         {
01208                 int litIdx = 2*atomIdx - 1;
01209                 return getOccurenceArray(litIdx);
01210         }
01211 
01218   void flipAtom(const int& toFlip, const int& blockIdx)
01219   {
01220     bool toFlipValue = getValueOfAtom(toFlip);
01221     register int clauseIdx;
01222     int sign;
01223     int oppSign;
01224     int litIdx;
01225     if (toFlipValue)
01226       sign = 1;
01227     else
01228       sign = 0;
01229     oppSign = sign ^ 1;
01230 
01231     flipAtomValue(toFlip, blockIdx);
01232 
01233       // Update all clauses in which the atom occurs as a true literal
01234     litIdx = 2*toFlip - sign;
01235     Array<int>& posOccArray = getOccurenceArray(litIdx);
01236     for (int i = 0; i < posOccArray.size(); i++)
01237     {
01238       clauseIdx = posOccArray[i];
01239         // Don't look at dead clauses
01240       if (deadClause_[clauseIdx]) continue;
01241         // The true lit became a false lit
01242       int numTrueLits = decrementNumTrueLits(clauseIdx);
01243       long double cost = getClauseCost(clauseIdx);
01244       int watch1 = getWatch1(clauseIdx);
01245       int watch2 = getWatch2(clauseIdx);
01246 
01247         // 1. If last true lit was flipped, then we have to update
01248         // the makecost / breakcost info accordingly        
01249       if (numTrueLits == 0)
01250       {
01251         weightSumDis_ -= clauseCost_[clauseIdx];
01252           // Pos. clause
01253         if (cost > 0)
01254         {
01255             // Add this clause as false in the state
01256           addFalseClause(clauseIdx);
01257             // Decrease toFlip's breakcost (add neg. cost)
01258           addBreakCost(toFlip, -cost);
01259             // Increase makecost of all vars in clause (add pos. cost)
01260           addMakeCostToAtomsInClause(clauseIdx, cost);
01261         }
01262           // Neg. clause
01263         else
01264         {
01265           assert(cost < 0);
01266             // Remove this clause as false in the state
01267           removeFalseClause(clauseIdx);
01268             // Increase breakcost of all vars in clause (add pos. cost)
01269           addBreakCostToAtomsInClause(clauseIdx, -cost);
01270             // Decrease toFlip's makecost (add neg. cost)
01271           addMakeCost(toFlip, cost);
01272         }
01273       }
01274         // 2. If there is now one true lit left, then move watch2
01275         // up to watch1 and increase the breakcost / makecost of watch1
01276       else if (numTrueLits == 1)
01277       {
01278         if (watch1 == toFlip)
01279                                 {
01280                                         assert(watch1 != watch2);
01281                                         setWatch1(clauseIdx, watch2);
01282                                         watch1 = getWatch1(clauseIdx);
01283                                 }
01284 
01285                                 // Pos. clause: Increase toFlip's breakcost (add pos. cost)
01286                                 if (cost > 0)
01287                                 {
01288                                         addBreakCost(watch1, cost);
01289                                 }
01290                                 // Neg. clause: Increase toFlip's makecost (add pos. cost)
01291                                 else
01292                                 {
01293                                         assert(cost < 0);
01294                                         addMakeCost(watch1, -cost);
01295                                 }
01296                         }
01297                         // 3. If there are 2 or more true lits left, then we have to
01298                         // find a new true lit to watch if one was flipped
01299                         else
01300                         { /* numtruelit[clauseIdx] >= 2 */
01301                                 // If watch1[clauseIdx] has been flipped
01302                                 if (watch1 == toFlip)
01303                                 {
01304                                         // find a different true literal to watch
01305                                         int diffTrueLit = getTrueLiteralOtherThan(clauseIdx, watch1, watch2);
01306                                         setWatch1(clauseIdx, diffTrueLit);
01307                                 }
01308                                 // If watch2[clauseIdx] has been flipped
01309                                 else if (watch2 == toFlip)
01310                                 {
01311                                         // find a different true literal to watch
01312                                         int diffTrueLit = getTrueLiteralOtherThan(clauseIdx, watch1, watch2);
01313                                         setWatch2(clauseIdx, diffTrueLit);
01314                                 }
01315                         }
01316                 }
01317 
01318                 // Update all clauses in which the atom occurs as a false literal
01319                 litIdx = 2*toFlip - oppSign;
01320                 Array<int>& negOccArray = getOccurenceArray(litIdx);
01321                 for (int i = 0; i < negOccArray.size(); i++)
01322                 {
01323                         clauseIdx = negOccArray[i];
01324                         // Don't look at dead clauses
01325                         if (deadClause_[clauseIdx]) continue;
01326                         // The false lit became a true lit
01327                         int numTrueLits = incrementNumTrueLits(clauseIdx);
01328                         long double cost = getClauseCost(clauseIdx);
01329                         int watch1 = getWatch1(clauseIdx);
01330 
01331                         // 1. If this is the only true lit, then we have to update
01332                         // the makecost / breakcost info accordingly        
01333                         if (numTrueLits == 1)
01334                         {
01335                                 weightSumDis_ += clauseCost_[clauseIdx];
01336                                 // Pos. clause
01337                                 if (cost > 0)
01338                                 {
01339                                         // Remove this clause as false in the state
01340                                         removeFalseClause(clauseIdx);
01341                                         // Increase toFlip's breakcost (add pos. cost)
01342                                         addBreakCost(toFlip, cost);        
01343                                         // Decrease makecost of all vars in clause (add neg. cost)
01344                                         addMakeCostToAtomsInClause(clauseIdx, -cost);
01345                                 }
01346                                 // Neg. clause
01347                                 else
01348                                 {
01349                                         assert(cost < 0);
01350                                         // Add this clause as false in the state
01351                                         addFalseClause(clauseIdx);
01352                                         // Decrease breakcost of all vars in clause (add neg. cost)
01353                                         addBreakCostToAtomsInClause(clauseIdx, cost);
01354                                         // Increase toFlip's makecost (add pos. cost)
01355                                         addMakeCost(toFlip, -cost);
01356                                 }
01357                                 // Watch this atom
01358                                 setWatch1(clauseIdx, toFlip);
01359                         }
01360                         // 2. If there are now exactly 2 true lits, then watch second atom
01361                         // and update breakcost
01362                         else if (numTrueLits == 2)
01363                                 {
01364                                         if (cost > 0)
01365                                         {
01366                                                 // Pos. clause
01367                                                 // Decrease breakcost of first atom being watched (add neg. cost)
01368                                                 addBreakCost(watch1, -cost);
01369                                         }
01370                                         else
01371                                         {
01372                                                 // Neg. clause
01373                                                 assert(cost < 0);
01374                                                 // Decrease makecost of first atom being watched (add neg. cost)
01375                                                 addMakeCost(watch1, cost);
01376                                         }
01377 
01378                                         // Watch second atom
01379                                         setWatch2(clauseIdx, toFlip);
01380                                 }
01381                 }
01382         }
01383 
01388 /*
01389         void flipAtomValue(const int& atomIdx)
01390         {
01391                 bool opposite = !atom_[atomIdx];
01392                 setValueOfAtom(atomIdx, opposite);
01393         }
01394 */
01395 
01403   void flipAtomValue(const int& atomIdx, const int& blockIdx)
01404   {
01405     bool opposite = !atom_[atomIdx];
01406     bool activate = true;
01407     setValueOfAtom(atomIdx, opposite, activate, blockIdx);
01408   }
01409 
01416 /*
01417         void activateAtom(const int& atomIdx, const bool& ignoreActivePreds)
01418         {
01419                 // Lazy version: if atom is not active, we need to activate clauses
01420                 // and take their cost into account
01421                 if (lazy_ && !isActive(atomIdx))
01422                 {
01423                         Predicate* p =
01424                                 gndPredHashArray_[atomIdx - 1]->createEquivalentPredicate(domain_);
01425                         getActiveClauses(p, newClauses_, true, ignoreActivePreds);
01426                         // Add the clauses and preds and fill info arrays
01427                         bool initial = false;
01428                         addNewClauses(initial);
01429                         // Set active status in db
01430                         domain_->getDB()->setActiveStatus(p, true);
01431                         activeAtoms_++;
01432                         delete p;
01433                 }        
01434         }
01435 */
01436 
01447   bool activateAtom(const int& atomIdx, const bool& ignoreActivePreds,
01448                     const bool& groundOnly)
01449   {
01450     /***
01451      * . [IF MCSAT] 
01452      * - check neg-wt clauses
01453      * . if alive, fix
01454      * . else mark dead
01455      * - if not fixed, add all pos-wt, killClauses
01456      * - else add dead
01457      * . [ELSE] add all
01458      ***/
01459     if (lazy_ && !isActive(atomIdx))
01460     {
01461       if (hvsdebug)
01462       {
01463         cout << "\tActivating ";
01464         gndPredHashArray_[atomIdx-1]->print(cout,domain_);
01465         cout << " " <<
01466         domain_->getDB()->getActiveStatus(gndPredHashArray_[atomIdx-1]) << endl;
01467       }
01468 
01469         // Set atom to true first, see if avoid getting clauses already active
01470       bool needToFlipBack = false;
01471       if (!atom_[atomIdx])
01472       {
01473         bool activate = false;
01474         setValueOfAtom(atomIdx, true, activate, -1);
01475         updateMakeBreakCostAfterFlip(atomIdx);
01476         needToFlipBack = true;
01477       } 
01478 
01479         // gather active clauses
01480       Predicate* p =
01481         gndPredHashArray_[atomIdx - 1]->createEquivalentPredicate(domain_);
01482 
01483       bool isFixed = false;
01484       Array<GroundClause*> unsatClauses;
01485       Array<GroundClause*> deadClauses;
01486       Array<GroundClause*> toAddClauses;
01487 
01488         // Using newClauses_ causes problem since it's shared across the board
01489       getActiveClauses(p, unsatClauses, true, ignoreActivePreds);
01490 
01491         // if MC-SAT: check neg-wt or unit clauses and see if can fix         
01492       if (useThreshold_)
01493       {
01494           // first append deadClauses, then pos-wt
01495         for (int ni = 0; ni < unsatClauses.size(); ni++)
01496         {
01497           GroundClause* c = unsatClauses[ni];
01498           if (c->getWt() < 0)
01499           {  // Neg. weighted clause
01500               // since newClauses_ excludes clauses in memory, c must be
01501               // goodInPrevious
01502             double threshold = RAND_MAX*(1 - exp(c->getWt()));
01503             if (random() <= threshold)
01504             {
01505                 // fix
01506               isFixed = true;
01507 
01508                 // append dead and fixed clauses first, so fixed atoms do not
01509                 // activate them unnecessarily
01510               if (deadClauses.size() > 0)
01511                 addNewClauses(ADD_CLAUSE_DEAD, deadClauses);
01512 
01513               Array<GroundClause*> fixedClauses;
01514               fixedClauses.append(c);
01515               addNewClauses(ADD_CLAUSE_SAT, fixedClauses);
01516 
01517                 // --- fix the atoms
01518               for (int pi = 0; pi < c->getNumGroundPredicates(); pi++)
01519               {
01520                 int lit = c->getGroundPredicateIndex(pi);
01521                 fixAtom(abs(lit), (lit < 0));
01522               }
01523 
01524                 // - can quit now
01525               break;
01526             }
01527             else
01528             {
01529                 // dead
01530               deadClauses.append(c);
01531             }
01532           }
01533           else if (c->getNumGroundPredicates() == 1)
01534           {  // Unit clause
01535             double threshold = RAND_MAX*(1 - exp(-c->getWt()));
01536             if (random() <= threshold)
01537             {
01538                 // fix
01539               isFixed = true;
01540 
01541                 // append dead and fixed clauses first, so fixed atoms do not
01542                 // activate them unnecessarily
01543               if (deadClauses.size() > 0)
01544                 addNewClauses(ADD_CLAUSE_DEAD, deadClauses);
01545 
01546               Array<GroundClause*> fixedClauses;
01547               fixedClauses.append(c);
01548               addNewClauses(ADD_CLAUSE_SAT, fixedClauses);
01549 
01550                 // --- fix the atoms
01551               int lit = c->getGroundPredicateIndex(0);
01552               fixAtom(abs(lit), (lit > 0)); // this is positive wt
01553 
01554                 // - can quit now
01555               break;
01556             }
01557             else
01558             {
01559                 // dead
01560               deadClauses.append(c);
01561             }
01562           }
01563           else toAddClauses.append(c);
01564         }
01565       }
01566 
01567         // Add the clauses and preds and fill info arrays
01568       if (!isFixed)
01569       {
01570         if (deadClauses.size() > 0)
01571           addNewClauses(ADD_CLAUSE_DEAD, deadClauses);
01572 
01573         if (useThreshold_)
01574           addNewClauses(ADD_CLAUSE_REGULAR, toAddClauses);
01575         else // lazy-sat
01576           addNewClauses(ADD_CLAUSE_REGULAR, unsatClauses);
01577 
01578           // To avoid append already-active: if not fixed, might need to
01579           // flip back
01580         if (needToFlipBack)
01581         {
01582           bool activate = false;
01583           setValueOfAtom(atomIdx, false, activate, -1);
01584           updateMakeBreakCostAfterFlip(atomIdx);
01585         }
01586 
01587         if (!groundOnly)
01588         {
01589             // Set active status in db
01590           domain_->getDB()->setActiveStatus(p, true);
01591           activeAtoms_++;
01592         }
01593       }
01594 
01595       delete p;
01596       unsatClauses.clear();
01597       deadClauses.clear();
01598       toAddClauses.clear();
01599 
01600       return !isFixed; // if !isFixed, then activated
01601     }
01602     return true;
01603   }
01604 
01608   void setInferenceMode(int mode)
01609   {
01610     if (mode == inferenceMode_) return;
01611     inferenceMode_ = mode;
01612     if (inferenceMode_ == MODE_MWS)
01613     {         
01614       for (int i = 0; i < gndClauses_->size(); i++)
01615       {
01616         if ((*gndClauses_)[i]->isHardClause())
01617           clauseCost_[i] = hardWt_;
01618         else
01619           clauseCost_[i] = (*gndClauses_)[i]->getWt();
01620       }
01621       initMakeBreakCostWatch();
01622     }
01623     else
01624     {
01625       if (inferenceMode_ == MODE_HARD) eliminateSoftClauses();
01626       else if (inferenceMode_ == MODE_SAMPLESAT) makeUnitCosts();
01627     }
01628   }
01629 
01636   void updateSatisfiedClauses(const int& toFix)
01637   {
01638       // Already flipped
01639     bool toFlipValue = getValueOfAtom(toFix);
01640       
01641     register int clauseIdx;
01642     int sign;
01643     int litIdx;
01644     if (toFlipValue)
01645       sign = 1;
01646     else
01647       sign = 0;
01648 
01649       // Set isSatisfied: all clauses in which the atom occurs as a true literal
01650     litIdx = 2*toFix - sign;
01651     Array<int>& posOccArray = getOccurenceArray(litIdx);
01652     for (int i = 0; i < posOccArray.size(); i++)
01653     {
01654       clauseIdx = posOccArray[i];
01655         // Don't look at dead clauses
01656         // ignore already sat
01657       if (deadClause_[clauseIdx] || isSatisfied_[clauseIdx]) continue;
01658 
01659       if (getClauseCost(clauseIdx) < 0) 
01660       {
01661         cout << "ERR: in MC-SAT, active neg-wt clause (" << clauseIdx
01662              << ") is sat by fixed "<<endl;
01663         exit(0);
01664       }
01665       isSatisfied_[clauseIdx] = true;  
01666     }
01667   }
01668 
01674   void updateMakeBreakCostAfterFlip(const int& toFlip)
01675   {   
01676       // Already flipped
01677     bool toFlipValue = !getValueOfAtom(toFlip);
01678 
01679     register int clauseIdx;
01680     int sign;
01681     int oppSign;
01682     int litIdx;
01683     if (toFlipValue)
01684       sign = 1;
01685     else
01686       sign = 0;
01687     oppSign = sign ^ 1;
01688 
01689       // Update all clauses in which the atom occurs as a true literal
01690     litIdx = 2*toFlip - sign;
01691     Array<int>& posOccArray = getOccurenceArray(litIdx);
01692 
01693     for (int i = 0; i < posOccArray.size(); i++)
01694     {
01695       clauseIdx = posOccArray[i];
01696         // Don't look at dead clauses and sat clauses
01697       if (deadClause_[clauseIdx] || isSatisfied_[clauseIdx]) continue;
01698 
01699         // The true lit became a false lit
01700       int numTrueLits = decrementNumTrueLits(clauseIdx);
01701       long double cost = getClauseCost(clauseIdx);
01702       int watch1 = getWatch1(clauseIdx);
01703       int watch2 = getWatch2(clauseIdx);
01704 
01705         // 1. If last true lit was flipped, then we have to update
01706         // the makecost / breakcost info accordingly        
01707       if (numTrueLits == 0)
01708       {
01709           // Pos. clause
01710         if (cost >= 0)
01711         {
01712             // Add this clause as false in the state
01713           addFalseClause(clauseIdx);
01714             // Decrease toFlip's breakcost (add neg. cost)
01715           addBreakCost(toFlip, -cost);
01716             // Increase makecost of all vars in clause (add pos. cost)
01717           addMakeCostToAtomsInClause(clauseIdx, cost);
01718         }
01719           // Neg. clause
01720         else
01721         {
01722           assert(cost < 0);
01723             // Remove this clause as false in the state
01724           removeFalseClause(clauseIdx);
01725             // Increase breakcost of all vars in clause (add pos. cost)
01726           addBreakCostToAtomsInClause(clauseIdx, -cost);        
01727             // Decrease toFlip's makecost (add neg. cost)
01728           addMakeCost(toFlip, cost);
01729         }
01730       }
01731         // 2. If there is now one true lit left, then move watch2
01732         // up to watch1 and increase the breakcost / makecost of watch1
01733       else if (numTrueLits == 1)
01734       {
01735         if (watch1 == toFlip)
01736         {
01737           assert(watch1 != watch2);
01738           setWatch1(clauseIdx, watch2);
01739           watch1 = getWatch1(clauseIdx);
01740         }
01741           // Pos. clause: Increase toFlip's breakcost (add pos. cost)
01742         if (cost >= 0)
01743         {
01744           addBreakCost(watch1, cost);
01745         }
01746             // Neg. clause: Increase toFlip's makecost (add pos. cost)
01747         else
01748         {
01749           assert(cost < 0);
01750           addMakeCost(watch1, -cost);
01751         }
01752       }
01753         // 3. If there are 2 or more true lits left, then we have to
01754         // find a new true lit to watch if one was flipped
01755       else
01756       {
01757           /* numtruelit[clauseIdx] >= 2 */
01758           // If watch1[clauseIdx] has been flipped
01759         if (watch1 == toFlip)
01760         {
01761             // find a different true literal to watch
01762           int diffTrueLit = getTrueLiteralOtherThan(clauseIdx, watch1, watch2);
01763           setWatch1(clauseIdx, diffTrueLit);
01764         }
01765           // If watch2[clauseIdx] has been flipped
01766         else if (watch2 == toFlip)
01767         {
01768             // find a different true literal to watch
01769           int diffTrueLit = getTrueLiteralOtherThan(clauseIdx, watch1, watch2);
01770           setWatch2(clauseIdx, diffTrueLit);
01771         }
01772       }
01773     }
01774 
01775       // Update all clauses in which the atom occurs as a false literal
01776     litIdx = 2*toFlip - oppSign;
01777     Array<int>& negOccArray = getOccurenceArray(litIdx);
01778     for (int i = 0; i < negOccArray.size(); i++)
01779     {
01780       clauseIdx = negOccArray[i];
01781         // Don't look at dead clauses or satisfied clauses
01782       if (deadClause_[clauseIdx] || isSatisfied_[clauseIdx]) continue;
01783 
01784         // The false lit became a true lit
01785       int numTrueLits = incrementNumTrueLits(clauseIdx);
01786       long double cost = getClauseCost(clauseIdx);
01787       int watch1 = getWatch1(clauseIdx);
01788 
01789         // 1. If this is the only true lit, then we have to update
01790         // the makecost / breakcost info accordingly        
01791       if (numTrueLits == 1)
01792       {
01793           // Pos. clause
01794         if (cost >= 0)
01795         {
01796             // Remove this clause as false in the state
01797           removeFalseClause(clauseIdx);
01798             // Increase toFlip's breakcost (add pos. cost)
01799           addBreakCost(toFlip, cost);        
01800             // Decrease makecost of all vars in clause (add neg. cost)
01801           addMakeCostToAtomsInClause(clauseIdx, -cost);
01802         }
01803           // Neg. clause
01804         else
01805         {
01806           assert(cost < 0);
01807             // Add this clause as false in the state
01808           addFalseClause(clauseIdx);
01809             // Decrease breakcost of all vars in clause (add neg. cost)
01810           addBreakCostToAtomsInClause(clauseIdx, cost);
01811             // Increase toFlip's makecost (add pos. cost)
01812           addMakeCost(toFlip, -cost);
01813         }
01814           // Watch this atom
01815         setWatch1(clauseIdx, toFlip);
01816       }
01817         // 2. If there are now exactly 2 true lits, then watch second atom
01818         // and update breakcost
01819       else if (numTrueLits == 2)
01820       {
01821         if (cost >= 0)
01822         {
01823             // Pos. clause
01824             // Decrease breakcost of first atom being watched (add neg. cost)
01825           addBreakCost(watch1, -cost);
01826         }
01827         else
01828         {
01829             // Neg. clause
01830           assert(cost < 0);
01831             // Decrease makecost of first atom being watched (add neg. cost)
01832           addMakeCost(watch1, cost);
01833         }
01834           // Watch second atom
01835         setWatch2(clauseIdx, toFlip);
01836       }
01837     }
01838   }
01839 
01846         bool isActive(const int& atomIdx)
01847         {
01848                 return domain_->getDB()->getActiveStatus(gndPredHashArray_[atomIdx-1]);
01849         }
01850 
01857         bool isActive(const Predicate* pred)
01858         {
01859                 return domain_->getDB()->getActiveStatus(pred);
01860         }
01861 
01865         Array<int>& getOccurenceArray(const int& idx)
01866         {
01867                 return occurence_[idx];
01868         }
01869 
01870 
01874         int incrementNumTrueLits(const int& clauseIdx)
01875         {
01876                 return ++numTrueLits_[clauseIdx];
01877         }
01878 
01882         int decrementNumTrueLits(const int& clauseIdx)
01883         {
01884                 return --numTrueLits_[clauseIdx];
01885         }
01886 
01890         int getNumTrueLits(const int& clauseIdx)
01891         {
01892                 return numTrueLits_[clauseIdx];
01893         }
01894 
01898         long double getClauseCost(const int& clauseIdx)
01899         {
01900                 return clauseCost_[clauseIdx];
01901         }
01902 
01906         Array<int>& getAtomsInClause(const int& clauseIdx)
01907         {
01908                 return clause_[clauseIdx];
01909         }
01910 
01914         void addBreakCost(const int& atomIdx, const long double& cost)
01915         {
01916                 breakCost_[atomIdx] += cost;
01917         }
01918 
01922         void subtractBreakCost(const int& atomIdx, const long double& cost)
01923         {
01924                 breakCost_[atomIdx] -= cost;
01925         }
01926 
01933         void addBreakCostToAtomsInClause(const int& clauseIdx,
01934                 const long double& cost)
01935         {
01936                 register int size = getClauseSize(clauseIdx);
01937                 for (int i = 0; i < size; i++)
01938                 {
01939                         register int lit = clause_[clauseIdx][i];
01940                         breakCost_[abs(lit)] += cost;
01941                 }
01942         }
01943 
01950         void subtractBreakCostFromAtomsInClause(const int& clauseIdx,
01951                 const long double& cost)
01952         {
01953                 register int size = getClauseSize(clauseIdx);
01954                 for (int i = 0; i < size; i++)
01955                 {
01956                         register int lit = clause_[clauseIdx][i];
01957                         breakCost_[abs(lit)] -= cost;
01958                 }
01959         }
01960 
01967         void addMakeCost(const int& atomIdx, const long double& cost)
01968         {
01969                 makeCost_[atomIdx] += cost;
01970         }
01971 
01978         void subtractMakeCost(const int& atomIdx, const long double& cost)
01979         {
01980                 makeCost_[atomIdx] -= cost;
01981         }
01982 
01989         void addMakeCostToAtomsInClause(const int& clauseIdx,
01990                 const long double& cost)
01991         {
01992                 register int size = getClauseSize(clauseIdx);
01993                 for (int i = 0; i < size; i++)
01994                 {
01995                         register int lit = clause_[clauseIdx][i];
01996                         makeCost_[abs(lit)] += cost;
01997                 }
01998         }
01999 
02006         void subtractMakeCostFromAtomsInClause(const int& clauseIdx,
02007                 const long double& cost)
02008         {
02009                 register int size = getClauseSize(clauseIdx);
02010                 for (int i = 0; i < size; i++)
02011                 {
02012                         register int lit = clause_[clauseIdx][i];
02013                         makeCost_[abs(lit)] -= cost;
02014                 }
02015         }
02016 
02026         const int getTrueLiteralOtherThan(const int& clauseIdx,
02027                 const int& atomIdx1,
02028                 const int& atomIdx2)
02029         {
02030                 register int size = getClauseSize(clauseIdx);
02031                 for (int i = 0; i < size; i++)
02032                 {
02033                         register int lit = clause_[clauseIdx][i];
02034                         register int v = abs(lit);
02035                         if (isTrueLiteral(lit) && v != atomIdx1 && v != atomIdx2)
02036                                 return v;
02037                 }
02038                 // If we're here, then no other true lit exists
02039                 assert(false);
02040                 return -1;
02041         }
02042 
02046         const bool isTrueLiteral(const int& literal)
02047         {
02048                 return ((literal > 0) == atom_[abs(literal)]);
02049         }
02050 
02054         const int getAtomInClause(const int& atomIdxInClause, const int& clauseIdx)
02055         {
02056                 return clause_[clauseIdx][atomIdxInClause];
02057         }
02058 
02062         const int getRandomAtomInClause(const int& clauseIdx)
02063         {
02064                 return clause_[clauseIdx][random()%getClauseSize(clauseIdx)];
02065         }
02066 
02073         const int getRandomTrueLitInClause(const int& clauseIdx)
02074         {
02075                 assert(numTrueLits_[clauseIdx] > 0);
02076                 int trueLit = random()%numTrueLits_[clauseIdx];
02077                 int whichTrueLit = 0;
02078                 for (int i = 0; i < getClauseSize(clauseIdx); i++)
02079                 {
02080                         int lit = clause_[clauseIdx][i];
02081                         int atm = abs(lit);
02082                         // True literal
02083                         if (isTrueLiteral(lit))
02084                                 if (trueLit == whichTrueLit++)
02085                                         return atm;
02086                 }
02087                 // If we're here, then no other true lit exists
02088                 assert(false);
02089                 return -1;
02090         }
02091 
02092 
02093         const long double getMakeCost(const int& atomIdx)
02094         {
02095                 return makeCost_[atomIdx];
02096         }
02097 
02098         const long double getBreakCost(const int& atomIdx)
02099         {
02100                 return breakCost_[atomIdx];
02101         }
02102 
02103         const int getClauseSize(const int& clauseIdx)
02104         {
02105                 return clause_[clauseIdx].size();
02106         }
02107 
02108         const int getWatch1(const int& clauseIdx)
02109         {
02110                 return watch1_[clauseIdx];
02111         }
02112 
02113         void setWatch1(const int& clauseIdx, const int& atomIdx)
02114         {
02115                 watch1_[clauseIdx] = atomIdx;
02116         }
02117 
02118         const int getWatch2(const int& clauseIdx)
02119         {
02120                 return watch2_[clauseIdx];
02121         }
02122 
02123         void setWatch2(const int& clauseIdx, const int& atomIdx)
02124         {
02125                 watch2_[clauseIdx] = atomIdx;
02126         }
02127 
02128         const bool isBlockEvidence(const int& blockIdx)
02129         {
02130                 return (*blockEvidence_)[blockIdx];
02131         }
02132 
02137         const int getBlockIndex(const int& atomIdx)
02138         {
02139                 for (int i = 0; i < blocks_->size(); i++)
02140                 {
02141                         int blockIdx = (*blocks_)[i].find(atomIdx);
02142                         if (blockIdx >= 0)
02143                                 return i;
02144                 }
02145                 return -1;
02146         }
02147 
02148         Array<int>& getBlockArray(const int& blockIdx)
02149         {
02150                 return (*blocks_)[blockIdx];
02151         }
02152 
02153         bool getBlockEvidence(const int& blockIdx)
02154         {
02155                 return (*blockEvidence_)[blockIdx];
02156         }
02157 
02158         int getNumBlocks()
02159         {
02160                 return blocks_->size();
02161         }
02165         const long double getLowCost()
02166         {
02167                 return lowCost_; 
02168         }
02169 
02173         const int getLowBad()
02174         {
02175                 return lowBad_;
02176         }
02177 
02178         void saveLowState()
02179         {
02180                 if (hvsdebug) cout << "Saving low state: " << endl;
02181                 for (int i = 1; i <= getNumAtoms(); i++)
02182                 {
02183                         lowAtom_[i] = atom_[i];
02184                         //if (hvsdebug) cout << lowAtom_[i] << endl;
02185                 }
02186                 lowCost_ = costOfFalseClauses_;
02187                 lowBad_ = numFalseClauses_;
02188                 if (lowBad_ > 0)
02189                 {
02190                         for (int i = 0; i < numFalseClauses_; i++)
02191                         {
02192                                 falseClauseLow_[i] = falseClause_[i];
02193                         }
02194                 }
02195         }
02196 
02200         int getTrueFixedAtomInBlock(const int blockIdx)
02201         {
02202                 Array<int>& block = (*blocks_)[blockIdx];
02203                 for (int i = 0; i < block.size(); i++)
02204                         if (fixedAtom_[block[i] + 1] > 0) return i;
02205                 return -1;
02206         }
02207         const GroundPredicateHashArray* getGndPredHashArrayPtr() const
02208         {
02209                 return &gndPredHashArray_;
02210         }
02211 
02212         const GroundPredicateHashArray* getUnePreds() const
02213         {
02214                 return unePreds_;
02215         }
02216 
02217         const GroundPredicateHashArray* getKnePreds() const
02218         {
02219                 return knePreds_;
02220         }
02221 
02222         const Array<TruthValue>* getKnePredValues() const
02223         {
02224                 return knePredValues_;
02225         }
02226 
02230   void setGndClausesWtsToSumOfParentWts()
02231   {
02232     for (int i = 0; i < gndClauses_->size(); i++)
02233     {
02234       GroundClause* gndClause = (*gndClauses_)[i];
02235       gndClause->setWtToSumOfParentWts(mln_);
02236       if (hvsdebug) cout << "Setting cost of clause " << i << " to "
02237                         << gndClause->getWt() << endl;
02238       clauseCost_[i] = gndClause->getWt();
02239 
02240         // Set thresholds for clause selection
02241       if (gndClause->isHardClause()) threshold_[i] = RAND_MAX;
02242       else
02243       {
02244         double w = gndClause->getWt();
02245         threshold_[i] = RAND_MAX*(1 - exp(-abs(w)));
02246         if (hvsdebug)
02247         {
02248           cout << "Weight: " << w << endl;            
02249         }
02250       }
02251       if (hvsdebug)
02252         cout << "Threshold: " << threshold_[i] << endl;
02253     }
02254   }
02255 
02266   void getNumClauseGndings(Array<double>* const & numGndings, bool tv)
02267   {
02268       // If lazy, then all groundings of pos. clauses not materialized in this
02269       // state are true (non-materialized groundings of neg. clauses are false),
02270       // so if tv is false and clause is pos. (or tv is true and clause is
02271       // neg.), then eager and lazy counts are equivalent. If tv is
02272       // true and clause is pos. (or tv is false and clause is neg.), then we
02273       // need to keep track of true *and* false groundings and
02274       // then subtract from total groundings of the f.o. clause.
02275       
02276       // This holds the false groundings when tv is true and lazy.
02277     Array<double> lazyFalseGndings(numGndings->size(), 0);
02278     Array<double> lazyTrueGndings(numGndings->size(), 0);
02279 
02280     IntBoolPairItr itr;
02281     IntBoolPair *clauseFrequencies;
02282     
02283       // numGndings should have been initialized with non-negative values
02284     int clauseCnt = numGndings->size();
02285     assert(clauseCnt == mln_->getNumClauses());
02286     for (int clauseno = 0; clauseno < clauseCnt; clauseno++)
02287       assert ((*numGndings)[clauseno] >= 0);
02288     
02289     for (int i = 0; i < gndClauses_->size(); i++)
02290     {
02291       GroundClause *gndClause = (*gndClauses_)[i];
02292       int satLitcnt = 0;
02293       for (int j = 0; j < gndClause->getNumGroundPredicates(); j++)
02294       {
02295         int lit = gndClause->getGroundPredicateIndex(j);
02296         if (isTrueLiteral(lit)) satLitcnt++;
02297       }
02298 
02299       clauseFrequencies = gndClause->getClauseFrequencies();
02300       for (itr = clauseFrequencies->begin();
02301            itr != clauseFrequencies->end(); itr++)
02302       {
02303         int clauseno = itr->first;
02304         int frequency = itr->second.first;
02305         bool invertWt = itr->second.second;
02306           // If flipped unit clause, then we want opposite kind of grounding
02307         if (invertWt)
02308         {
02309             // Want true and is true => don't count it
02310           if (tv && satLitcnt > 0)
02311           {
02312               // Lazy: We need to keep track of false groundings also
02313             if (lazy_) lazyFalseGndings[clauseno] += frequency;
02314             continue;
02315           }
02316             // Want false and is false => don't count it
02317           if (!tv && satLitcnt == 0)
02318           {
02319               // Lazy: We need to keep track of false groundings also
02320             if (lazy_) lazyTrueGndings[clauseno] += frequency;
02321             continue;
02322           }
02323         }
02324         else
02325         {
02326             // Want true and is false => don't count it
02327           if (tv && satLitcnt == 0)
02328           {
02329               // Lazy: We need to keep track of false groundings also
02330             if (lazy_) lazyFalseGndings[clauseno] += frequency;
02331             continue;
02332           }
02333             // Want false and is true => don't count it
02334           if (!tv && satLitcnt > 0)
02335           {
02336               // Lazy: We need to keep track of false groundings also
02337             if (lazy_) lazyTrueGndings[clauseno] += frequency;
02338             continue;
02339           }
02340         }
02341         (*numGndings)[clauseno] += frequency;
02342       }
02343     }
02344     
02345       // Getting true counts in lazy: we have to add the remaining groundings
02346       // not materialized (they are by definition true groundings if clause is
02347       // positive, or false groundings if clause is negative)
02348     if (lazy_)
02349     {
02350       for (int c = 0; c < mln_->getNumClauses(); c++)
02351       {
02352         const Clause* clause = mln_->getClause(c);
02353           // Getting true counts and positive clause
02354         if (tv && clause->getWt() >= 0)
02355         {
02356           double totalGndings = domain_->getNumNonEvidGroundings(c);
02357           assert(totalGndings >= (*numGndings)[c] + lazyFalseGndings[c]);
02358           double remainingTrueGndings = totalGndings - lazyFalseGndings[c] -
02359                                         (*numGndings)[c];
02360           (*numGndings)[c] += remainingTrueGndings;
02361         }
02362           // Getting false counts and negative clause
02363         else if (!tv && clause->getWt() < 0)
02364         {
02365           double totalGndings = domain_->getNumNonEvidGroundings(c);
02366           assert(totalGndings >= (*numGndings)[c] + lazyTrueGndings[c]);
02367           double remainingFalseGndings = totalGndings - lazyTrueGndings[c] -
02368                                         (*numGndings)[c];
02369           (*numGndings)[c] += remainingFalseGndings;
02370         }
02371       }
02372     }
02373 
02374   }
02375 
02383   void setOthersInBlockToFalse(const int& atomIdx, const int& blockIdx)
02384   {
02385     if (hvsdebug)
02386     {
02387       cout << "Set all in block " << blockIdx << " to false except "
02388            << atomIdx << endl;
02389     }
02390     int blockSize = domain_->getBlockSize(blockIdx);
02391     for (int i = 0; i < blockSize; i++)
02392     {
02393       const Predicate* pred = domain_->getPredInBlock(i, blockIdx);
02394       GroundPredicate* gndPred = new GroundPredicate((Predicate*)pred);      
02395       int idx = gndPredHashArray_.find(gndPred);
02396 
02397       if (hvsdebug)
02398       {
02399         cout << "Gnd pred in block ";
02400         gndPred->print(cout, domain_);
02401         cout << " (idx " << idx << ")" << endl;
02402       }
02403 
02404       delete gndPred;
02405       delete pred;
02406       
02407         // Pred already present: check that it's not fixed
02408       if (idx >= 0)
02409       {
02410           // Atom not the one specified and not fixed
02411         if (idx != atomIdx && fixedAtom_[idx + 1] == 0)
02412         {
02413           if (hvsdebug)
02414             cout << "Set " << idx + 1 << " to false" << endl;
02415 
02416           bool activate = true;
02417           setValueOfAtom(idx + 1, false, activate, -1);
02418         }
02419       }
02420     }
02421   }
02422 
02429 /*
02430         void setOthersInBlockToFalse(const int& atomIdx,
02431                 const int& blockIdx)
02432         {
02433                 Array<int>& block = (*blocks_)[blockIdx];
02434                 for (int i = 0; i < block.size(); i++)
02435                 {
02436                         // Atom not the one specified and not fixed
02437                         if (i != atomIdx && fixedAtom_[block[i] + 1] == 0)
02438                                 setValueOfAtom(block[i] + 1, false);
02439                 }
02440         }
02441 */
02442 
02451   void fixAtom(const int& atomIdx, const bool& value)
02452   {
02453     assert(atomIdx > 0);
02454     if (hvsdebug)
02455     {
02456       cout << "Fixing ";
02457       (*gndPreds_)[atomIdx - 1]->print(cout, domain_);
02458       cout << " to " << value << endl;    
02459     }
02460 
02461       // Must be in mc-sat
02462     if (!useThreshold_)
02463     {
02464       cout << ">>> [ERR] useThreshold_ is false" << endl;
02465       exit(0);
02466     }
02467 
02468       // If already fixed to opp. sense, then contradiction
02469     if ((fixedAtom_[atomIdx] == 1 && value == false) ||
02470         (fixedAtom_[atomIdx] == -1 && value == true))
02471     {
02472       cout << "Contradiction: Tried to fix atom " << atomIdx <<
02473       " to true and false ... exiting." << endl;
02474       exit(0);
02475     }
02476 
02477       // already fixed
02478     if (fixedAtom_[atomIdx] != 0) return;
02479 
02480     fixedAtom_[atomIdx] = (value) ? 1 : -1; 
02481     if (atom_[atomIdx] != value) 
02482     {
02483       bool activate = false;
02484       int blockIdx =  getBlockIndex(atomIdx - 1);
02485       setValueOfAtom(atomIdx, value, activate, blockIdx);
02486       updateMakeBreakCostAfterFlip(atomIdx);
02487     }
02488     
02489       // update isSat
02490     updateSatisfiedClauses(atomIdx);
02491 
02492       // If in a block and fixing to true, fix all others to false
02493     if (value)
02494     {
02495       int blockIdx = getBlockIndex(atomIdx - 1);
02496       if (blockIdx > -1)
02497       {
02498         int blockSize = domain_->getBlockSize(blockIdx);
02499         for (int i = 0; i < blockSize; i++)
02500         {
02501           const Predicate* pred = domain_->getPredInBlock(i, blockIdx);
02502           GroundPredicate* gndPred = new GroundPredicate((Predicate*)pred);      
02503           int idx = gndPredHashArray_.find(gndPred);
02504           delete gndPred;
02505           delete pred;
02506       
02507             // Pred already present: check that it's not fixed
02508           if (idx >= 0)
02509           {
02510               // Atom not the one specified
02511             if (idx != (atomIdx - 1))
02512             {
02513                 // If already fixed to true, then contradiction
02514               if (fixedAtom_[idx + 1] == 1)
02515               {
02516                 cout << "Contradiction: Tried to fix atom " << idx + 1 <<
02517                 " to true and false ... exiting." << endl;
02518                 exit(0);
02519               }
02520                 // already fixed
02521               if (fixedAtom_[idx + 1] == -1) continue;
02522               if (hvsdebug)
02523               {
02524                 cout << "Fixing ";
02525                 (*gndPreds_)[idx]->print(cout, domain_);
02526                 cout << " to 0" << endl;
02527               }
02528               fixedAtom_[idx + 1] = -1; 
02529               if (atom_[idx + 1] != false) 
02530               {
02531                 bool activate = false;
02532                 setValueOfAtom(idx + 1, value, activate, blockIdx);
02533                 updateMakeBreakCostAfterFlip(idx + 1);
02534               }
02535                 // update isSat
02536               updateSatisfiedClauses(idx + 1);
02537             }
02538           }
02539         }
02540       }
02541     }
02542 
02543       // activate clauses falsified
02544       // need to updateMakeBreakCost for new clauses only, which aren't sat
02545     if (lazy_ && !isActive(atomIdx) && value)
02546     {
02547         // if inactive fixed to true, need to activate falsified
02548         // inactive clauses gather active clauses
02549       Predicate* p =
02550         gndPredHashArray_[atomIdx - 1]->createEquivalentPredicate(domain_);
02551         
02552       bool ignoreActivePreds = false; // only get currently unsat ones
02553       Array<GroundClause*> unsatClauses;
02554       getActiveClauses(p, unsatClauses, true, ignoreActivePreds);       
02555         
02556         // filter out clauses already added (can also add directly, but
02557         // will elicit warning)
02558       addNewClauses(ADD_CLAUSE_REGULAR, unsatClauses);
02559 
02560         // Set active status in db
02561       domain_->getDB()->setActiveStatus(p, true);
02562       activeAtoms_++;
02563 
02564       delete p;
02565     }
02566   }
02567 
02568 
02577 /*
02578         void fixAtom(const int& atomIdx, const bool& value)
02579         {
02580                 assert(atomIdx > 0);
02581                 // If already fixed to opp. sense, then contradiction
02582                 if ((fixedAtom_[atomIdx] == 1 && value == false) ||
02583                         (fixedAtom_[atomIdx] == -1 && value == true))
02584                 {
02585                         cout << "Contradiction: Tried to fix atom " << atomIdx <<
02586                                 " to true and false ... exiting." << endl;
02587                         exit(0);
02588                 }
02589 
02590                 if (hvsdebug)
02591                 {
02592                         cout << "Fixing ";
02593                         (*gndPreds_)[atomIdx - 1]->print(cout, domain_);
02594                         cout << " to " << value << endl;
02595                 }
02596 
02597                 setValueOfAtom(atomIdx, value);
02598                 fixedAtom_[atomIdx] = (value) ? 1 : -1;
02599         }
02600 */
02601 
02613         Array<int>* simplifyClauseFromFixedAtoms(const int& clauseIdx)
02614         {
02615                 Array<int>* returnArray = new Array<int>;
02616                 // If already satisfied from fixed atoms, then return empty array
02617                 if (isSatisfied_[clauseIdx]) return returnArray;
02618 
02619                 // Keeps track of pos. clause being satisfied or 
02620                 // neg. clause being unsatisfied due to fixed atoms
02621                 bool isGood = (clauseCost_[clauseIdx] > 0) ? false : true;
02622                 // Keeps track of all atoms being fixed to false in a pos. clause
02623                 bool allFalseAtoms = (clauseCost_[clauseIdx] > 0) ? true : false;
02624                 // Check each literal in clause
02625                 for (int i = 0; i < getClauseSize(clauseIdx); i++)
02626                 {
02627                         int lit = clause_[clauseIdx][i];
02628                         int fixedValue = fixedAtom_[abs(lit)];
02629 
02630                         if (clauseCost_[clauseIdx] > 0)
02631                         { // Pos. clause: check if clause is satisfied
02632                                 if ((fixedValue == 1 && lit > 0) ||
02633                                         (fixedValue == -1 && lit < 0))
02634                                 { // True fixed lit
02635                                         isGood = true;
02636                                         allFalseAtoms = false;
02637                                         returnArray->clear();
02638                                         break;
02639                                 }
02640                                 else if (fixedValue == 0)
02641                                 { // Lit not fixed
02642                                         allFalseAtoms = false;
02643                                         returnArray->append(lit);
02644                                 }
02645                         }
02646                         else
02647                         { // Neg. clause:
02648                                 assert(clauseCost_[clauseIdx] < 0);
02649                                 if ((fixedValue == 1 && lit > 0) ||
02650                                         (fixedValue == -1 && lit < 0))
02651                                 { // True fixed lit
02652                                         cout << "Contradiction: Tried to fix atom " << abs(lit) <<
02653                                                 " to true in a negative clause ... exiting." << endl;
02654                                         exit(0);
02655                                 }
02656                                 else
02657                                 { // False fixed lit or non-fixed lit
02658                                         returnArray->append(lit);
02659                                         // Non-fixed lit
02660                                         if (fixedValue == 0) isGood = false;          
02661                                 }
02662                         }
02663                 }
02664                 if (allFalseAtoms)
02665                 {
02666                         cout << "Contradiction: All atoms in clause " << clauseIdx <<
02667                                 " fixed to false ... exiting." << endl;
02668                         exit(0);
02669                 }
02670                 if (isGood) isSatisfied_[clauseIdx] = true;
02671                 return returnArray;
02672         }
02673 
02680         const bool isDeadClause(const int& clauseIdx)
02681         {
02682                 return deadClause_[clauseIdx];
02683         }
02684 
02688         void eliminateSoftClauses()
02689         {
02690                 bool atLeastOneDead = false;
02691                 for (int i = 0; i < getNumClauses(); i++)
02692                 {
02693                         if (!(*gndClauses_)[i]->isHardClause())
02694                         {
02695                                 atLeastOneDead = true;
02696                                 deadClause_[i] = true;
02697                         }
02698                 }
02699                 if (atLeastOneDead) initMakeBreakCostWatch();
02700                 initMakeBreakCostWatchCont();
02701         }
02702 
02703         void updateNumTrueLits()//dis
02704         {
02705                 for(int i = 0;i < getNumClauses(); i++)
02706                 {
02707                         numTrueLits_[i] = 0;
02708                         for (int j = 0; j < getClauseSize(i); j++)
02709                         {
02710                                 if (isTrueLiteral(clause_[i][j]))
02711                                 { // ij is true lit
02712                                         numTrueLits_[i]++;
02713                                 }
02714                         }
02715                 }
02716         }
02717 
02725         void killClauses(const int& startClause)
02726         {
02727                 for (int i = startClause; i < getNumClauses(); i++)
02728                 {
02729                         GroundClause* clause = (*gndClauses_)[i];
02730                         if ((clauseGoodInPrevious(i)) &&
02731                                 (clause->isHardClause() || random() <= threshold_[i]))
02732                         {
02733                                 if (hvsdebug)
02734                                 {
02735                                         cout << "Keeping clause "<< i << " ";
02736                                         clause->print(cout, domain_, &gndPredHashArray_);
02737                                         cout << endl;
02738                                 }
02739                                 deadClause_[i] = false;
02740                         }
02741                         else
02742                         {
02743                                 deadClause_[i] = true;
02744                         }
02745                 }
02746 
02747                 if(startClause == 0)
02748                 {
02749                         initMakeBreakCostWatch();
02750                 }
02751                 else
02752                 {
02753                         initMakeBreakCostWatch(startClause);
02754                 }
02755 
02756                 initMakeBreakCostWatchCont();
02757         }
02758 
02759 
02767         const bool clauseGoodInPrevious(const int& clauseIdx)
02768         {
02769                 //GroundClause* clause = (*gndClauses_)[clauseIdx];
02770                 int numSatLits = numTrueLits_[clauseIdx];
02771                 // Num. of satisfied lits in previous iteration is stored in clause
02772                 if ((numSatLits > 0 && clauseCost_[clauseIdx] > 0.0) ||
02773                         (numSatLits == 0 && clauseCost_[clauseIdx] < 0.0))
02774                         return true;
02775                 else
02776                         return false;
02777         }
02778 
02782         void resetDeadClauses()
02783         {
02784                 for (int i = 0; i < deadClause_.size(); i++)
02785                         deadClause_[i] = false;
02786                 initMakeBreakCostWatch();
02787                 initMakeBreakCostWatchCont();           
02788         }
02789 
02790         void resetDeadClausesAndInitMake()
02791         {
02792                 for (int i = 0; i < deadClause_.size(); i++)
02793                         deadClause_[i] = false;
02794                 initMakeBreakCostWatch();
02795         }
02796 
02800         void resetFixedAtoms()
02801         {
02802                 for (int i = 0; i < fixedAtom_.size(); i++)
02803                         fixedAtom_[i] = 0;
02804                 for (int i = 0; i < isSatisfied_.size(); i++)
02805                         isSatisfied_[i] = false;
02806         }
02807 
02808         void setLazy(const bool& l) { lazy_ = l; }
02809         const bool getLazy() { return lazy_; }
02810 
02811         void setUseThreshold(const bool& t) { useThreshold_ = t;}
02812         const bool getUseThreshold() { return useThreshold_; }
02813 
02814         long double getHardWt() { return hardWt_; }
02815 
02816         const Domain* getDomain() { return domain_; }
02817 
02818         const MLN* getMLN() { return mln_; }
02819 
02825         void printLowState(ostream& out)
02826         {
02827                 for (int i = 0; i < getNumAtoms(); i++)
02828                 {
02829                         (*gndPreds_)[i]->print(out, domain_);
02830                         out << " " << lowAtom_[i + 1] << endl;
02831                 }
02832         }
02833 
02834 
02841         void printGndPred(const int& predIndex, ostream& out)
02842         {
02843                 (*gndPreds_)[predIndex]->print(out, domain_);
02844         }
02845 
02847 
02854         GroundPredicate* getGndPred(const int& index)
02855         {
02856                 return (*gndPreds_)[index];
02857         }
02858 
02865         GroundClause* getGndClause(const int& index)
02866         {
02867                 return (*gndClauses_)[index];
02868         }
02869 
02873         void saveLowStateToGndPreds()
02874         {
02875                 //cout << "Entering saveLowStateToGndPreds" << endl;
02876                 for (int i = 0; i < getNumAtoms(); i++)
02877                         (*gndPreds_)[i]->setTruthValue(lowAtom_[i + 1]);
02878                 //cout << "Leaving saveLowStateToGndPreds" << endl;
02879         }
02880 
02884         void saveLowStateToDB()
02885         {
02886                 for (int i = 0; i < getNumAtoms(); i++)
02887                 {
02888                         GroundPredicate* p = gndPredHashArray_[i];
02889                         bool value = lowAtom_[i + 1];
02890                         if (value)
02891                         {
02892                                 domain_->getDB()->setValue(p, TRUE);
02893                         }
02894                         else
02895                         {
02896                                 domain_->getDB()->setValue(p, FALSE);
02897                         }
02898                 }
02899         }
02900 
02907         const int getGndPredIndex(GroundPredicate* const& gndPred)
02908         {
02909                 return gndPreds_->find(gndPred);
02910         }
02912 
02913 
02915 
02929   void getActiveClauses(Predicate *inputPred,
02930                         Array<GroundClause*>& activeClauses,
02931                         bool const & active,
02932                         bool const & ignoreActivePreds)
02933   {
02934     Timer timer;
02935     double currTime;
02936 
02937     Clause *fclause;
02938     GroundClause* newClause;
02939     int clauseCnt;
02940     GroundClauseHashArray clauseHashArray;
02941 
02942     Array<GroundClause*>* newClauses = new Array<GroundClause*>; 
02943   
02944     const Array<IndexClause*>* indexClauses = NULL;
02945       
02946       // inputPred is null: all active clauses should be retrieved
02947     if (inputPred == NULL)
02948     {
02949       clauseCnt = mln_->getNumClauses();
02950     }
02951       // Otherwise, look at all first order clauses containing the pred
02952     else
02953     {
02954       if (domain_->getDB()->getDeactivatedStatus(inputPred)) return;
02955       int predId = inputPred->getId();
02956       indexClauses = mln_->getClausesContainingPred(predId);
02957       clauseCnt = indexClauses->size();
02958     }
02959 
02960       // Look at each first-order clause and get active groundings
02961     int clauseno = 0;
02962 
02963     while (clauseno < clauseCnt)
02964     {
02965       if (inputPred)
02966         fclause = (Clause *) (*indexClauses)[clauseno]->clause;           
02967       else
02968         fclause = (Clause *) mln_->getClause(clauseno);
02969 
02970       if (hvsdebug)
02971       {
02972         cout << "Getting active clauses for FO clause: ";
02973         fclause->print(cout, domain_);
02974         cout << endl;
02975       }
02976 
02977       currTime = timer.time();
02978 
02979       const double* parentWtPtr = NULL;
02980       if (!fclause->isHardClause()) parentWtPtr = fclause->getWtPtr();
02981       const int clauseId = mln_->findClauseIdx(fclause);
02982       newClauses->clear();
02983 
02984       if (stillActivating_)
02985         stillActivating_ = fclause->getActiveClauses(inputPred, domain_,
02986                                                      newClauses,
02987                                                      &gndPredHashArray_,
02988                                                      ignoreActivePreds);
02989 
02990       for (int i = 0; i < newClauses->size(); i++)
02991       {
02992         long double wt = fclause->getWt();
02993         newClause = (*newClauses)[i];
02994 
02995           // If already active, ignore; assume all gndClauses_ are active
02996         if (gndClauses_->find(newClause) >= 0)
02997         {
02998           delete newClause;
02999           continue;
03000         }
03001 
03002         bool invertWt = false;
03003           // We want to normalize soft unit clauses to all be positives
03004         if (!fclause->isHardClause() &&
03005             newClause->getNumGroundPredicates() == 1 &&
03006             !newClause->getGroundPredicateSense(0))
03007         {
03008           newClause->setGroundPredicateSense(0, true);
03009           newClause->setWt(-newClause->getWt());
03010           wt = -wt;
03011           invertWt = true;
03012           int addToIndex = gndClauses_->find(newClause);
03013           if (addToIndex >= 0)
03014           {
03015             (*gndClauses_)[addToIndex]->addWt(wt);
03016             if (parentWtPtr)
03017               (*gndClauses_)[addToIndex]->incrementClauseFrequency(clauseId, 1,
03018                                                                    invertWt);
03019             delete newClause;
03020             continue;
03021           }
03022         }
03023         
03024         int pos = clauseHashArray.find(newClause);
03025           // If clause already present, then just add weight
03026         if (pos >= 0)
03027         {
03028             // Check if already added from this f.o. clause. If so, don't add
03029             // again
03030           if (clauseHashArray[pos]->getClauseFrequency(clauseId) > 0)
03031           {
03032             delete newClause;
03033             continue;
03034           }
03035           if (hvsdebug)
03036           {
03037             cout << "Adding weight " << wt << " to clause ";
03038             clauseHashArray[pos]->print(cout, domain_, &gndPredHashArray_);
03039             cout << endl;
03040           }
03041           clauseHashArray[pos]->addWt(wt);
03042           if (parentWtPtr)
03043             clauseHashArray[pos]->incrementClauseFrequency(clauseId, 1,
03044                                                            invertWt);
03045           delete newClause;
03046           continue;
03047         }
03048 
03049           // If here, then clause is not yet present        
03050         newClause->setWt(wt);
03051         if (parentWtPtr)
03052           newClause->incrementClauseFrequency(clauseId, 1, invertWt);
03053 
03054         if (hvsdebug)
03055         {
03056           cout << "Appending clause ";
03057           newClause->print(cout, domain_, &gndPredHashArray_);
03058           cout << endl;
03059         }
03060         clauseHashArray.append(newClause);
03061       }
03062       clauseno++; 
03063 
03064     } //while (clauseno < clauseCnt)
03065 
03066     for (int i = 0; i < clauseHashArray.size(); i++)
03067     {
03068       newClause = clauseHashArray[i];
03069       activeClauses.append(newClause);
03070     }
03071 
03072     newClauses->clear();
03073     delete newClauses;
03074 
03075     clauseHashArray.clear();
03076   }
03077 
03085         void getActiveClauses(Array<GroundClause*> &allClauses,
03086                 bool const & ignoreActivePreds)
03087         {
03088                 getActiveClauses(NULL, allClauses, true, ignoreActivePreds);
03089         }
03090 
03091         int getNumActiveAtoms()
03092         {
03093                 return activeAtoms_; 
03094         }
03095 
03100 /*
03101         void addOneAtomToEachBlock()
03102         {
03103                 assert(lazy_);
03104                 // For each block: select one to set to true
03105                 for (int i = 0; i < blocks_->size(); i++)
03106                 {
03107                         // If evidence atom exists, then all others are false
03108                         if ((*blockEvidence_)[i])
03109                         {
03110                                 // If first argument is -1, then all are set to false
03111                                 setOthersInBlockToFalse(-1, i);
03112                                 continue;
03113                         }
03114 
03115                         // Assumption is initLazyBlocks has been called
03116                         // Pick one ground pred from the block in the domain
03117                         const Array<Predicate*>* block = domain_->getPredBlock(i);
03118 
03119                         int chosen = random() % block->size();
03120                         Predicate* pred = (*block)[chosen];
03121                         GroundPredicate* groundPred = new GroundPredicate(pred);
03122 
03123                         // If chosen pred is not yet present, then add it, otherwise delete it
03124                         int index = gndPredHashArray_.find(groundPred);
03125                         if (index < 0)
03126                         {
03127                                 // Pred not yet present
03128                                 index = gndPredHashArray_.append(groundPred);
03129                                 (*blocks_)[i].append(index);
03130                                 chosen = (*blocks_)[i].size() - 1;
03131                                 // addNewClauses adds the predicate to the state and updates
03132                                 // info arrays
03133                                 bool initial = false;
03134                                 addNewClauses(initial);
03135                         }
03136                         else
03137                         {
03138                                 delete groundPred;
03139                                 chosen = (*blocks_)[i].find(index);
03140                         }
03141                         setValueOfAtom(index + 1, true);
03142                         setOthersInBlockToFalse(chosen, i);
03143                 }
03144         }
03145 */
03146 
03150         void initLazyBlocks()
03151         {
03152                 assert(lazy_);
03153                 blocks_ = new Array<Array<int> >;
03154                 blocks_->growToSize(domain_->getNumPredBlocks());
03155                 blockEvidence_ = new Array<bool>(*(domain_->getBlockEvidenceArray()));
03156         }
03157 
03161 /*    
03162         void fillLazyBlocks()
03163         {
03164                 assert(lazy_);
03165                 const Array<Array<Predicate*>*>* blocks = domain_->getPredBlocks();
03166                 for (int i = 0; i < blocks->size(); i++)
03167                 {
03168                         if (hvsdebug) cout << "Block " << i << endl;
03169                         Array<Predicate*>* block = (*blocks)[i];
03170                         for (int j = 0; j < block->size(); j++)
03171                         {
03172                                 Predicate* pred = (*block)[j];
03173                                 if (hvsdebug)
03174                                 {
03175                                         cout << "\tPred: ";
03176                                         pred->printWithStrVar(cout, domain_);
03177                                         cout << endl;
03178                                 }
03179                                 // Add all non-evid preds in blocks to the state
03180                                 if (domain_->getDB()->getEvidenceStatus(pred))
03181                                         continue;
03182                                 GroundPredicate* groundPred = new GroundPredicate(pred);
03183 
03184                                 // Add pred if not yet present, otherwise delete it
03185                                 int index = gndPredHashArray_.find(groundPred);
03186                                 if (index < 0)
03187                                         index = gndPredHashArray_.append(groundPred);
03188                                 else
03189                                         delete groundPred;
03190 
03191                                 // Append the atom to the block if not yet there
03192                                 if (!(*blocks_)[i].contains(index))
03193                                         (*blocks_)[i].append(index);
03194                         }
03195                 }
03196                 // addNewClauses adds the predicates to the state and updates info arrays
03197                 bool initial = true;
03198                 addNewClauses(initial);
03199         }
03200 */
03201         /*
03202         Hybrid functions.
03203         */
03204         struct HybridConstraint
03205         {
03206                 int contClauseIdx_;
03207                 double vThreshold_;//if wts > 0, the contraint is greater than th, if wt < 0, the constraint is less than
03208                 bool bSatisfiedLast_;//whether satisfied by last assignment
03209                 int unSatType_;
03210                 HybridConstraint()
03211                 {
03212                         contClauseIdx_ = -1;
03213                         vThreshold_ = 0;
03214                         bSatisfiedLast_ = false;
03215                         unSatType_ = -1;                
03216                 }
03217         };
03218 
03219         void printHybridConstraint(int i, ostream& os)
03220         {
03221                 os << "Information for hybrid constraint " << i <<  ": threshold -- " << hybridConstraints_[i].vThreshold_ << ". weighted value -- " << HybridClauseValue(i) << ". "; 
03222                 os << "Polynomial: "; hybridPls_[i].PrintTo(os); os << endl;
03223                 os << "Discrete variable values: " ;
03224                 for (int j = 0; j < hybridDisClause_[i].size(); ++j) {  
03225                         int predIdx = abs(hybridDisClause_[i][j]);
03226                         os << "<";(*gndPreds_)[predIdx - 1]->print(os, domain_); os << ": " << atom_[predIdx]<< ">, ";
03227                 }
03228                 os << endl;
03229                 os << "Continuous variable values:";
03230                 for (int j = 0; j < hybridContClause_[i].size(); j++)
03231                 {
03232                         int contVarIdx = hybridContClause_[i][j];
03233                         map<int,string>::const_iterator citer = gndPredReverseCont_.find(contVarIdx);
03234                         os << citer->second << ": " << contAtoms_[contVarIdx] << "; ";
03235                 }
03236                 os << endl;
03237         }
03238 
03239         void WriteGndPredIdxMap(const char* gnd_pred_map_file) {
03240                 if ( NULL != gnd_pred_map_file )
03241                 {
03242                         cout << "Saving ground predicate variables into file: " << gnd_pred_map_file << endl;
03243                         ofstream os(gnd_pred_map_file);
03244                         // First write discrete predicates
03245                         for (int i = 0; i < getNumAtoms(); ++i) {
03246                                 (*gndPreds_)[i]->print(os, domain_); os << " " << i + 1<< endl;
03247                         }
03248 
03249                         for (int i = 0; i < getNumContAtoms(); ++i)     {
03250                                 os << gndPredReverseCont_[i + 1] << " " << i + getNumAtoms() + 1 << endl;
03251                         }
03252                         os.close();
03253                 }
03254         }
03255 
03256         //Init the staisfiable status of each cont constraints
03257         void initMakeBreakCostWatchCont() 
03258         {
03259                 if (hvsdebug)
03260                 {
03261                         cout << "entering initMakeBreakCostWatchCont" << endl;
03262                 }
03263 
03264                 weightSumCont_ = 0.0;
03265                 for(int i = 0; i < hybridClauseNum_; ++i)
03266                 {
03267                         if (0 == hybridWts_[i]) {
03268                                 hybridClauseValue_[i] = 0;
03269                                 hybridConstraints_[i].bSatisfiedLast_ = true;
03270                                 hybridConstraints_[i].vThreshold_ = 0;
03271 
03272                                 continue;
03273                         }
03274 
03275                         bool dis = false;
03276                         double cont = 0.0;
03277                         hybridClauseValue_[i] = HybridClauseValue(i, dis, cont);
03278                         hybridClauseDisValue_[i] = dis;
03279                         weightSumCont_ += hybridClauseValue_[i];
03280 
03281                         if (hvsdebug)
03282                         {
03283                                 cout << "clause " << i << " value:" << hybridClauseValue_[i] << endl;
03284                         }
03285                         if (isSatisfied(hybridConstraints_[i], hybridClauseValue_[i]))
03286                         {
03287                                 hybridConstraints_[i].bSatisfiedLast_ = true;
03288                         } else {
03289                                 hybridConstraints_[i].bSatisfiedLast_ = false;
03290                                 hybridFalseClause_[hybridFalseConstraintNum_] = i;
03291                                 hybridWhereFalse_[i] = hybridFalseConstraintNum_;
03292                                 hybridFalseConstraintNum_ ++;
03293                                 totalFalseConstraintNum_++;
03294                                 costOfTotalFalseConstraints_ += fabs(hybridClauseCost_[i]);
03295                                 costHybridFalseConstraint_ += fabs(hybridClauseCost_[i]);
03296 
03297                                 if (dis == 0)
03298                                 {
03299                                         hybridConstraints_[i].unSatType_ = UNSAT_DIS0;
03300                                 }
03301                                 else
03302                                 {
03303                                         hybridConstraints_[i].unSatType_ = UNSAT_DIS1;
03304                                 }
03305                         }
03306                 }
03307 
03308                 if (hvsdebug)
03309                 {
03310                         cout << "leaving initMakeBreakCostWatchCont" << endl;
03311                 }
03312         }
03313 
03314         int getNumContAtoms() { return contAtoms_.size() - 1;}
03315 
03322         int getIndexOfRandomAtom()
03323         {
03324                 assert(totalAtomNum_ > 0);
03325                 int discreteNumAtoms = getNumAtoms();
03326                 int idx = random()%totalAtomNum_;
03327                 if (idx < discreteNumAtoms)
03328                 {
03329                         return (idx + 1);
03330                 }
03331                 else
03332                 {
03333                         return -(idx - discreteNumAtoms + 1);
03334                 }
03335         }
03336 
03342         int getRandomToFixClauseIdx()
03343         {
03344                 int idx = random() % (numFalseClauses_ + hybridClauseNum_);
03345 
03346                 if (idx < numFalseClauses_)
03347                         return falseClause_[idx];
03348                 else return -(idx - numFalseClauses_);
03349         }
03350 
03351         double getCostOfTotalFalseConstraints()
03352         {
03353                 return costOfTotalFalseConstraints_;
03354         }
03355 
03356         double getCostOfAllClauses(double& discost, double& hybridcost)
03357         {
03358                 discost = weightSumDis_;
03359                 hybridcost = weightSumCont_;
03360                 return weightSumDis_ + weightSumCont_;
03361         }
03362 
03363         void UpdateHybridClauseWeightSumByContAtom(const int& atomIdx, const double& atomValue)
03364         {
03365                 contAtoms_[atomIdx] = atomValue;
03366                 for(int i = 0; i < hybridContOccurrence_[atomIdx].size(); i++)
03367                 {
03368                         int contClauseIdx = hybridContOccurrence_[atomIdx][i];
03369                         double vOld = hybridClauseValue_[contClauseIdx];
03370                         hybridClauseValue_[contClauseIdx] = HybridClauseValue(contClauseIdx);
03371                         weightSumCont_ = weightSumCont_ - vOld + hybridClauseValue_[contClauseIdx];
03372                 }
03373         }
03374 
03375         void UpdateHybridClauseWeightSumByDisAtom(const int& atomIdx, bool atomValue)
03376         {
03377                 setValueOfAtom(atomIdx, atomValue, false, -1);
03378                 for(int i = 0; i < hybridDisOccurrence_[atomIdx].size(); i++)
03379                 {
03380                         int contClauseIdx = hybridDisOccurrence_[atomIdx][i];
03381                         double vOld = hybridClauseValue_[contClauseIdx];
03382                         double cont;
03383                         bool dis;
03384                         hybridClauseValue_[contClauseIdx] = HybridClauseValue(contClauseIdx,dis,cont);
03385                         hybridClauseDisValue_[contClauseIdx] = dis;
03386                         weightSumCont_ = weightSumCont_ - vOld + hybridClauseValue_[contClauseIdx];
03387                 }
03388         }
03389 
03390 
03391 
03392         void UpdateHybridClauseInfoByContAtom(const int& atomIdx, const double& atomValue) // update contclause by cont atoms
03393         {
03394                 contAtoms_[atomIdx] = atomValue;
03395                 for(int i = 0; i < hybridContOccurrence_[atomIdx].size(); i++)
03396                 {
03397                         UpdateHybridClause(hybridContOccurrence_[atomIdx][i]);
03398                 }
03399         }
03400 
03401         void UpdateHybridClauseInfoByDisAtom(const int& atomIdx, const bool& atomValue)
03402         {
03403                 setValueOfAtom(atomIdx, atomValue, false, -1);
03404 
03405                 for(int i = 0; i < hybridDisOccurrence_[atomIdx].size(); i++)
03406                 {
03407                         UpdateHybridClause(hybridDisOccurrence_[atomIdx][i]);
03408                 }
03409         }
03410 
03411         // Update the related info for the disClauseValue, clauseValue, weightSum, etc.
03412         // This function could be called by UpdateHybridClauseByCont or UpdateHybridClauseByDis.
03413         // If called by UpdateHybridClauseByCont, then the constraint must be unsatisfied in previous iteration due to HMCS
03414         // If called by UpdateHybridClauseByDis, then it could be satisfied in previous iteration.
03415         void UpdateHybridClause(const int& contClauseIdx)
03416         {
03417                 double cont;
03418                 bool dis;
03419                 double vOld = hybridClauseValue_[contClauseIdx];
03420                 hybridClauseValue_[contClauseIdx] = HybridClauseValue(contClauseIdx, dis, cont);
03421                 hybridClauseDisValue_[contClauseIdx] = dis;
03422                 weightSumCont_ = weightSumCont_ - vOld + hybridClauseValue_[contClauseIdx];
03423                 //hybridClauseValue_[contClauseIdx] = bDis*cont*hybridWts_[contClauseIdx];
03424                 //contDisValue_[contClauseIdx] = int(bDis);
03425                 bool bSatLast = hybridConstraints_[contClauseIdx].bSatisfiedLast_;
03426                 hybridConstraints_[contClauseIdx].bSatisfiedLast_ =
03427                         isSatisfied(hybridConstraints_[contClauseIdx], hybridClauseValue_[contClauseIdx]);
03428 
03429                 if (!hybridConstraints_[contClauseIdx].bSatisfiedLast_)
03430                 {
03431                         if (dis == 0 && hybridConstraints_[contClauseIdx].vThreshold_ > 0)
03432                         {
03433                                 hybridConstraints_[contClauseIdx].unSatType_ = UNSAT_DIS0;
03434                         }
03435                         else if(dis == 1)
03436                         {                                                                                         
03437                                 hybridConstraints_[contClauseIdx].unSatType_ = UNSAT_DIS1;
03438                         }
03439                 }
03440 
03441                 if(bSatLast && !hybridConstraints_[contClauseIdx].bSatisfiedLast_)
03442                 {
03443                         addFalseHybridConstraint(contClauseIdx);// update false cont constraint info
03444                 }
03445 
03446                 if (!bSatLast && hybridConstraints_[contClauseIdx].bSatisfiedLast_)
03447                 {
03448                         removeFalseHybridConstraint(contClauseIdx);
03449                 }
03450         }       
03451 
03452         // 
03453         long double getImprovementRandomMoveCont(const int& atomIdx, const double& atomValue)
03454         {
03455                 double improvement = 0;
03456                 Array<int>& occCont = getContContOccurenceArray(atomIdx);
03457                 double atomVarOrg = contAtoms_[atomIdx];
03458                 contAtoms_[atomIdx] = atomValue;
03459                 for(int i = 0;i < occCont.size(); i++)
03460                 {
03461                         int clauseIdx = occCont[i];
03462                         if (hybridWts_[clauseIdx] == 0 || hybridClauseDisValue_[clauseIdx] == false) {
03463                                 continue;
03464                         }
03465                         double cont;
03466                         bool dis;
03467                         double vCur = HybridClauseValue(clauseIdx,dis,cont);
03468                         double vOld = hybridClauseValue_[clauseIdx];
03469                         improvement += vCur - vOld;
03470                 }
03471                 contAtoms_[atomIdx] = atomVarOrg;
03472                 return improvement;
03473         }
03474 
03475         long double getImprovementInWeightSumByFlipping(const int& atomIdx)
03476         {
03477                 double improvement = 0;
03478                 
03479                 bool toFlipValue = getValueOfAtom(atomIdx);
03480                 int sign;
03481                 int oppSign;
03482                 int litIdx;
03483                 if (toFlipValue)
03484                         sign = 1;
03485                 else
03486                         sign = 0;
03487                 oppSign = sign ^ 1;
03488 
03489                 //flipAtomValue(toFlip);
03490 
03491                 // Update all clauses in which the atom occurs as a true literal
03492                 litIdx = 2*atomIdx - sign;
03493                 Array<int>& posOccArray = getOccurenceArray(litIdx);
03494 
03495                 litIdx = 2*atomIdx - oppSign;
03496                 Array<int>& negOccArray = getOccurenceArray(litIdx);            
03497 
03498 
03499                 for(int i = 0; i < posOccArray.size(); i++) // for those where the atom appears as a true lits
03500                 {
03501                         int clauseIdx = posOccArray[i];
03502                         int numTrueLitsOrg = getNumTrueLits(clauseIdx);
03503                         if (numTrueLitsOrg == 1) // flipped the only true lit, affect the improvement
03504                         {
03505                                 improvement -= clauseCost_[clauseIdx];
03506                         }                
03507                 }
03508 
03509                 for(int i = 0; i < negOccArray.size(); i++)// for those where the atom appears as false lits
03510                 {
03511                          int clauseIdx = negOccArray[i];
03512                          int numTrueLitsOrg = getNumTrueLits(clauseIdx);
03513                          if (numTrueLitsOrg == 0) // change the clause to true, affect the improvement
03514                          {
03515                                  improvement += clauseCost_[clauseIdx];
03516                          }
03517                 }
03518 
03519                 setValueOfAtom(atomIdx, !toFlipValue, false, -1);
03520                 Array<int>& occCont = getContDisOccurenceArray(atomIdx);
03521                 for(int i = 0; i < occCont.size(); i++)
03522                 {
03523                         int clauseIdx = occCont[i];
03524                         if (hybridWts_[clauseIdx] == 0)
03525                         {
03526                                 continue;
03527                         }
03528 
03529                         double vOrg = hybridClauseValue_[clauseIdx];
03530                         double cont;
03531                         bool dis;
03532                         double vCur = HybridClauseValue(clauseIdx,dis,cont);
03533                         improvement += vCur - vOrg;
03534                 }
03535                 setValueOfAtom(atomIdx, toFlipValue, false, -1);
03536                 return improvement;
03537                         
03538         }
03539 
03540         
03542         // Hybrid MC-SAT functions
03544 
03545         // Solve the hybrid constraint according to the given continuous variable.
03546         double SolveConstraintAndRandomSample(const int& contClauseIdx, const int& inIdx) 
03547         {
03548                 double dis = HybridClauseDisPartValue(contClauseIdx);
03549                 // Discrete part is 0, while threshold greater than 0, at this time can not solve by varying continuous variables
03550                 if (fabs(dis) < 0.0001 && hybridConstraints_[contClauseIdx].vThreshold_ > 0) 
03551                 {
03552                         //cout << "unsolvable becoz of dis, constraint: " << contClauseIdx << endl;
03553                         return FLIPDIS;
03554                 }
03555                 // The discrete part is 0 and the threshold is less than 0. The constraint is always satisfied, no matter what values the continuous variables are.
03556                 else if (fabs(dis) < 0.0001 && hybridConstraints_[contClauseIdx].vThreshold_ <= 0)
03557                 {
03558                         return 0;
03559                 }
03560                 else
03561                 {
03562                         DoubleRange r = SolveHybridConstraintToContVar(contClauseIdx, inIdx);
03563                         if (r.iType == 3) // constriant unsolvable
03564                         {
03565                                 return UNSOLVABLE;
03566                         }
03567                         double d = randomSampleRange(r);
03568                         //normalizeContAtomsValueByRange(contContClause_[contClauseIdx][contAtomIdx], d);
03569                         return d;
03570                 }       
03571         }
03572 
03582         long double getImprovementByFlippingDisHMCS(const int& atomIdx) //change to hybrid
03583         {
03584                 if (hvsdebug) {
03585                         cout << "Entering HVariableState::getImprovementByFlippingDisHMCS" << endl;
03586                 }
03587                 assert(atomIdx > 0);
03588                 // This is the improvement from discrete clauses
03589                 long double improvementDis = makeCost_[atomIdx] - breakCost_[atomIdx];
03590                 double improvementHybrid = getDisImproveInHybridByFlippingMCSAT(atomIdx);
03591                 if (hvsdebug) {
03592                         cout << "Leaving HVariableState::getImprovementByFlippingDisHMCS" << endl;
03593                 }
03594                 return improvementDis + improvementHybrid;
03595         }
03596 
03597         // Get the improvement of the hybrid clauses by flipping a single discrete variable.
03598         // Hybrid clause costs are explicitly set to unit. And the improvement is computed as the actual number of newly satisfied constraints.
03599         double getDisImproveInHybridByFlippingMCSAT(const int& atomIdx) 
03600         {       
03601                 if (hvsdebug) {
03602                         cout << "Entering HVariableState::getDisImproveInHybridByFlippingMCSAT" << endl;
03603                 }
03604                 double improvement = 0;
03605                 atom_[atomIdx] = !atom_[atomIdx];
03606                 for(int i = 0; i < hybridDisOccurrence_[atomIdx].size(); i++)
03607                 {
03608                         int contClauseIdx = hybridDisOccurrence_[atomIdx][i];
03609                         if (0 == hybridWts_[contClauseIdx]) continue;
03610                         double contClauseValue = HybridClauseValue(contClauseIdx);
03611                         HybridConstraint& cst = hybridConstraints_[contClauseIdx];
03612                         if (!isSatisfied(cst, contClauseValue) && cst.bSatisfiedLast_) {
03613                                 // Calculate improvement according to cost.
03614                                 // Each hybrid constraint is treated as a single weighted ground formula.
03615                                 improvement = improvement - fabs(hybridClauseCost_[contClauseIdx]);
03616                         } else if (isSatisfied(cst, contClauseValue) && !cst.bSatisfiedLast_) {
03617                                 // each hybrid constraint is treated as a single weighted ground formula
03618                                 improvement = improvement + fabs(hybridClauseCost_[contClauseIdx]);
03619                         }
03620                 }
03621                 atom_[atomIdx] = !atom_[atomIdx];
03622                 if (hvsdebug) {
03623                         cout << "Leaving HVariableState::getDisImproveInHybridByFlippingMCSAT" << endl;
03624                 }
03625                 return improvement;
03626         }
03627 
03628         // Wrapper function to solve a hybrid constraint according to a given continuous variable.
03629         // Return value: a satisfying solution value of the given continuous variable for the constraint. NOVALUE for non-solvable
03630         double SolveHybridConstraintToContVarSample(int contClauseIdx, int inIdx, int maxIter = 100) 
03631         {
03632                 PolyNomial pl = hybridPls_[contClauseIdx];
03633                 int pickAtomIdx = hybridContClause_[contClauseIdx][inIdx];
03634                 if (pl.GetHighestOrder(inIdx) <= 2.0)
03635                 {
03636                         // Polynomials with order equal to or lower than 2 are solved analytically.
03637                         return SolveConstraintAndRandomSample(contClauseIdx, inIdx);
03638                 }
03639                 else  
03640                 {  
03641                         // Polynomials with order higher than 2 are solved with L-BFGS.
03642                         PolyNomial plOneVar = pl;
03643                         plOneVar.ReduceToOneVar(inIdx);
03644                         if (hybridClauseCost_[contClauseIdx] > 0)
03645                         {
03646                                 plOneVar.MultiplyConst(-1.0);
03647                         }                       
03648 
03649                         LBFGSP lbfgsp(-1,-1,1);
03650                         double low, high;
03651                         low = contAtomRange_[pickAtomIdx-1].low;
03652                         high = contAtomRange_[pickAtomIdx-1].high;
03653                         lbfgsp.setLowerBounds(&low);
03654                         lbfgsp.setUpperBounds(&high);
03655 
03656                         lbfgsp.startLBFGS(plOneVar);
03657                         double plValue = plOneVar.ComputePlValue();
03658                         if (hybridClauseCost_[contClauseIdx] > 0)
03659                         {
03660                                 plValue *= -1.0;
03661                         }
03662 
03663                         bool dis = HybridClauseDisPartValue(contClauseIdx);
03664 
03665                         int iter = 0;
03666                         while (!isSatisfied(hybridConstraints_[contClauseIdx], hybridClauseCost_[contClauseIdx] * plValue * double(dis)))
03667                         {
03668                                 lbfgsp.proceedOneStep(plOneVar);
03669                                 ++ iter;                                                        
03670                                 if (iter > maxIter) break;
03671                         }
03672 
03673                         if (iter <= maxIter) //found satisfied solution in 100 iterations
03674                         {
03675                                 // assign this value back as picked value
03676                                 return plOneVar.varValue_[0];
03677                         }
03678                         else // haven't found satisfied solution in 100 iterations
03679                         {
03680                                 return UNSOLVABLE;
03681                         }
03682                 }
03683         }
03684 
03685         // Get HMCS improvement in #satisfying clause by solve the given hybrid constraint to given continuous variable.
03686         // The third parameter returns the value of the picked variable.
03687         // The function returns the improvement for HWalkSAT in HMCS usage.
03688         double GetImprovementBySolvingHybridConstraintToContVar(const int& contClauseIdx, const int& inIdx, double& cont_var_val)
03689         {
03690                 //solve and sample
03691                 cont_var_val = SolveHybridConstraintToContVarSample(contClauseIdx, inIdx);
03692                 double improvement = 0;
03693                 if (cont_var_val == UNSOLVABLE)
03694                 {
03695                         return CANNOTSATCURRENT;//make sure this variable is not picked
03696                 }
03697 
03698                 //save old cont atom value
03699                 int atomIdx = hybridContClause_[contClauseIdx][inIdx];
03700                 double old_val = contAtoms_[atomIdx];
03701                 contAtoms_[atomIdx] = cont_var_val;
03702                 for(int i = 0; i < hybridContOccurrence_[atomIdx].size(); i++)
03703                 {
03704                         int hClause = hybridContOccurrence_[atomIdx][i];
03705                         double hclause_val = HybridClauseValue(hClause);
03706                         //since current assignment can surely satisfy current constraint, we only count the unsatisfied one here                                
03707                         if (!isSatisfied(hybridConstraints_[hClause], hclause_val) && hybridConstraints_[hClause].bSatisfiedLast_)
03708                         {
03709                                 //improvement--;
03710                                 improvement = improvement - fabs(hybridClauseCost_[hClause]);
03711                         }
03712                         else if (isSatisfied(hybridConstraints_[hClause], hclause_val) && !hybridConstraints_[hClause].bSatisfiedLast_)
03713                         {
03714                                 //improvement++;
03715                                 improvement = improvement + fabs(hybridClauseCost_[hClause]);
03716                         }
03717                 }
03718 
03719                 contAtoms_[atomIdx] = old_val; //reset the cont variable value
03720                 return improvement;
03721         }
03722 
03723         bool isConstraintSolvableByCont(const int& contClauseIdx)
03724         {
03725                 double dis = HybridClauseDisPartValue(contClauseIdx);
03726 
03727                 // discrete part is 0, while the constraint threshold is greater than 0
03728                 // at this time it can not be solved by changing any continuous variable(s)
03729                 if (fabs(dis) < SMALLVALUE && hybridConstraints_[contClauseIdx].vThreshold_ > 0) 
03730                 {
03731                         return false;
03732                 }
03733                 // otherwise this constraint is already satisfied
03734                 else if (fabs(dis) < SMALLVALUE && hybridConstraints_[contClauseIdx].vThreshold_ < 0) 
03735                 {
03736                         return true;
03737                 }
03738 
03739                 // we need to compute the optimum value here, if there is no optimum, the program will exit
03740                 // TODO: replace the computation of optimum with L-BFGS-B to adapt arbitrary polynomial
03741 
03742                 double optValue;
03743                 map<int,double>::const_iterator citer;
03744                 if ((citer = contOptimum_.find(contClauseIdx)) != contOptimum_.end())
03745                 {
03746                         optValue = citer->second;
03747                 }
03748                 else
03749                 {
03750                         PolyNomial& pl = hybridPls_[contClauseIdx];
03751                         Array<double> ar;
03752                         int ret = pl.Optimize2(&ar, &optValue);
03753                         if (ret == 0) // found optimum and there is single optimum
03754                         {
03755                                 contOptimum_.insert(map<int,double>::value_type(contClauseIdx, optValue));
03756                                 contOptimumAssignment_.insert(map<int,Array<double> >::value_type(contClauseIdx, ar));
03757                         }
03758                         else // found optimum, but multiple optimum assignment
03759                         {
03760                                 pl.PrintTo(cout);
03761                                 contOptimum_.insert(map<int,double>::value_type(contClauseIdx, optValue));
03762                                 contOptimumAssignment_.insert(map<int,Array<double> >::value_type(contClauseIdx, ar));
03763                         }
03764                 }
03765 
03766                 if (fabs(dis) == 1 
03767                         && optValue * hybridWts_[contClauseIdx] >= hybridConstraints_[contClauseIdx].vThreshold_)
03768                 {
03769                         return true;
03770                 }
03771                 else if (fabs(dis) == 1 
03772                         && optValue * hybridWts_[contClauseIdx] < hybridConstraints_[contClauseIdx].vThreshold_)
03773                 {
03774                         return false;
03775                 }
03776                 return true;
03777         }
03778 
03779         // HMC-SAT style, each hybrid clause is associated with an inequality constraint.
03780         // Return value: positive -- discrete clause, negative -- hybrid clause
03781         int getRandomFalseClauseIndexHMCS()  //need to be changed to adapt hybrid
03782         {
03783                 if (totalFalseConstraintNum_ == 0) return NOVALUE;
03784 
03785                 int idx = random() % totalFalseConstraintNum_;
03786 
03787                 if (idx < numFalseClauses_) //discrete
03788                 {
03789                         return falseClause_[idx] + 1;
03790                 }
03791                 else
03792                 {
03793                         return -(hybridFalseClause_[idx - numFalseClauses_] + 1); //negative for cont clauses
03794                 }
03795         }
03796 
03797         // HMCS: Calculate improvement by changing some continuous variable's value according to a random walk step following some given proposal distribution. 
03798         double GetImprovementByMovingContVar(const int& atomIdx, double& vContAtomFlipped) 
03799         {
03800                 double vLastCont = contAtoms_[atomIdx]; //as miu
03801                 double stdev = proposalStdev_[atomIdx];
03802                 vContAtomFlipped = ExtRandom::gaussRandom(vLastCont, stdev);
03803 
03804                 double improvement = 0;
03805                 //save old cont atom value
03806                 double vOldContAtomValue = contAtoms_[atomIdx];
03807                 contAtoms_[atomIdx] = vContAtomFlipped;
03808 
03809                 for(int i = 0; i < hybridContOccurrence_[atomIdx].size(); i++)
03810                 {
03811                         int contClauseIdx = hybridContOccurrence_[atomIdx][i];
03812                         double cont;
03813                         bool dis;
03814                         double vContClause = HybridClauseValue(hybridContOccurrence_[atomIdx][i],dis,cont);
03815                         //since current assignment can surely satisfy current constraint, we only count the unsatisfied one here                                
03816                         if (!isSatisfied(hybridConstraints_[contClauseIdx], vContClause) && hybridConstraints_[contClauseIdx].bSatisfiedLast_)                          
03817                         {
03818                                 //improvement--;
03819                                 improvement = improvement - fabs(hybridClauseCost_[contClauseIdx]);
03820                         }
03821                         else if (isSatisfied(hybridConstraints_[contClauseIdx], vContClause) && !hybridConstraints_[contClauseIdx].bSatisfiedLast_)
03822                         {
03823                                 //improvement++;
03824                                 improvement = improvement + fabs(hybridClauseCost_[contClauseIdx]);
03825                         }
03826                 }
03827                 //check continuous constraints, assume constraints are in the form C(x) > v
03828                 contAtoms_[atomIdx] = vOldContAtomValue; //reset the cont variable value
03829                 return improvement;
03830         }
03831 
03832 
03833 
03834         void addFalseHybridConstraint(const int& contClauseIdx)
03835         {
03836                 hybridFalseClause_[hybridFalseConstraintNum_] = contClauseIdx;
03837                 hybridWhereFalse_[contClauseIdx] = hybridFalseConstraintNum_;
03838                 hybridFalseConstraintNum_++;
03839                 totalFalseConstraintNum_++;
03840                 costOfTotalFalseConstraints_ += fabs(hybridClauseCost_[contClauseIdx]);
03841                 costHybridFalseConstraint_ += fabs(hybridClauseCost_[contClauseIdx]);
03842         }
03843 
03844         void removeFalseHybridConstraint(const int& contClauseIdx)
03845         {
03846                 hybridFalseConstraintNum_--;
03847                 totalFalseConstraintNum_--;
03848                 hybridFalseClause_[hybridWhereFalse_[contClauseIdx]] = hybridFalseClause_[hybridFalseConstraintNum_];
03849                 hybridWhereFalse_[hybridFalseClause_[hybridFalseConstraintNum_]] = hybridWhereFalse_[contClauseIdx];
03850                 costOfTotalFalseConstraints_ -= fabs(hybridClauseCost_[contClauseIdx]);
03851                 costHybridFalseConstraint_ -= fabs(hybridClauseCost_[contClauseIdx]);
03852         }
03853 
03854         //  Update hybrid constraint thresholds
03855         void UpdateHybridConstraintTh() 
03856         {
03857                 for(int i = 0; i < hybridClauseNum_; i++)
03858                 {
03859                         hybridConstraints_[i].vThreshold_ = hybridClauseValue_[i] + log((double(random()) + 0.1)/double(RAND_MAX));
03860                 }                                                                       
03861         }
03862 
03863         void addFalseClause(const int& clauseIdx)
03864         {
03865                 falseClause_[numFalseClauses_] = clauseIdx;
03866                 whereFalse_[clauseIdx] = numFalseClauses_;
03867                 numFalseClauses_++;
03868                 totalFalseConstraintNum_++;
03869                 costOfFalseClauses_ += fabs(clauseCost_[clauseIdx]);
03870                 costOfTotalFalseConstraints_ += fabs(clauseCost_[clauseIdx]);
03871         }
03872 
03876         void removeFalseClause(const int& clauseIdx)
03877         {
03878                 numFalseClauses_--;
03879                 totalFalseConstraintNum_--;
03880                 falseClause_[whereFalse_[clauseIdx]] = falseClause_[numFalseClauses_];
03881                 whereFalse_[falseClause_[numFalseClauses_]] = whereFalse_[clauseIdx];
03882                 costOfFalseClauses_ -= abs(clauseCost_[clauseIdx]);
03883                 costOfTotalFalseConstraints_ -= abs(clauseCost_[clauseIdx]);
03884         }
03885 
03890         void makeUnitCosts()
03891         {
03892                 for (int i = 0; i < clauseCost_.size(); i++)
03893                 {
03894                         // All hard clauses would have weight 1.0 .
03895                         if (clauseCost_[i] > 0) clauseCost_[i] = 1.0;
03896                         else {
03897                                 assert(clauseCost_[i] < 0);
03898                                 clauseCost_[i] = -1.0;
03899                         }
03900                 }
03901 
03902                 for(int i = 0; i < hybridClauseCost_.size(); i++)
03903                 {
03904                         if (hybridClauseCost_[i] > 0) hybridClauseCost_[i] = 1.0;
03905                         else
03906                         {
03907                                 assert(hybridClauseCost_[i] < 0);
03908                                 hybridClauseCost_[i] = -1.0;
03909                         }
03910                 }
03911         }
03912 
03913 
03914 
03915 
03916 
03917 
03919         // Hybrid MaxWalkSAT functions
03921         // This function try to look for optimal variable assignment for each numeric term
03922         // And the corresponding state entry is set to true or false.
03923         void optimizeIndividualNumTerm() // for H-MaxWalkSAT
03924         {
03925                 // Using contsolvers_ which is initialized in setProposalStdev.
03926                 for (int i = 0; i < hybridClauseNum_; i++)
03927                 {
03928                         PolyNomial pl = hybridPls_[i];
03929                         int varNum = pl.GetVarNum();                    
03930                         LBFGSP lbfgsp(-1,-1,varNum);
03931                         double* upper = new double[varNum];
03932                         double* lower = new double[varNum];
03933                         for(int k = 0; k < varNum; k++)
03934                         {
03935                                 upper[k] = contAtomRange_[hybridContClause_[i][k]-1].high;
03936                                 lower[k] = contAtomRange_[hybridContClause_[i][k]-1].low;
03937                         }
03938                         lbfgsp.setUpperBounds(upper);
03939                         lbfgsp.setLowerBounds(lower);
03940 
03941                         // Since the L-BfGS package only support minize functionality interface.
03942                         // We assume the weight contribution from num terms are negative,
03943                         // s.t., we could achieve the optimal value by minimizing its negation.
03944                         if (hybridClauseCost_[i] > 0)   
03945                         {
03946                                 pl.MultiplyConst(-1.0);
03947                         }
03948 
03949                         int iter;
03950                         bool berror;
03951                         double f = lbfgsp.minimize(iter, berror, pl);
03952                         //in H-MAXWALKSAT, the values are not gonna to be changed
03953                         lbfgsCache_[i].copyFrom(pl.GetVarValue());
03954                         if(hybridClauseCost_[i] > 0) f *= -1.0;
03955                         hmwsContOptimal_[i] = f;
03956                         if ((f > 0 && hybridClauseCost_[i] > 0) || (hybridClauseCost_[i] < 0 && f < 0))
03957                         {
03958                                 hmwsDisOptimal_[i] = true;
03959                         }
03960                         else if ((f > 0 && hybridClauseCost_[i] < 0) || (hybridClauseCost_[i] > 0 && f < 0))
03961                         {
03962                                 hmwsDisOptimal_[i] = false;
03963                         }
03964 
03965                         delete[] upper;
03966                         delete[] lower;
03967                 }
03968         }
03969 
03970         // Given a set of continuous variables, compute its Markov blanket in the HMLN (the hybrid clauses involving these variables -- S, assume values of all other variables are fixed). 
03971         // Then optimize the Markov blanket according to these variables. Save the variable values in assign.
03972         // Return value is the improvement of weighted sum on the Markov blanket.
03973         // Due to the implementation limit of Polynomial class, the variable order in the contVarIdx has to be the same as in their polynomial.
03974         // This function doesn't change the state variables' values.
03975         double ReduceClauseAndOptimize(const Array<int>& contVarIdx, Array<double>& assign)
03976         {
03977                 if (hvsdebug) {
03978                         cout << "Entering ReduceClauseAndOptimize ...." << endl;
03979                 }
03980                 set<int> occ;
03981                 for(int i = 0; i < contVarIdx.size(); i++)
03982                 {
03983                         Array<int>& ar = getContContOccurenceArray(contVarIdx[i]);
03984                         for(int j = 0; j < ar.size(); j++)
03985                         {
03986                                 if (occ.find(ar[j]) == occ.end())
03987                                 {
03988                                         occ.insert(ar[j]);
03989                                 }
03990                         }
03991                 }
03992 
03993                 PolyNomial pl;
03994                 double orgSum = 0;
03995                 for(set<int>::iterator it = occ.begin(); it != occ.end(); ++it)
03996                 {
03997                         int contClauseIdx = *it;
03998                         if (hybridClauseDisValue_[contClauseIdx] == false) {
03999                                 continue;
04000                         }
04001                         PolyNomial pltmp = hybridPls_[contClauseIdx];
04002                         pltmp.MultiplyConst(hybridWts_[contClauseIdx]);
04003                         pl.AddPl(pltmp);
04004                         orgSum += hybridClauseValue_[contClauseIdx];
04005                 }
04006 
04007                 if (pl.GetVarNum() == 0)  // All dis part of the corrsponding rules are 0
04008                 {
04009                         cout << "No hybrid rule is activated ..." << endl;
04010                         return NOVALUE;
04011                 }
04012 
04013                 // we use lbfgs to solutionve the optimization problem
04014                 pl.MultiplyConst(-1.0);
04015                 LBFGSP lbfgsp(-1, -1, pl.GetVarNum());
04016                 double* upper = new double[pl.GetVarNum()];
04017                 double* lower = new double[pl.GetVarNum()];
04018                 for (int k = 0; k < pl.GetVarNum(); ++k)
04019                 {
04020                         upper[k] = 10000;
04021                         lower[k] = -10000;
04022                 }
04023                 
04024                 lbfgsp.setUpperBounds(upper);
04025                 lbfgsp.setLowerBounds(lower);           
04026 
04027                 int iter;
04028                 bool berror;
04029                 double f = lbfgsp.minimize(iter, berror, pl);
04030                 delete[] upper;
04031                 delete[] lower;         
04032 
04033                 assign.clear();
04034                 assign.copyFrom(pl.GetVarValue());
04035 
04036                 if (hvsdebug) {
04037                         cout << "Leaving ReduceClauseAndOptimize ...." << endl;
04038                 }
04039 
04040                 return f*(-1.0) - orgSum;
04041         }
04042 
04043 
04044         // The single variable version of the above function.
04045         double ReduceClauseAndOptimize(const int& contVarIdx, double* assign)
04046         {
04047                 if (hvsdebug) {
04048                         cout << "Entering ReduceClauseAndOptimize ...." << endl;
04049                 }
04050                 set<int> occ;
04051                 Array<int>& ar = getContContOccurenceArray(contVarIdx);
04052                 for(int j = 0; j < ar.size(); ++j)
04053                 {
04054                         if (occ.find(ar[j]) == occ.end())
04055                         {
04056                                 occ.insert(ar[j]);
04057                         }
04058                 }
04059 
04060                 PolyNomial pl;
04061                 double orgSum = 0;
04062                 for(set<int>::iterator it = occ.begin(); it != occ.end(); ++it)
04063                 {
04064                         int contClauseIdx = *it;
04065                         if (hybridClauseDisValue_[contClauseIdx] == false || hybridWts_[contClauseIdx] == 0) {
04066                                 continue;
04067                         }
04068                         int curInIdx = -1;
04069                         Array<double> var_value;
04070                         for (int i = 0; i < hybridContClause_[contClauseIdx].size(); ++i) {
04071                                 int cont_var_idx = hybridContClause_[contClauseIdx][i];
04072                                 var_value.append(contAtoms_[cont_var_idx]);
04073                                 if (hybridContClause_[contClauseIdx][i] == contVarIdx) {
04074                                         curInIdx = i;
04075                                 }
04076                         }
04077 
04078                         if (curInIdx == -1) {
04079                                 return NOVALUE;
04080                         }
04081                                                 
04082                         PolyNomial pltmp = hybridPls_[contClauseIdx];
04083                         pltmp.MultiplyConst(hybridWts_[contClauseIdx]);
04084                         pltmp.ReduceToOneVar(var_value, curInIdx);
04085 
04086                         pl.AddPl(pltmp);                        
04087                         orgSum += hybridClauseValue_[contClauseIdx];
04088                 }
04089                 
04090                 if (pl.GetVarNum() != 1) {
04091                         // The Markov blanket here could be 0.
04092                         return NOVALUE;
04093                 }
04094                 // we use lbfgs to solutionve the optimization problem
04095                 pl.MultiplyConst(-1.0);
04096                 LBFGSP lbfgsp(-1, -1, 1);
04097                 double upper = 10000000;
04098                 double lower = -10000000;
04099 
04100                 lbfgsp.setUpperBounds(&upper);
04101                 lbfgsp.setLowerBounds(&lower);          
04102 
04103                 int iter;
04104                 bool berror;
04105                 double f = lbfgsp.minimize(iter, berror, pl);
04106 
04107                 *assign = pl.GetVarValue(0);
04108                 if (hvsdebug) {
04109                         cout << "Leaving ReduceClauseAndOptimize ...." << endl;
04110                 }
04111 
04112                 return f*(-1.0) - orgSum;
04113         }
04114 
04115         double OptimizeHybridClauseToContVar(int clause_idx, int cont_var_inIdx) {
04116 
04117                 PolyNomial pl = hybridPls_[clause_idx];  // Make a copy of the original polynomial.
04118                 Array<double> var_value;
04119                 for (int i = 0; i < hybridContClause_[clause_idx].size(); ++i) {
04120                         int cont_var_idx = hybridContClause_[clause_idx][i];
04121                         var_value.append(contAtoms_[cont_var_idx]);
04122                 }
04123                 pl.SetVarValue(var_value);
04124                 pl.ReduceToOneVar(cont_var_inIdx);
04125                 LBFGSP lbfgsp(-1,-1, pl.GetVarNum());
04126                 double* upper = new double[pl.GetVarNum()];
04127                 double* lower = new double[pl.GetVarNum()];
04128                 for(int k = 0; k < pl.GetVarNum(); k++)
04129                 {
04130                         upper[k] = 10000;
04131                         lower[k] = -10000;
04132                 }
04133                 lbfgsp.setUpperBounds(upper);
04134                 lbfgsp.setLowerBounds(lower);
04135 
04136                 int iter;
04137                 bool berror;
04138                 lbfgsp.minimize(iter, berror, pl);
04139 
04140                 delete[] upper;
04141                 delete[] lower;         
04142                 return pl.varValue_[0];
04143         }
04144 
04145         long double getImprovementByFlippingDisHMWS(const int& atomIdx) //change to hybrid
04146         {
04147                 assert(atomIdx > 0);
04148                 long double improvementDis = makeCost_[atomIdx] - breakCost_[atomIdx];// this is the improvement from discrete clauses
04149                 double improvementCont = getDisImproveInHybridByFlippingHMWS(atomIdx);
04150                 return improvementDis + improvementCont;
04151         }
04152 
04153         // Get the improvement of the continuous clauses by flipping a single discrete variable
04154         // The improvement is computed as the actual weighted sum of hybrid feature values.
04155         double getDisImproveInHybridByFlippingHMWS(const int& atomIdx) 
04156         {       
04157                 double improvement = 0; 
04158                 for(int i = 0; i < hybridDisOccurrence_[atomIdx].size(); i++)
04159                 {
04160                         int contClauseIdx = hybridDisOccurrence_[atomIdx][i];
04161                         if (hybridWts_[contClauseIdx] == 0)     continue;
04162                         double hybridClauseValueBeforeFlip = HybridClauseValue(contClauseIdx);
04163                         atom_[atomIdx] = !atom_[atomIdx];
04164                         double hybridClauseValueAfterFlip = HybridClauseValue(contClauseIdx);
04165                         improvement += hybridClauseValueAfterFlip - hybridClauseValueBeforeFlip;
04166                         atom_[atomIdx] = !atom_[atomIdx];
04167                 }
04168                 return improvement;
04169         }
04170 
04171         int getRandomFalseClauseIndexHMWS()  //need to be changed to adapt hybrid
04172         {
04173                 int totalFalseClauseNum = numFalseClauses_ + hybridClauseNum_;
04174                 int idx = random() % totalFalseClauseNum;
04175 
04176                 if (idx < numFalseClauses_) //discrete
04177                 {
04178                         return falseClause_[idx] + 1;
04179                 }
04180                 else
04181                 {
04182                         return -(idx - numFalseClauses_ + 1); //negative for cont clauses
04183                 }
04184         }
04185 
04186         
04187         double getContVarValueByRandomMove(const int& atomIdx)
04188         {
04189                 double vLastCont = contAtoms_[atomIdx]; //as miu
04190                 double stdev = proposalStdev_[atomIdx];
04191                 double vContAtomFlipped = ExtRandom::gaussRandom(vLastCont, stdev);
04192                 return vContAtomFlipped;
04193         }
04194 
04195 
04196         Array<int>& getContDisOccurenceArray(const int& idx)
04197         {
04198                 return hybridDisOccurrence_[idx];
04199         }
04200 
04201 
04202         Array<int>& getContContOccurenceArray(const int& idx)
04203         {
04204                 return hybridContOccurrence_[idx];
04205         }
04206 
04207         
04211         const double getMaxClauseWeightTotal()
04212         {
04213                 double maxWeight = 0.0;
04214                 for (int i = 0; i < getNumClauses(); i++)
04215                 {
04216                         double weight = abs(clauseCost_[i]);
04217                         if (weight > maxWeight) maxWeight = weight;
04218                 }
04219 
04220                 for(int i = 0; i < hybridClauseNum_; i++)
04221                 {
04222                         double weight = abs(hybridClauseCost_[i]);
04223                         if (weight > maxWeight) maxWeight = weight;
04224                 }
04225                 return maxWeight;
04226         }
04227 
04231         const long double getLowCostAll()
04232         {
04233                 return lowCostAll_; 
04234         }
04235 
04239         const int getLowBadAll()
04240         {
04241                 return lowBadAll_;
04242         }
04243 
04244 
04245         const long double getLowCostCont()
04246         {
04247                 return lowCostHybrid_; 
04248         }
04249 
04253         const int getLowBadCont()
04254         {
04255                 return lowBadHybrid_;
04256         }
04257 
04258         void printFalseClauses(ostream& os)
04259         {
04260                 os << "dis false clauses:" << endl;
04261                 for(int i = 0; i < numFalseClauses_; i++)
04262                 {
04263                         int fcIdx = falseClause_[i];
04264                         GroundClause* pC = getGndClause(fcIdx);
04265                         os << "clause " << fcIdx << ":";pC->printWithWtAndStrVar(os, domain_, &gndPredHashArray_);
04266                         os << "  ";
04267                         for(int j = 0; j < clause_[fcIdx].size(); j++)
04268                         {
04269                                 int predIdx = abs(clause_[fcIdx][j]);
04270                                 (*gndPreds_)[predIdx-1]->print(os, domain_);
04271                                 os << ": " << atom_[predIdx] <<"; ";
04272                         }
04273                         os << endl;
04274                 }
04275                 os << "cont false clauses:" << endl;
04276                 for(int i = 0;i < hybridFalseConstraintNum_; i++)
04277                 {
04278                         int fcIdx = hybridFalseClause_[i];
04279                         printHybridConstraint(fcIdx, os);
04280                         os << endl;                     
04281                 }
04282 
04283         }
04284 
04285 
04286 
04287         
04288         void saveLowToCurrentAll()
04289         {
04290            saveLowToCurrentDis();
04291            saveLowToCurrentCont();
04292            costOfTotalFalseConstraints_ = lowCostAll_;
04293            totalFalseConstraintNum_ = lowBadAll_;
04294         }
04295 
04296         void saveLowToCurrentDis()
04297         {
04298 //cout << "entering saveLowToCurrentDis" << endl;
04299                 atom_.copyFrom(lowAtom_);
04300                 costOfFalseClauses_=  lowCost_;
04301                 numFalseClauses_ = lowBad_;
04302                 falseClause_.copyFrom(falseClauseLow_);
04303                 
04304 //cout << "leaving saveLowToCurrentDis" << endl;
04305         }
04306 
04307         void saveLowToCurrentCont()
04308         {
04309                 contAtomsBackup_.copyFrom(contAtoms_);
04310                 contAtoms_.copyFrom(contAtomsLow_);
04311                 costHybridFalseConstraint_ = lowCostHybrid_;
04312                 hybridFalseConstraintNum_ = lowBadHybrid_;
04313                 hybridFalseClause_.copyFrom(hybridFalseClauseLow_);
04314         }
04315 
04316 
04317         void saveLowStateAll()
04318         {
04319            saveLowState();
04320            saveLowStateCont();
04321            
04322            lowCostAll_ = costOfTotalFalseConstraints_ ;
04323            lowBadAll_ = totalFalseConstraintNum_ ;   
04324         }
04325         void saveLowStateCont()
04326         {
04327                 for (int i = 1; i <= contAtomNum_; i++)
04328                 {
04329                         contAtomsLow_[i] = contAtoms_[i];
04330                         if (hvsdebug) cout << contAtomsLow_[i] << endl;
04331                 }
04332                 lowCostHybrid_ = costHybridFalseConstraint_;
04333                 lowBadHybrid_ = hybridFalseConstraintNum_;
04334                 hybridFalseClauseLow_.copyFrom(hybridFalseClause_);
04335         }
04339         // Save the current variable assignment as the last snapshot for future use.
04340         void saveCurrentAsLastAssignment() 
04341         {
04342                 atomsLast_.copyFrom(atom_);
04343                 contAtomsLast_.copyFrom(contAtoms_);
04344         }
04345 
04346         void saveLastAsCurrentAssignment()
04347         {
04348                 atom_.copyFrom(atomsLast_);
04349                 contAtoms_.copyFrom(contAtomsLast_);
04350         }
04351         void updateCost()
04352         {
04353                 hybridFalseConstraintNum_  = 0;
04354                 costHybridFalseConstraint_ = 0;
04355                 totalFalseConstraintNum_ = 0;
04356                 costOfTotalFalseConstraints_ = 0;
04357                 numFalseClauses_ = 0;
04358                 costOfFalseClauses_ = 0;         
04359                 weightSumCont_ = 0;
04360                 weightSumDis_ = 0;
04361                 initMakeBreakCostWatch();
04362                 initMakeBreakCostWatchCont();
04363         }
04364         
04365         // Used by learning. 
04366         // Compute the value sum of given first-order hybrid formula from the ground values of hybrid variables.
04367         void getContClauseGndings(Array<double>* const & numGndings)
04368         {
04369                 assert(numGndings->size() == hybridFormulaNum_);
04370                 for(int i = 0; i < hybridFormulaNum_; i++) // First-order hybrid formulas.
04371                 {
04372                         Array<int>& ar = hybridFormulaGndClauseIdx_[i]; // Index of ground hybrid clauses.
04373                         double v = 0;
04374                         for(int j = 0; j < ar.size(); j++)
04375                         {
04376                                  v += hybridClauseValue_[ar[j]];
04377                                 
04378                         }
04379                         (*numGndings)[i] += v;
04380                 }
04381         }
04382 
04383         void getContClauseGndingsWithUnknown(double numGndings[], int contClauseCnt, const Array<bool>* const& unknownPred)
04384         {
04385                 assert(unknownPred->size() == getNumAtoms());
04386                 assert(contClauseCnt == getNumContFormulas());
04387 
04388                 for (int clauseno = 0; clauseno < contClauseCnt; clauseno++)
04389                         numGndings[clauseno] = 0;
04390                 for(int i = 0; i < contClauseCnt; i++)
04391                 {
04392                         Array<int>& ar = hybridFormulaGndClauseIdx_[i];
04393                         for(int j = 0;j < ar.size(); j++)
04394                         {
04395                                 int contClauseIdx = ar[j];
04396                                 Array<int>& contDis = hybridDisClause_[contClauseIdx];
04397                                 bool bUnknown = false;
04398                                 int satLitcnt = 0;
04399                                 for(int k = 0; k < contDis.size(); k++)
04400                                 {
04401                                         int lit = contDis[k];
04402                                         if ((*unknownPred)[abs(lit) - 1])
04403                                         {
04404                                                 bUnknown = true;
04405                                                 continue;
04406                                         }
04407                                         if (isTrueLiteral(lit)) satLitcnt++;
04408                                 }
04409                                 if (hybridConjunctionDisjunction_[contClauseIdx]) // ^, and
04410                                 {
04411                                         if (bUnknown)
04412                                         {
04413                                                 cout << "unknown, shouldn't be here" << endl;
04414                                                 continue;
04415                                         }
04416                                         else if (satLitcnt < contDis.size()) //dispart false
04417                                         {
04418                                                 numGndings[i] += 0;
04419                                         }
04420                                         else //dis part true
04421                                         {
04422                                                 numGndings[i] += HybridClauseValueNonWt(contClauseIdx);
04423                                         }                               
04424                                 }
04425                                 else // v, or
04426                                 {
04427                                         if (satLitcnt > 0)
04428                                         {
04429                                                 numGndings[i] += HybridClauseValueNonWt(contClauseIdx);
04430                                         }
04431                                         else if (bUnknown)
04432                                         {
04433                                                 cout << "unknown, shouldn't be here" << endl;
04434                                                 continue;
04435                                         }
04436                                         else
04437                                         {
04438                                                 numGndings[i] += 0;
04439                                         }
04440                                 }
04441                         }
04442                 }
04443         }
04444     
04456   void getNumClauseGndingsWithUnknown(double numGndings[], int clauseCnt,
04457                                       bool tv,
04458                                       const Array<bool>* const& unknownPred)
04459   {
04460     // TODO: lazy version
04461     assert(unknownPred->size() == getNumAtoms());
04462     IntBoolPairItr itr;
04463     IntBoolPair *clauseFrequencies;
04464     
04465     for (int clauseno = 0; clauseno < clauseCnt; clauseno++)
04466       numGndings[clauseno] = 0;
04467     
04468     for (int i = 0; i < gndClauses_->size(); i++)
04469     {
04470       GroundClause *gndClause = (*gndClauses_)[i];
04471       int satLitcnt = 0;
04472       bool unknown = false;
04473       for (int j = 0; j < gndClause->getNumGroundPredicates(); j++)
04474       {
04475         int lit = gndClause->getGroundPredicateIndex(j);
04476         if ((*unknownPred)[abs(lit) - 1])
04477         {
04478           unknown = true;
04479           continue;
04480         }
04481         if (isTrueLiteral(lit)) satLitcnt++;
04482       }
04483 
04484       clauseFrequencies = gndClause->getClauseFrequencies();
04485       for (itr = clauseFrequencies->begin();
04486            itr != clauseFrequencies->end(); itr++)
04487       {
04488         int clauseno = itr->first;
04489         int frequency = itr->second.first;
04490         bool invertWt = itr->second.second;
04491           // If flipped unit clause, then we want opposite kind of grounding
04492         if (invertWt)
04493         {
04494             // Want true and is true or unknown => don't count it
04495           if (tv && (satLitcnt > 0 || unknown))
04496             continue;
04497             // Want false and is false => don't count it
04498           if (!tv && satLitcnt == 0)
04499             continue;
04500         }
04501         else
04502         {
04503             // Want true and is false => don't count it
04504           if (tv && satLitcnt == 0)
04505             continue;
04506             // Want false and is true => don't count it
04507           if (!tv && (satLitcnt > 0 || unknown))
04508             continue;
04509         }
04510         numGndings[clauseno] += frequency;
04511       }
04512     }
04513   }
04514     
04515     
04527 /*
04528         void getNumClauseGndingsWithUnknown(double numGndings[], int clauseCnt,
04529                 bool tv,
04530                 const Array<bool>* const& unknownPred)
04531         {
04532                 assert(unknownPred->size() == getNumAtoms());
04533                 IntBoolPairItr itr;
04534                 IntBoolPairItr *clauseFrequencies;
04535 
04536                 for (int clauseno = 0; clauseno < clauseCnt; clauseno++)
04537                         numGndings[clauseno] = 0;
04538 
04539                 for (int i = 0; i < gndClauses_->size(); i++)
04540                 {
04541                         GroundClause *gndClause = (*gndClauses_)[i];
04542                         int satLitcnt = 0;
04543                         bool unknown = false;
04544                         for (int j = 0; j < gndClause->getNumGroundPredicates(); j++)
04545                         {
04546                                 int lit = gndClause->getGroundPredicateIndex(j);
04547                                 if ((*unknownPred)[abs(lit) - 1])
04548                                 {
04549                                         unknown = true;
04550                                         continue;
04551                                 }
04552                                 if (isTrueLiteral(lit)) satLitcnt++;
04553                         }
04554 
04555                         if (tv && satLitcnt == 0)
04556                                 continue;
04557                         if (!tv && (satLitcnt > 0 || unknown))
04558                                 continue;
04559 
04560                         clauseFrequencies = gndClause->getClauseFrequencies();
04561                         for (itr = clauseFrequencies->begin();
04562                                 itr != clauseFrequencies->end(); itr++)
04563                         {
04564                                 int clauseno = itr->first;
04565                                 int frequency = itr->second;
04566                                 numGndings[clauseno] += frequency;
04567                         }
04568                 }
04569         }
04570 */
04571 
04572 
04573 
04574         void printLowStateCont(ostream& os)
04575         {
04576                 for(int i = 0; i < contAtomNum_; i++)
04577                 {
04578                         map<int,string>::const_iterator citer = gndPredReverseCont_.find(i+1);
04579                         os << citer->second << " " <<contAtoms_[i+1] << endl;
04580                 }
04581         }
04582 
04583         void printLowStateAll(ostream& os)
04584         {
04585                 printLowState(os);
04586                 printLowStateCont(os);
04587         }
04588 
04589 
04591 
04593         //WJ: functions for handling hybrid problems.
04595 
04596         // Record in the second variable the atoms to be flipped to make the discrete part of a hybrid clause to be false.
04597         // The flip operation is not actually performed.
04598         void recordAtomMakeDisClauseFalse(int clauseIdx, Array<int>* record)
04599         {
04600                 RecordAtomMakeClauseFalse(hybridDisClause_[clauseIdx], atom_, hybridConjunctionDisjunction_[clauseIdx], record);
04601         }
04602 
04603 
04604         // Record in the second variable the atoms to be flipped to make the discrete part of a hybrid clause to be true.
04605         // The flip operation is not actually performed.
04606         void recordAtomMakeDisClauseTrue(int clauseIdx, Array<int>* record)
04607         {
04608                 RecordAtomMakeClauseTrue(hybridDisClause_[clauseIdx], atom_, hybridConjunctionDisjunction_[clauseIdx], record);
04609         }
04610 
04611         double HybridClauseValueNonWt(int contClauseIdx)
04612         {
04613                 return HybridClauseContPartValue(contClauseIdx) * double(HybridClauseDisPartValue(contClauseIdx));
04614         }
04615         double HybridClauseValue(int contClauseIdx, bool& dis, double& cont)
04616         {
04617                 dis = HybridClauseDisPartValue(contClauseIdx);
04618                 cont = HybridClauseContPartValue(contClauseIdx);
04619                 if (0 == dis)
04620                 {
04621                         return 0;
04622                 }
04623 
04624                 return hybridWts_[contClauseIdx] * double(dis) * cont;
04625         }
04626 
04627         double HybridClauseValue(int contClauseIdx)
04628         {
04629                 bool dis = 0;
04630                 double cont = 0;
04631                 return HybridClauseValue(contClauseIdx, dis, cont);
04632         }
04633 
04634         double HybridClauseContPartValue(int contClauseIdx)
04635         {
04636                 PolyNomial& pl = GetHybridClausePolynomial(contClauseIdx);
04637                 assert(hybridContClause_[contClauseIdx].size() == pl.GetVarNum());              
04638                 Array<double> cont_var_values;
04639                 for(int i = 0; i < hybridContClause_[contClauseIdx].size(); i++)
04640                 {
04641                         cont_var_values.append(contAtoms_[hybridContClause_[contClauseIdx][i]]);
04642                 }
04643                 return pl.ComputePlValue(cont_var_values);
04644         }
04645 
04646         bool HybridClauseDisPartValue(int contClauseIdx)
04647         {
04648                 Array<int>& contDisClause = hybridDisClause_[contClauseIdx];
04649                 bool bClause;
04650                 if (hybridConjunctionDisjunction_[contClauseIdx]) //conjunction
04651                 {
04652                         bClause = true;
04653                         for(int i = 0; i < contDisClause.size(); i++)
04654                         {
04655                                 bool b = (atom_[abs(contDisClause[i])] == (contDisClause[i] > 0));//true literal or not
04656                                 if (!b) //false literal in a conjunction clause
04657                                 {
04658                                         bClause = false;
04659                                         break;
04660                                 }
04661                         }
04662                 }
04663                 else //disjunction
04664                 {
04665                         bClause = false;
04666                         for(int i = 0; i < contDisClause.size(); i++)
04667                         {
04668                                 bool b = (atom_[abs(contDisClause[i])] == (contDisClause[i] > 0));
04669                                 if (b) //true literal in a disjunction clause
04670                                 {
04671                                         bClause = true;
04672                                         break;
04673                                 }
04674                         }
04675                 }
04676 
04677                 return bClause;
04678         }
04679 
04680         PolyNomial& GetHybridClausePolynomial(int contClauseIdx)
04681         {
04682                 return hybridPls_[contClauseIdx];
04683         }
04684 
04685 
04686 
04687         bool isSatisfied(int iContClauseIdx)
04688         {
04689                 return isSatisfied(hybridConstraints_[iContClauseIdx]);
04690         }
04691 
04692         //check constraint satisfied or not
04693         bool isSatisfied(const HybridConstraint& cst, double currentValue) // the value is wt* dis * cont
04694         {
04695                 assert(hybridWts_[cst.contClauseIdx_] != 0);
04696                 if (currentValue >= cst.vThreshold_)
04697                 {
04698                         return true;
04699                 }                       
04700                 else return false;
04701         }
04702 
04703 
04704         bool CheckIfLBFGSCacheSatisfied(int contClauseIdx)
04705         {
04706                 // if still can not find satisfying solutionution till some point, we just quit L-BFGS
04707                 PolyNomial pl = hybridPls_[contClauseIdx];
04708                 pl.SetVarValue(lbfgsCache_[contClauseIdx]);
04709                 double plValue = pl.ComputePlValue();
04710                 bool dis = HybridClauseDisPartValue(contClauseIdx);
04711                 return isSatisfied(hybridConstraints_[contClauseIdx], plValue * double(dis));
04712         }
04713 
04714 
04715         bool isSatisfied(const HybridConstraint& cst)
04716         {
04717                 //PolyNomial& pl = GetHybridClausePolynomial(cst.contClauseIdx);
04718                 double cont;
04719                 bool dis;
04720                 double currentValue = HybridClauseValue(cst.contClauseIdx_,dis, cont);
04721                 return isSatisfied(cst, currentValue);
04722         }
04723 
04724         void LoadDisPartAtoms(const string & str, Array<int>& arDis, map<string, int>& gndPredCont, const int& clauseIdx) 
04725         {// here we assume the same dis variables can not appear more than 1 times in the same clause
04726                 stringstream s(str);
04727                 string strPred;
04728                 while(getline(s, strPred, ';'))
04729                 {
04730                         bool bFalse = false;
04731                         if (strPred[0] == '!')
04732                         {
04733                                 strPred = strPred.substr(1, strPred.length() - 1);
04734                                 bFalse = true;
04735                         }
04736 
04737                         map<string, int>::const_iterator citer;
04738                         citer = gndPredCont.find(strPred);
04739 
04740 
04741                         if (citer == gndPredCont.end())
04742                         {
04743                                 cout << "unseen dis predicate:" <<strPred << endl;
04744                         }
04745 
04746                         assert(citer != gndPredCont.end());
04747 
04748                         if (bFalse)
04749                         {
04750                                 arDis.append(-1*citer->second);
04751                         }                                                                  
04752                         else
04753                         {
04754                                 arDis.append(citer->second);
04755                         }
04756                         hybridDisOccurrence_[citer->second].append(clauseIdx);
04757                 }
04758         }
04759 
04760         void LoadContPartAtoms(const string & str, Array<int>& arDis)
04761         {
04762                 stringstream s(str);
04763                 string strPred;
04764                 while(getline(s, strPred, ';'))
04765                 {
04766                         int contAtomNum = gndPredCont_.size();
04767                         map<string, int>::const_iterator citer;
04768                         if ((citer = gndPredCont_.find(strPred)) != gndPredCont_.end())
04769                         {
04770                                 arDis.append(citer->second);
04771                         }
04772                         else
04773                         {
04774                                 gndPredCont_.insert(map<string,int>::value_type(strPred, contAtomNum+1));
04775                                 gndPredReverseCont_.insert(map<int,string>::value_type(contAtomNum+1, strPred));
04776                                 arDis.append(contAtomNum+1);
04777                         }
04778                 }
04779         }
04780 
04781         void printContAtom(int conAtomIdx, ostream& os)
04782         {
04783                 map<int, string>::const_iterator citer;
04784                 citer = gndPredReverseCont_.find(conAtomIdx);
04785                 os << citer->second << ": " << contAtoms_[citer->first] << "; ";
04786         }
04787 
04788         void printContAtoms(ostream& os)
04789         {
04790                 map<int, string>::const_iterator citer;
04791                 for(citer = gndPredReverseCont_.begin(); citer != gndPredReverseCont_.end(); ++citer)
04792                 {
04793                         os << citer->second << ": " << contAtoms_[citer->first] << "; ";
04794                 }
04795         }
04796 
04797         void PrintDisAtoms(ostream& os)
04798         {
04799                 for(int i = 0; i < getNumAtoms(); i++)
04800                 {
04801                         (*gndPreds_)[i]->print(os, domain_);
04802                         os << ": " << atom_[i+1] <<"; ";
04803                 }                                                                  
04804         }
04805 
04806         void PrintContPartMLN(ostream& os)
04807         {
04808                 for(int i = 0;i < hybridClauseNum_; i++)
04809                 {
04810                         os << hybridConjunctionDisjunction_[i] << '|' << hybridWts_[i] << '|';
04811                         for(int j = 0; j < hybridDisClause_[i].size(); j++)
04812                         {
04813                                 (*gndPreds_)[abs(hybridDisClause_[i][j])-1]->print(os, domain_);
04814                                 os << ';';
04815                         }
04816                         os << '|';
04817                         for(int j = 0; j < hybridContClause_[i].size(); j++)
04818                         {
04819                                 os << gndPredReverseCont_[hybridContClause_[i][j]] <<';';                               
04820                         }
04821                         os << '|';
04822                         hybridPls_[i].PrintTo(os);
04823                         os << endl;
04824                 }
04825         }
04826 
04827         void printContOccurrence(ostream& os)
04828         {
04829                 os << "Dis occur, atoms: " << hybridDisOccurrence_.size() - 1 << endl;
04830                 for(int i = 1; i < hybridDisOccurrence_.size(); i++)
04831                 {       
04832                         os << "atom " << i << " occurs at " << hybridDisOccurrence_[i].size() << " different cont clauses; ";
04833                         for(int j = 0; j < hybridDisOccurrence_[i].size(); j++)
04834                         {
04835                                 os << hybridDisOccurrence_[i][j] << " ";
04836                         }
04837                         os << endl;
04838                 }
04839 
04840                 os << "Cont occur, atoms: " << hybridContOccurrence_.size() - 1 << endl;
04841                 for(int i = 1; i < hybridContOccurrence_.size(); i++)
04842                 {       
04843                         os << "atom " << i << " occurs at " << hybridContOccurrence_[i].size() << " different cont clauses; ";
04844                         for(int j = 0; j < hybridContOccurrence_[i].size(); j++)
04845                         {
04846                                 os << hybridContOccurrence_[i][j] << " ";
04847                         }
04848                         os << endl;
04849                 }
04850         }
04851 
04852         void buildContOccurrence()
04853         {
04854                 for(int i = 0; i < hybridContClause_.size(); i++)
04855                 {
04856                         for(int j = 0; j < hybridContClause_[i].size(); j++)
04857                         {
04858                                 hybridContOccurrence_[hybridContClause_[i][j]].append(i);
04859                         }
04860                 }
04861         }
04862 
04863         void setDisVarValueFromEvi()
04864         {
04865                 for(int i = 0; i < getNumAtoms(); i++)
04866                 {
04867                         atom_[i+1] = atomEvi_[i+1];
04868                 }
04869         }
04870         void setContVarValueFromEvi()
04871         {
04872                 for(int i = 0; i < contAtomNum_; i++)
04873                 {
04874                         contAtoms_[i+1] = contAtomsEvi_[i+1];
04875 
04876                 }
04877         }
04878 
04879         void LoadDisEviValuesFromRst(const char* szDisEvi)
04880         {
04881                 for(int i = 1; i < atomEvi_.size(); i++)
04882                 {
04883                         atomEvi_[i] = false;
04884                 }
04885                 map<string, int> gndPredCont;
04886                 for(int i = 0; i < gndPreds_->size(); i++)
04887                 {
04888                         string str = (*gndPreds_)[i]->getPredicateStr(domain_);
04889                         gndPredCont.insert(map<string, int>::value_type(str, i+1));
04890                 }
04891                 ifstream is(szDisEvi);
04892                 string strLine;
04893                 while (getline(is, strLine))
04894                 {
04895                         stringstream ss(strLine);
04896                         string strtmp;
04897                         getline(ss,strtmp, ' ');
04898                         //strLine = "Hastype(Wall,L0_1)";
04899 
04900                         map<string, int>::const_iterator citer;
04901                         citer = gndPredCont.find(strtmp);
04902                         if (citer == gndPredCont.end())
04903                         {
04904                                 cout << "dis evi file error, non-existent query gndings" << endl;
04905                                 cout  << strLine << endl;
04906                                 exit(1);
04907                         }
04908                         int atomIdx = citer->second;
04909                         //atomEvi_[atomIdx] = true;
04910 
04911                         getline(ss, strtmp);
04912                         int b = atoi(strtmp.c_str());
04913                         if (b==1)
04914                         {
04915                                 atomEvi_[atomIdx] = true;
04916                         }
04917                         else
04918                         {
04919                                 atomEvi_[atomIdx] = false;
04920                         }
04921                 }
04922         }
04923         void LoadDisEviValues(const char* szDisEvi)      //close world assumption, file format compatible to the dis evi file
04924         {
04925                 for(int i = 1; i < atomEvi_.size(); i++)
04926                 {
04927                         atomEvi_[i] = false;
04928                 }
04929                 map<string, int> gndPredCont;
04930                 for(int i = 0; i < gndPreds_->size(); i++)
04931                 {
04932                         string str = (*gndPreds_)[i]->getPredicateStr(domain_);
04933                         gndPredCont.insert(map<string, int>::value_type(str, i+1));
04934                 }
04935                 ifstream is(szDisEvi);
04936                 string strLine;
04937                 while (getline(is, strLine))
04938                 {
04939                         /*stringstream ss(strLine);
04940                         string strtmp;
04941                         getline(ss,strtmp, ' ');*/
04942                         //strLine = "Hastype(Wall,L0_1)";
04943 
04944                         map<string, int>::const_iterator citer;
04945                         citer = gndPredCont.find(strLine);
04946                         if (citer == gndPredCont.end())
04947                         {
04948                                 cout << "dis evi file error, non-existent query gndings" << endl;
04949                                 cout  << strLine << endl;
04950                                 exit(1);
04951                         }
04952                         int atomIdx = citer->second;
04953                         atomEvi_[atomIdx] = true;
04954 
04955                         /*getline(ss, strtmp);
04956                         int b = atoi(strtmp.c_str());
04957                         if (b==1)
04958                         {
04959                         atom_[atomIdx] = true;
04960                         }
04961                         else
04962                         {
04963                         atom_[atomIdx] = false;
04964                         }*/
04965                 }
04966         }
04967 
04968 
04969         void LoadContEviValues(const char* szContEvi)// called after the LoadContGroundedMLN is called
04970         {
04971                 map<string, int>::const_iterator citer;
04972                 string strLine;
04973                 ifstream is(szContEvi);
04974                 while (getline(is, strLine))
04975                 {
04976                         stringstream ss(strLine);
04977                         string strTmp;
04978                         getline(ss, strTmp, ' ');
04979                         citer = gndPredCont_.find(strTmp);
04980                         if (citer == gndPredCont_.end())
04981                         {
04982                                 cout << "cont evi file error, non-existent query gndings" << endl;
04983                                 exit(1);
04984                         }
04985                         getline(ss, strTmp);
04986                         contAtomsEvi_[citer->second] = atof(strTmp.c_str());
04987                 }
04988         }
04989 
04990         void LoadContGroundedMLN(const char* szContFile) //load & parse the grounded hybrid part of the HMLN
04991         {
04992                 ifstream is(szContFile);
04993                 if(!is.good())
04994                 {
04995                         cout << "cont file error" << endl;
04996                         exit(0);
04997                 }
04998                 string strLine;
04999                 //map<string, int> gndPredCont;
05000                 for(int i = 0; i < gndPreds_->size(); i++)
05001                 {
05002                         string str = (*gndPreds_)[i]->getPredicateStr(domain_);
05003                         gndPredDis_.insert(map<string, int>::value_type(str, i+1));
05004                 }
05005 
05006                 hybridDisOccurrence_.growToSize(getNumAtoms() + 1);
05007                 while (getline(is, strLine))
05008                 {
05009                         stringstream ss(strLine);
05010                         string str;
05011                         getline(ss, str, '|');
05012                         hybridGndClauseToFormulaMap_.append(atoi(str.c_str()));
05013                         getline(ss, str, '|');
05014                         if (str == "1") // And string
05015                         {
05016                                 hybridConjunctionDisjunction_.append(true);
05017                         }
05018                         else hybridConjunctionDisjunction_.append(false);
05019 
05020                         getline(ss, str, '|');//weight
05021                         hybridWts_.append(atof(str.c_str()));
05022                         hybridClauseCost_.append(atof(str.c_str()));
05023 
05024                         Array<int> arDis; //for the dis part of current clause
05025                         getline(ss, str, '|');                                     
05026                         LoadDisPartAtoms(str, arDis, gndPredDis_, hybridClauseNum_);
05027                         hybridDisClause_.append(arDis);
05028                         arDis.clear();
05029                         getline(ss, str, '|');
05030                         LoadContPartAtoms(str, arDis);
05031                         hybridContClause_.append(arDis);
05032 
05033                         getline(ss, str, '|');
05034                         PolyNomial pl;
05035                         istringstream iss(str);
05036                         pl.ReadFrom(iss);
05037                         hybridPls_.append(pl);
05038 
05039                         //init the threshold of constraint to 0
05040                         HybridConstraint cst;
05041                         cst.contClauseIdx_ = hybridClauseNum_;
05042                         // Setting the threshold value of the constraint would ensure 
05043                         // that its status is set to Satisfied at the intial stage of HMCSAT.
05044                         cst.vThreshold_ = -BigValue;
05045                         cst.bSatisfiedLast_ = true;
05046                         cst.unSatType_ = UNKNOWN;
05047                         hybridConstraints_.append(cst);
05048                         hybridClauseNum_++;
05049                 }
05050                 
05051                 contAtomNum_ = gndPredCont_.size();
05052                 contAtomRange_.growToSize(contAtomNum_);
05053                 proposalStdev_.growToSize(contAtomNum_+1,0);
05054                 contAtoms_.growToSize(contAtomNum_ + 1, 0); //the idx for atoms start from 1
05055                 contAtomsLast_.growToSize(contAtomNum_ + 1, 0); //the idx for atoms start from 1
05056                 contAtomsEvi_.growToSize(contAtomNum_ + 1, NOVALUE);
05057                 hybridContOccurrence_.growToSize(contAtomNum_ + 1);
05058                 // build contContOccurrence here
05059                 buildContOccurrence();
05060                 set<int> contFormulaSet;
05061                 for(int i = 0; i < hybridGndClauseToFormulaMap_.size(); i++)
05062                 {
05063                         contFormulaSet.insert(hybridGndClauseToFormulaMap_[i]);
05064                 }
05065 
05066                 hybridFormulaNum_ = contFormulaSet.size();
05067                 hybridFormulaGndClauseIdx_.growToSize(hybridFormulaNum_);
05068 
05069                 for(int i = 0; i < hybridGndClauseToFormulaMap_.size(); i++)
05070                 {
05071                         hybridFormulaGndClauseIdx_[hybridGndClauseToFormulaMap_[i]].append(i);
05072                 }
05073 
05074                 //hybridClauseCost_.growToSize(hybridClauseNum_);
05075                 hybridFalseClause_.growToSize(hybridClauseNum_);
05076                 hybridWhereFalse_.growToSize(hybridClauseNum_);
05077                 lbfgsCache_.growToSize(hybridClauseNum_);
05078                 hmwsContOptimal_.growToSize(hybridClauseNum_);
05079                 hmwsDisOptimal_.growToSize(hybridClauseNum_);
05080                 contAtomsLow_.growToSize(contAtomNum_ + 1, 0);
05081                 hybridClauseValue_.growToSize(hybridClauseNum_, 0);             
05082                 hybridClauseDisValue_.growToSize(hybridClauseNum_, false);
05083                 totalAtomNum_ = contAtomNum_ + getNumAtoms();
05084                 numFalseClauses_ = 0;
05085                 initRange(); 
05086 
05087                 if (hvsdebug)
05088                 {
05089                         cout << "cont atom number: " << contAtomNum_ << endl;
05090                         printContOccurrence(cout);
05091                 }
05092         }
05093 
05094         int getNumContFormulas()
05095         {
05096                 return hybridFormulaNum_;
05097         }
05098 
05099 
05100         // initialize DoubleRange bounds array for continuous variables, the actual bounds will be loaded in setPropStdev
05101         void initRange() 
05102         {
05103                 if(contAtomRange_.size() < contAtomNum_)
05104                 {
05105                         contAtomRange_.growToSize(contAtomNum_);
05106                 }
05107                 else if (contAtomRange_.size() > contAtomNum_)
05108                 {
05109                         contAtomRange_.shrinkToSize(contAtomNum_);
05110                 }
05111                 for(int i = 0; i < contAtomRange_.size(); i++)
05112                 {
05113                         contAtomRange_[i].low = 0;
05114                         contAtomRange_[i].high = 2;
05115                         contAtomRange_[i].iType = 0;
05116                 }                                                       
05117         }
05118 
05119         double randomSampleRange(const DoubleRange& r)
05120         {
05121 
05122                 if (r.iType == 0)
05123                 {
05124                         return double(random())*(r.high-r.low)/double(RAND_MAX) + r.low;
05125                 }
05126                 else if (r.iType == 1)
05127                 {
05128                         //cout << "never supposed to be 1" << endl;
05129                         double leftR,rightR;
05130                         if (r.low < -ABSBIG && r.high < ABSBIG)
05131                         {
05132                                 //discard it
05133                                 DoubleRange rt;
05134                                 rt.iType = 0;
05135                                 rt.high = ABSBIG;
05136                                 rt.low = max(r.high, -ABSBIG);
05137                                 //leftR = 0;
05138                                 return randomSampleRange(rt);
05139 
05140                         }
05141                         else if (r.low < -ABSBIG && r.high > ABSBIG)
05142                         {
05143                                 return 0;
05144                         }
05145                         else if (r.low > -ABSBIG && r.high > ABSBIG)
05146                         {
05147                                 DoubleRange rt;
05148                                 rt.iType = 0;
05149                                 rt.low = -ABSBIG;
05150                                 rt.high = MIN(r.low, ABSBIG);
05151                                 //leftR = 0;
05152                                 return randomSampleRange(rt);
05153 
05154                         }
05155                         else if (r.low > -ABSBIG && r.high < ABSBIG)
05156                         {
05157                                 leftR = r.low + ABSBIG;
05158                                 rightR = ABSBIG - r.high;
05159                                 double rs = double(random())/ double(RAND_MAX);
05160 
05161                                 if (rs  < leftR /(leftR + rightR))
05162                                 {
05163                                         return -ABSBIG + (leftR + rightR)*rs;
05164                                 }
05165                                 else
05166                                 {
05167                                         rs = rs - leftR /(leftR + rightR);
05168                                         return r.high + rs* (leftR + rightR);
05169                                 }
05170                         }
05171                 }
05172                 return 0;//should never be here
05173         }
05174 
05175         // By Dynamic Programming.
05176         double computeMaxValue(PolyNomial& pl,int contClauseIdx, int i)
05177         {
05178                 if (contClauseIdx >= hybridClauseNum_)
05179                 {
05180                         cout << "Cont clause Exceed, " << contClauseIdx << ", " << i << endl;
05181                 }
05182 
05183                 if(i >= hybridContClause_[contClauseIdx].size())
05184                         cout << "Cont Atom Exceed, " << contClauseIdx << ", " << i << endl;
05185 
05186 
05187                 int atomIdx = hybridContClause_[contClauseIdx][i];
05188                 double m1, m2;
05189 
05190                 if (i < pl.GetVarNum() -1 )
05191                 {
05192                         (pl.GetVarValue())[i] = contAtomRange_[atomIdx].low; 
05193                         m1 = computeMaxValue(pl, contClauseIdx, i+1);
05194 
05195                         (pl.GetVarValue())[i] = contAtomRange_[atomIdx].high;
05196                         m2 = computeMaxValue(pl, contClauseIdx,i+1);
05197                 }
05198 
05199 
05200                 if (i == pl.GetVarNum() - 1)
05201                 {
05202                         (pl.GetVarValue())[i] = contAtomRange_[atomIdx].low; 
05203                         m1 = pl.ComputePlValue();
05204 
05205                         (pl.GetVarValue())[i] = contAtomRange_[atomIdx].high;
05206                         m2 = pl.ComputePlValue();
05207                 }
05208 
05209                 if (m1 > m2)
05210                 {
05211                         return m1;
05212                 }
05213                 else
05214                         return m2;
05215         }
05216 
05217         void setProposalStdev(const char* szStdev)
05218         {
05219                 ifstream is(szStdev);
05220                 if (!is.good())
05221                 {
05222                         cout << "proposal stdev file error." << endl;
05223                         exit(0);
05224                 }
05225                 string strLine;
05226                 int i = 0;
05227                 while (getline(is, strLine) && i < getNumContAtoms())
05228                 {
05229                         stringstream ss(strLine);                       
05230                         ss >> contAtomRange_[i].low >> contAtomRange_[i].high >> proposalStdev_[i+1];
05231                         //cout << contAtomRange_[i].low <<" " << contAtomRange_[i].high <<" " << proposalStdev_[i+1] << endl; 
05232                         i++;                                    
05233                 }
05234 
05235                 if ( i != contAtomNum_)
05236                 {
05237                         cout << "propos stdev file not match!" << endl;
05238                         cout << i << "\t" << contAtomNum_ << endl;
05239                         for (int j = 0; j < contAtomNum_; j++)
05240                         {
05241                                 printContAtom(j + 1,cout);cout << endl;
05242                         }                       
05243                 }
05244 
05245                 // intialize L-BFGS solutionvers here
05246                 for(int j = 0;j < hybridClauseNum_; j++)
05247                 {
05248                         int varNum = hybridPls_[j].GetVarNum();
05249                         LBFGSP* lbfgsp = new LBFGSP(-1,-1,varNum);
05250                         double* upper = new double[varNum];
05251                         double* lower = new double[varNum];
05252                         for(int k = 0; k < hybridContClause_[j].size(); k++)
05253                         {
05254                                 upper[k] = contAtomRange_[hybridContClause_[j][k]-1].high;
05255                                 lower[k] = contAtomRange_[hybridContClause_[j][k]-1].low;
05256                         }
05257                         lbfgsp->setUpperBounds(upper);
05258                         lbfgsp->setLowerBounds(lower);
05259                         PolyNomial pl = hybridPls_[j];
05260 
05261                         if (hybridClauseCost_[j] >  0)
05262                         {
05263                                 pl.MultiplyConst(-1.0);
05264                         }
05265 
05266                         lbfgsp->startLBFGS(pl);
05267                         lbfgsCache_[j].copyFrom(pl.GetVarValue());
05268                         contsolvers_.append(lbfgsp);
05269                         delete[] upper;
05270                         delete[] lower;
05271                 }
05272         }
05273         
05274         void proceedOneStepAndCache(int contClauseIdx, PolyNomial& pl)
05275         {
05276                 if(wjhvsdbg)
05277                 {
05278                         cout << "begin proceedOneStepAndCache" << endl;
05279                 }
05280 
05281                 LBFGSP* lbfgsp = contsolvers_[contClauseIdx];
05282                 pl.SetVarValue(lbfgsCache_[contClauseIdx]);
05283                 lbfgsp->proceedOneStep(pl);
05284                 //cache
05285                 lbfgsCache_[contClauseIdx].copyFrom(pl.GetVarValue());          
05286 
05287                 if(wjhvsdbg)
05288                 {
05289                         cout << "end proceedOneStepAndCache" << endl;
05290                 }
05291         }
05292 
05293         bool SolveContByLBFGS(int contClauseIdx, int maxIter)
05294         {
05295                 // resume l-bfgs from the cached assignment
05296                 // until entering the satisfying region
05297                 PolyNomial pl = hybridPls_[contClauseIdx];
05298                 pl.MultiplyConst(-1.0);
05299                 bool bSat = false;
05300                 for(int i = 0; i < maxIter; i++)
05301                 {
05302                         proceedOneStepAndCache(contClauseIdx, pl);
05303                         double plValue = pl.ComputePlValue();
05304                         cout << "step " << i  << ", polynomial value " << plValue << endl;
05305                         if(isSatisfied(hybridConstraints_[contClauseIdx], -1*plValue))
05306                         {
05307                                 bSat = true;
05308                                 break;
05309                         }
05310                 }       
05311                 return bSat;
05312         }       
05313         
05314         void initContinuousVariableRandom()
05315         {
05316                 if(hvsdebug)
05317                 {
05318                         cout << "entering init continuous random" << endl;
05319                 }
05320 
05321                 assert(contAtomNum_ == contAtomRange_.size());
05322 
05323                 for (int i = 0; i < contAtomNum_; i++)
05324                 {
05325                         contAtoms_[i+1] = contAtomRange_[i].low + (contAtomRange_[i].high - contAtomRange_[i].low)*double(random()) / double(RAND_MAX);
05326                 }
05327 
05328                 if(hvsdebug)
05329                 {
05330                         cout << "leaving init continuous random" << endl;
05331                 }        
05332         }
05333 
05334         
05335 private:
05336         /*
05337         Hybrid MLN functions.
05338         */
05339 
05341         // Hybrid MCSAT functions.
05343 
05344         // Solve the hybrid constraint according to the degenerated form of its continuous part, in regarding to one of its continuous variables.
05345         DoubleRange SolveHybridConstraintToContVar(const int& contClauseIdx, const int& inIdx) 
05346         {
05347                 //w*f(n) > th = log(u), u ~ U(0,exp(w*f(n-1))), pl is f(n)
05348                 PolyNomial pl = hybridPls_[contClauseIdx]; // Make a copy of the pl.            
05349                 pl.MultiplyConst(hybridWts_[contClauseIdx]);
05350                 double d = hybridConstraints_[contClauseIdx].vThreshold_;               
05351                 // pl reduce to 1 variable pl by fixing all the other variables except contAtomIdx.
05352                 Array<double> currentVars;
05353                 int i;
05354                 for( i = 0; i < hybridContClause_[contClauseIdx].size(); ++i)
05355                 {
05356                         currentVars.append(contAtoms_[hybridContClause_[contClauseIdx][i]]);
05357                 }
05358                 //find the offset of 
05359                 assert(inIdx >= 0 && inIdx < hybridContClause_[contClauseIdx].size());
05360                 pl.ReduceToOneVar(currentVars, inIdx);
05361                 DoubleRange r = pl.SolvePoly2(d);               
05362                 return r;
05363         }
05364 
05366         // Hybrid MaxWalkSAT functions.
05368 
05374         void setHardClauseWeight()
05375         {
05376                 // Soft weights are summed up to determine hard weight
05377                 long double sumSoftWts = 0.0;
05378                 // Determine hard clause weight
05379                 int clauseCnt = mln_->getNumClauses();    
05380                 // Sum up the soft weights of all grounded clauses
05381                 for (int i = 0; i < clauseCnt; i++)
05382                 {
05383                         Clause* fclause = (Clause *) mln_->getClause(i);
05384                         // Skip hard clauses
05385                         if (fclause->isHardClause()) continue;
05386                         // Weight could be negative
05387                         long double wt = abs(fclause->getWt());
05388                         long double numGndings = fclause->getNumGroundings(domain_);
05389                         sumSoftWts += wt*numGndings;
05390                 }
05391 
05392                 assert(sumSoftWts >= 0);
05393                 // Add constant so weight isn't zero if no soft clauses present
05394                 hardWt_ = sumSoftWts + 10.0;
05395                 //cout << "Set hard weight to " << hardWt_ << endl;
05396         }
05397 
05398                                            
05399 public:
05400         // Variables defined in the original VariableState.
05401 
05402    // Inference mode: decide how getActiveClauses and addNewClauses
05403    // filter and set cost
05404   const static int MODE_MWS = 0;
05405   const static int MODE_HARD = 1;
05406   const static int MODE_SAMPLESAT = 2;
05407 
05408   const static int ADD_CLAUSE_INITIAL = 0;
05409   const static int ADD_CLAUSE_REGULAR = 1;
05410   const static int ADD_CLAUSE_DEAD = 2;
05411   const static int ADD_CLAUSE_SAT = 3;    // the clauses are sat by fixed atoms
05412 
05413 
05414         // Eager version: Pointer to gndPreds_ and gndClauses_ in MRF
05415         // Lazy version: Holds active atoms and clauses
05416         Array<GroundPredicate*>* gndPreds_;
05417         Array<GroundClause*>* gndClauses_;
05418         // Predicates corresponding to the groundings of the unknown non-evidence
05419         // predicates
05420         GroundPredicateHashArray* unePreds_;
05421         // Predicates corresponding to the groundings of the known non-evidence
05422         // predicates
05423         GroundPredicateHashArray* knePreds_;
05424         // Actual truth values of ground known non-evidence preds
05425         Array<TruthValue>* knePredValues_;  
05426         // Holds the new active clauses
05427         Array<GroundClause*> newClauses_;
05428         // Holds the new gnd preds
05429         Array<GroundPredicate*> newPreds_;
05430         // Holds the ground predicates in a hash array.
05431         // Fast access is needed for comparing preds when activating clauses.
05432         GroundPredicateHashArray gndPredHashArray_;
05433         // Clauses to be satisfied
05434         // Indexed as clause_[clause_num][literal_num]
05435         Array<Array<int> > clause_;
05436         // Cost of each clause (can be negative)
05437         Array<long double> clauseCost_;
05438         // Clauses which are pos. and unsatisfied or neg. and satisfied
05439         Array<int> falseClause_;
05440         Array<int> falseClauseLow_;
05441         // Where each clause is listed in falseClause_
05442         Array<int> whereFalse_;
05443         // Number of true literals in each clause
05444         Array<int> numTrueLits_;
05445         // watch1_[c] contains the id of the first atom which c is watching
05446         Array<int> watch1_;
05447         // watch2_[c] contains the id of the second atom which c is watching
05448         Array<int> watch2_;
05449         // Which clauses are satisfied by fixed atoms
05450         Array<bool> isSatisfied_;
05451         // Clauses which are not to be considered
05452         Array<bool> deadClause_;
05453         // Use threshold to exclude clauses from the state?
05454         bool useThreshold_;
05455         // Pre-computed thresholds for each clause
05456         Array<long double> threshold_;
05457 
05458         // Holds the index of clauses in which each literal occurs
05459         // Indexed as occurence_[2*abs(lit) - (lit > 0)][occurence_num]
05460         Array<Array<int> > occurence_;
05461 
05462         // Cost of clauses which would become satisfied by flipping each atom
05463         Array<long double> makeCost_;
05464         // Cost of clauses which would become unsatisfied by flipping each atom
05465         Array<long double> breakCost_;
05466         // Indicates if an atom is fixed to a value (0 = not fixed, -1 = false,
05467         // 1 = true)
05468         Array<int> fixedAtom_;
05469         // Assigment of atoms producing lowest cost so far
05470         Array<bool> lowAtom_;
05471         // Cost of false clauses in the currently best state
05472         long double lowCost_;
05473 
05474         // Current assigment of atoms
05475         Array<bool> atom_;
05476 
05478         // Variables added for hybrid states.
05480 
05481         bool bInitFromEvi_; // whether initialize from evidence
05482         // public properties
05483         // new groundings
05484         Array<bool> atomEvi_;
05485         Array<bool> atomsLast_;
05486 
05487         //continuous constraints
05488         Array<LBFGSP*> contsolvers_;
05489         Array<HybridConstraint> hybridConstraints_;      // Hybrid constraints used in hybrid MC-SAT
05490         Array<PolyNomial> hybridPls_; // one polynomial per clause
05491         Array<double> hybridWts_;
05492         map<int, double> contOptimum_; // cont optimum values
05493         map<int, Array<double> > contOptimumAssignment_;
05494 
05495         Array<double> contAtomsLast_;
05496         Array<double> contAtoms_; //cont atom values
05497         Array<double> contAtomsBackup_;
05498         Array<double> contAtomsEvi_;
05499         Array<double> contAtomsLow_;
05500 
05501         double lowCostHybrid_;
05502         int lowBadHybrid_;
05503 
05504         Array<Array<int> > hybridDisClause_;     //index of discrete part of continuous clauses
05505         Array<Array<int> > hybridContClause_;
05506         Array<Array<int> > hybridDisOccurrence_;//occurrence of discrete part of continuous clauses, no pos or neg occur here
05507         Array<Array<int> > hybridContOccurrence_;        //no pos or neg occur here
05508         Array<DoubleRange> contAtomRange_; // Value range of continuous variables.
05509         Array<bool> hybridConjunctionDisjunction_; //the discrete part of hybrid clauses are 1 conjunction or 0 disjunction     
05510         Array<double> hybridClauseCost_;  // The cost of hybrid clauses are initialized as their weights
05511         Array<int> hybridGndClauseToFormulaMap_;
05512         Array<Array<int> > hybridFormulaGndClauseIdx_;
05513 
05514         int hybridFormulaNum_;
05515         int hybridClauseNum_;
05516         int contAtomNum_;
05517         int totalAtomNum_;
05518         int totalFalseConstraintNum_;
05519         int hybridFalseConstraintNum_;
05520 
05521         Array<int> hybridFalseClause_; // Storing the clause indices of false hybrid formulas.
05522         Array<int> hybridFalseClauseLow_;
05523         // Where each clause is listed in falseClause_
05524         Array<int> hybridWhereFalse_;
05525         
05526         Array<double> hybridClauseValue_;
05527         Array<bool> hybridClauseDisValue_;
05528 
05529         map<string ,int> gndPredCont_;
05530         map<int, string> gndPredReverseCont_;
05531         
05532         double costOfTotalFalseConstraints_;
05533         int lowBadAll_;
05534         double lowCostAll_;
05535         double costHybridFalseConstraint_;
05536         bool bMaxOnly_;
05537 
05538         Array<double> proposalStdev_;
05539         map<string,int> gndPredDis_;
05540 
05541         double weightSumDis_;
05542         double weightSumCont_;
05543 
05544         Array<Array<double> > lbfgsCache_;
05545         Array<double> hmwsContOptimal_;
05546         Array<bool> hmwsDisOptimal_;
05547         
05548         string strHybridDis_;
05549 
05550 private:
05551         // If true, this is a lazy variable state, else eager.
05552         bool lazy_;
05553 
05554         // Weight used for hard clauses (sum of soft weights + constant)
05555         long double hardWt_;
05556 
05557         // mln and domain are used to build MRF in eager state and to
05558         // retrieve active atoms in lazy state.
05559         MLN* mln_;
05560         Domain* domain_;
05561         
05563         // Number of distinct atoms in the first set of unsatisfied clauses
05564         int baseNumAtoms_;
05565         // If true, atoms are not deactivated when mem. is full
05566         bool noApprox_;
05567         // Indicates whether deactivation of atoms has taken place yet
05568         bool haveDeactivated_;
05569         // Max. amount of memory to use
05570         int memLimit_;
05571         // Max. amount of clauses memory can hold
05572         int clauseLimit_;
05574 
05576         // MRF is used with eager states. If lazy, this stays NULL.
05577         MRF* mrf_;
05579 
05580         // Highest cost of false clause
05581         // long double highestCost_;
05582         // If true, more than one clause has highest cost
05583         // bool eqHighest_;
05584         // Number of clauses with highest cost
05585         // int numHighest_;
05586 
05587         // Number of false clauses in the currently best state
05588         int lowBad_;
05589 
05590         // Current no. of unsatisfied clauses
05591         int numFalseClauses_;
05592         // Cost associated with the number of false clauses
05593         long double costOfFalseClauses_;        
05594 
05595         // For block inference: blocks_ and blockEvidence_
05596         // All atom indices in (*blocks_)[i] are to be treated as in one block
05597         Array<Array<int> >* blocks_;
05598         // (*blockEvidence_)[i] states whether block i has true evidence and
05599         // thus all should be false
05600         Array<bool >* blockEvidence_;
05601 
05602           // Number of active atoms in state.  
05603         int activeAtoms_;
05604     
05605       // Number of non-evidence atoms in the domain
05606     int numNonEvAtoms_;
05607 
05608     // Inference mode: decide how getActiveClauses and addNewClauses
05609     // filter and set cost
05610   int inferenceMode_;
05611   
05612       // Indicates if atoms are still being activated. If main memory is full,
05613       // then activating atoms is disabled and inference is run in the partial
05614       // network
05615     bool stillActivating_;
05616       
05617 };
05618 
05619 #endif /*VARIABLESTATE_H_*/

Generated on Sun Jun 7 11:55:16 2009 for Alchemy by  doxygen 1.5.1