00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 #ifndef LISTOBJ_H_JUN_21_2005
00067 #define LISTOBJ_H_JUN_21_2005
00068
00069 #include <string>
00070 #include <list>
00071 #include <ostream>
00072 #include <ext/hash_map>
00073 using namespace __gnu_cxx;
00074 #include "array.h"
00075 #include "hashstring.h"
00076 #include "domain.h"
00077 #include "arraysaccessor.h"
00078
00079 typedef hash_map<const string, int, HashString, EqualString> VarTypeMap;
00080
00081
00082
00083
00084
00085
00086
00087
00088 class ListObj
00089 {
00090 public:
00091 ListObj()
00092 {
00093 str_ = new char[1];
00094 str_[0] = '\0';
00095 }
00096
00097
00098 ListObj(const char* const & str)
00099 {
00100 if (str != NULL)
00101 {
00102 str_ = new char[strlen(str)+1];
00103 strcpy(str_, str);
00104 }
00105 else
00106 {
00107 str_ = new char[1];
00108 str_[0] = '\0';
00109 }
00110 }
00111
00112
00113 ListObj(const ListObj* const & p)
00114 {
00115 for (int i = 0; i < p->size(); i++)
00116 list_.append(new ListObj((*p)[i]));
00117 str_ = new char[strlen(p->str_)+1];
00118 strcpy(str_, p->str_);
00119
00120 assert(p->list_.size() == list_.size());
00121
00122 }
00123
00124
00125 ~ListObj() { delete [] str_; list_.deleteItemsAndClear(); }
00126
00127
00128 void clear() { list_.clear(); delete [] str_; str_=new char[1];str_[0]='\0'; }
00129
00130 void deleteAndClear() { list_.deleteItemsAndClear(); clear(); }
00131
00132 void clearList() { list_.clear(); }
00133
00134 ostream& print(ostream& out) const
00135 {
00136 if (isStr())
00137 out << str_;
00138 else
00139 {
00140 out << "(";
00141 for (int i = 0; i < list_.size(); i++)
00142 {
00143 list_[i]->print(out);
00144 out << ((i<list_.size()-1)? " " : "");
00145 }
00146 out << ")";
00147 }
00148 return out;
00149 }
00150
00151
00152
00153 const Array<ListObj*>& getList() const { return list_; }
00154
00155
00156 const char* getStr() const { return str_; }
00157
00158
00159
00160 void setStrIfStr(const char* str)
00161 {
00162 if (isStr())
00163 {
00164 delete [] str_;
00165 str_ = new char[strlen(str)+1];
00166 strcpy(str_,str);
00167 }
00168 }
00169
00170 bool isStr() const { return (strlen(str_) > 0); }
00171
00172 bool isList() const { return !isStr(); }
00173
00174 void append(ListObj* const & p) { list_.append(p); }
00175
00176 void append(const char* const & s) { list_.append(new ListObj(s)); }
00177
00178 ListObj* removeLast()
00179 {
00180 ListObj* lo = list_.removeLastItem();
00181 list_.compress();
00182 return lo;
00183 }
00184
00185 int size() const { return list_.size(); }
00186
00187 ListObj* operator[](const int& index) const { return list_[index]; }
00188
00189
00190 static ListObj* toCNF(const ListObj* const & p, const ListObj* const & vars,
00191 const Domain* const & domain,
00192 const VarTypeMap * const& vtMap, bool& hasExist)
00193 {
00194 ListObj* p1 = eliminateImplication(p);
00195
00196 const char* opp = op(p1)->str_;
00197
00198 if (strcmp(opp, "!")==0)
00199 {
00200 ListObj* p2 = moveNotInwards(arg1(p1));
00201 if (isLiteralClause(p2)) { delete p1; return p2; }
00202
00203 ListObj* ret = toCNF(p2, vars, domain, vtMap, hasExist);
00204 delete p2; delete p1;
00205 return ret;
00206 }
00207
00208 if (strcmp(opp, "^")==0)
00209 {
00210 ListObj* n = NULL;
00211 int numConj = 0;
00212 ListObj* firstConj = NULL;
00213
00214 for (int i = 1; i < p1->size(); i++)
00215 {
00216 ListObj* conj = toCNF((*p1)[i], vars, domain, vtMap, hasExist);
00217
00218 bool isConj = strcmp(op(conj)->str_, "^")==0;
00219 int jbeg = (isConj) ? 1 : 0;
00220 int jmax = (isConj) ? conj->size() : 1;
00221 ListObj* conjj;
00222
00223 for (int j = jbeg; j < jmax; j++)
00224 {
00225 if (isConj) conjj = (*conj)[j];
00226 else conjj = conj;
00227
00228 numConj++;
00229 if (numConj==1) { firstConj = conjj; continue; }
00230 else
00231 if (numConj==2) {n=new ListObj; n->append("^"); n->append(firstConj);}
00232 n->append(conjj);
00233 }
00234
00235 if (isConj) { delete (*conj)[0]; conj->clearList(); delete conj; }
00236
00237 }
00238
00239 delete p1;
00240 if (numConj == 1) { return firstConj; }
00241 return n;
00242 }
00243
00244 if (strcmp(opp, "v")==0)
00245 {
00246 ListObj* n = new ListObj;
00247 for (int i = 1; i < p1->size(); i++)
00248 n->append(toCNF((*p1)[i], vars, domain, vtMap, hasExist));
00249 ListObj* ret = mergeDisjuncts(n, n->size());
00250
00251 delete n; delete p1;
00252 return ret;
00253 }
00254
00255 if (strcmp(opp, "FORALL")==0)
00256 {
00257 const ListObj* arg1var = arg1(p1);
00258
00259 ListObj* newVar = new ListObj;
00260 for (int i = 0; i < arg1var->size(); i++)
00261 newVar->append(newVariable((*arg1var)[i]));
00262 assert(newVar->size() == arg1var->size());
00263
00264 const ListObj* aarg2 = new ListObj(arg2(p1));
00265
00266 for (int i = 0; i < newVar->size(); i++)
00267 for (int j = 0; j < aarg2->size(); j++)
00268 (*aarg2)[j]->sub((*arg1var)[i], (*newVar)[i]);
00269
00270 ListObj* app = new ListObj;
00271 for (int i = 0; i < newVar->size(); i++) app->append((*newVar)[i]);
00272 for (int i = 0; i < vars->size(); i++) app->append((*vars)[i]);
00273
00274 newVar->clearList();
00275 delete newVar;
00276 ListObj* ret = toCNF(aarg2, app, domain, vtMap, hasExist);
00277 delete aarg2; delete app; delete p1;
00278 return ret;
00279 }
00280
00281 if (strcmp(opp, "EXIST")==0)
00282 {
00283 hasExist = true;
00284 const ListObj* a2 = arg2(p1);
00285 const ListObj* a1 = arg1(p1);
00286
00287
00288
00289 if (domain == NULL)
00290 {
00291 ListObj* sk = skolemize(a2, a1, vars);
00292 ListObj* c = toCNF(sk, vars, domain, vtMap, hasExist);
00293 delete sk; delete p1;
00294 return c;
00295 }
00296
00297 Array<string> varNames;
00298 for (int i = 0; i < a1->size(); i++)
00299 varNames.append((*a1)[i]->getStr());
00300
00301 ArraysAccessor<int> arrAccessor;
00302 for (int i = 0; i < varNames.size(); i++)
00303 {
00304 VarTypeMap::const_iterator mit = vtMap->find(varNames[i]);
00305 assert(mit != vtMap->end());
00306 int typeId = (*mit).second;
00307 assert(typeId > 0);
00308 const Array<int>* constArr = domain->getConstantsByType(typeId);
00309 if (constArr->size() == 0)
00310 {
00311 cout << "You must declare constants for type "
00312 << domain->getTypeName(typeId)
00313 << " in order to ground the variable " << varNames[i] << endl;
00314 exit(-1);
00315 }
00316 arrAccessor.appendArray(constArr);
00317 }
00318
00319 if (varNames.size()==0){cout<<"ERROR: EXIST has no vars."<<endl;exit(-1);}
00320
00321 ListObj* newFormula = new ListObj;
00322 newFormula->append("v");
00323 Array<int> constIds;
00324 while (arrAccessor.getNextCombination(constIds))
00325 {
00326 ListObj* replacedFormula = new ListObj(a2);
00327
00328 assert(constIds.size() == varNames.size());
00329 for (int i = 0; i < varNames.size(); i++)
00330 {
00331 const char* constName = domain->getConstantName(constIds[i]);
00332 replace(replacedFormula, varNames[i].c_str(), constName, domain);
00333 }
00334 newFormula->append(replacedFormula);
00335 }
00336
00337
00338
00339 delete p1;
00340 ListObj* c = toCNF(newFormula, vars, domain, vtMap, hasExist);
00341
00342 delete newFormula;
00343 return c;
00344 }
00345
00346 return p1;
00347 }
00348
00349
00350 void replaceAsterisk(const Array<bool>& bArr, int& idx)
00351 {
00352 if (!isStr())
00353 {
00354 const char* opp = op(this)->str_;
00355
00356 if (strcmp(opp, "*")==0)
00357 {
00358 assert(size()==2);
00359
00360
00361 if (!bArr[idx])
00362 (*this)[0]->setStrIfStr("!");
00363 else
00364 {
00365 ListObj* unNegatedFormula = new ListObj((*this)[1]);
00366 assert(!unNegatedFormula->isStr());
00367 deleteAndClear();
00368 for (int i = 0; i < unNegatedFormula->size(); i++)
00369 append((*unNegatedFormula)[i]);
00370 unNegatedFormula->clear();
00371 delete unNegatedFormula;
00372 }
00373 idx++;
00374 if (idx == bArr.size()) return;
00375 }
00376
00377 for (int i = 0; i < size(); i++)
00378 {
00379 (*this)[i]->replaceAsterisk(bArr, idx);
00380 if (idx == bArr.size()) return;
00381 }
00382 }
00383 }
00384
00385
00386
00387 void cleanUpVars()
00388 {
00389 if (isStr())
00390 {
00391 if (str_[0] != '$') return;
00392 char* dot = strrchr(str_, '.');
00393 if (dot==NULL) return;
00394 int numChar = dot-str_-1;
00395 char* tmp = new char[numChar+1];
00396 strncpy(tmp, str_+1, numChar);
00397 tmp[numChar] = '\0';
00398 delete [] str_;
00399 str_ = tmp;
00400 }
00401 else
00402 for (int i = 0; i < list_.size(); i++)
00403 list_[i]->cleanUpVars();
00404 }
00405
00406
00407 void removeRedundantPredicates()
00408 {
00409 const char* opp = op(this)->str_;
00410
00411 if (strcmp(opp,"^")==0)
00412 {
00413 for (int i = 1; i < size(); i++)
00414 removeRedundantPredicates((*this)[i]);
00415 }
00416 else
00417 removeRedundantPredicates(this);
00418 }
00419
00420
00421 void removeRedundantClauses()
00422 {
00423
00424
00425
00426
00427
00428 const char* opp = op(this)->str_;
00429
00430 if (strcmp(opp,"^")==0)
00431 {
00432 for (int i = 1; i < size(); i++)
00433 removeRedundantPredicates((*this)[i]);
00434
00435 Array<ListObj*> clauses, redundantClauses;
00436 for (int i = 1; i < size(); i++)
00437 {
00438 bool keep = true;
00439 for (int j = 1; j < size(); j++)
00440 {
00441 if (i==j) continue;
00442 if (subsetOf((*this)[j],(*this)[i]))
00443 if ((*this)[i]->size() != (*this)[j]->size() || i < j)
00444 { keep = false; break; }
00445 }
00446 if (keep) clauses.append((*this)[i]);
00447 else redundantClauses.append((*this)[i]);
00448 }
00449
00450 ListObj* andOper = (*this)[0];
00451 assert(strcmp(andOper->str_,"^")==0);
00452
00453 for (int i = 0; i < redundantClauses.size(); i++)
00454 delete redundantClauses[i];
00455 clear();
00456 append(andOper);
00457 for (int i = 0; i < clauses.size(); i++) append(clauses[i]);
00458 }
00459 else
00460 removeRedundantPredicates(this);
00461 }
00462
00463
00464 static void replace(const ListObj* const & p, const char* const & varName,
00465 const char* const& constName, const Domain* const& domain)
00466 {
00467 const char* opp = op(p)->str_;
00468
00469
00470
00471 if (strcmp(opp, "EXIST")==0 || strcmp(opp, "FORALL")==0)
00472 if (containsVarName((*p)[1], varName)) return;
00473
00474
00475 const bool isPredFunc = ( domain->isPredicate(opp)
00476 || domain->isFunction(opp));
00477
00478 for (int i = 1; i < p->size(); i++)
00479 {
00480
00481
00482 if (isPredFunc && (*p)[i]->isStr())
00483 {
00484
00485 if (strcmp((*p)[i]->getStr(), varName)==0)
00486 (*p)[i]->setStrIfStr(constName);
00487 }
00488 else
00489 replace((*p)[i], varName, constName, domain);
00490 }
00491 }
00492
00493
00494 void replace(const char* const & oldop, const char* const & newop)
00495 {
00496 for (int i = 0; i < size(); i++)
00497 {
00498 if (strcmp((*this)[i]->getStr(), oldop)==0)
00499 (*this)[i]->setStrIfStr(newop);
00500 else
00501 (*this)[i]->replace(oldop, newop);
00502 }
00503 }
00504
00505
00506 bool hasOrOp()
00507 {
00508 if (!isList()) return false;
00509 return (strcmp(op(this)->str_,"v")==0);
00510 }
00511
00512
00513 bool hasAndOp()
00514 {
00515 if (!isList()) return false;
00516 return (strcmp(op(this)->str_,"^")==0);
00517 }
00518
00519
00520 private:
00521 static bool same(const ListObj* const & lo1, const ListObj* const & lo2)
00522 {
00523 if (lo1->isStr() && lo2->isStr())
00524 {
00525 if (strcmp(lo1->str_, lo2->str_)==0) return true;
00526 return false;
00527 }
00528
00529 if (lo1->isList() && lo2->isList())
00530 {
00531 if (lo1->size() == lo2->size())
00532 {
00533 for (int i = 0; i < lo1->size(); i++)
00534 if (!same((*lo1)[i],(*lo2)[i])) return false;
00535 return true;
00536 }
00537 return false;
00538 }
00539 return false;
00540 }
00541
00542
00543 void sub(const ListObj* const & oldlo, const ListObj* const & newlo)
00544 {
00545 if (isStr())
00546 {
00547 if (same(this, oldlo))
00548 {
00549 if (newlo->isStr())
00550 {
00551 delete [] str_;
00552 str_ = new char[strlen(newlo->str_)+1];
00553 strcpy(str_, newlo->str_);
00554 }
00555 else
00556 {
00557 delete [] str_;
00558 str_ = new char[1];
00559 str_[0] = '\0';
00560 list_.deleteItemsAndClear();
00561
00562 for (int i = 0; i < newlo->size(); i++)
00563 list_.append(new ListObj((*newlo)[i]));
00564 }
00565 }
00566 return;
00567 }
00568
00569 for (int i = 0; i < list_.size(); i++)
00570 {
00571 if (same(list_[i],oldlo)) {delete list_[i]; list_[i]=new ListObj(newlo); }
00572 else list_[i]->sub(oldlo, newlo);
00573 }
00574 }
00575
00576
00577 static const ListObj* op(const ListObj* const & exp)
00578 {
00579 assert(exp->isList());
00580 if (exp->size() == 0) return exp;
00581 return (*exp)[0];
00582 }
00583
00584
00585 static const ListObj* arg1(const ListObj* const & exp)
00586 {
00587 if (exp->isList() && exp->size() > 1) return (*exp)[1];
00588 else return null_;
00589 }
00590
00591
00592 static const ListObj* arg2(const ListObj* const & exp)
00593 {
00594 if (exp->isList() && exp->size() > 2) return (*exp)[2];
00595 else return null_;
00596 }
00597
00598
00599
00600 static bool isConnective(const char* const & c)
00601 {
00602 if (strcmp(c, "^")==0 || strcmp(c, "v")==0 || strcmp(c, "!")==0 ||
00603 strcmp(c, "=>")==0 || strcmp(c, "<=>")==0 )
00604 return true;
00605 return false;
00606 }
00607
00608
00609 static bool isQuantifier(const char* const & q)
00610 {
00611 if (strcmp(q, "FORALL")==0 || strcmp(q, "EXIST")==0)
00612 return true;
00613 return false;
00614 }
00615
00616
00617
00618 static bool isAtomicClause(const ListObj* const & sentence)
00619 {
00620
00621
00622 const char* opp = op(sentence)->str_;
00623 if (!isConnective(opp) && !isQuantifier(opp)) return true;
00624 return false;
00625 }
00626
00627
00628 static bool isNegatedClause(const ListObj* const & sentence)
00629 {
00630 if (strcmp(op(sentence)->str_, "!")==0) return true;
00631 return false;
00632 }
00633
00634
00635 static bool isLiteralClause(const ListObj* const & sentence)
00636 {
00637 if (isAtomicClause(sentence) || (isNegatedClause(sentence)
00638 && isAtomicClause(arg1(sentence))))
00639 return true;
00640 return false;
00641 }
00642
00643
00644 static ListObj* eliminateImplication(const ListObj* const & p)
00645 {
00646 if (isLiteralClause(p)) return new ListObj(p);
00647
00648 const char* opp = op(p)->str_;
00649
00650 if (strcmp(opp, "=>")==0)
00651 {
00652 ListObj* n1 = new ListObj;
00653 n1->append("!"); n1->append(new ListObj(arg1(p)));
00654 ListObj* n = new ListObj;
00655 n->append("v"); n->append(new ListObj(arg2(p))); n->append(n1);
00656 return n;
00657 }
00658 else
00659 if (strcmp(opp, "<=>")==0)
00660 {
00661 ListObj* n1a = new ListObj;
00662 n1a->append("!"); n1a->append(new ListObj(arg1(p)));
00663 ListObj* na = new ListObj;
00664 na->append("v"); na->append(n1a); na->append(new ListObj(arg2(p)));
00665
00666 ListObj* n1b = new ListObj;
00667 n1b->append("!"); n1b->append(new ListObj(arg2(p)));
00668 ListObj* nb = new ListObj;
00669 nb->append("v"); nb->append(new ListObj(arg1(p)));
00670 nb->append(n1b);
00671
00672 ListObj* n = new ListObj; n->append("^"); n->append(nb); n->append(na);
00673 return n;
00674 }
00675 else
00676 {
00677 ListObj* n = new ListObj; n->append(opp);
00678 for (int i = 1; i < p->size(); i++)
00679 n->append(eliminateImplication((*p)[i]));
00680 return n;
00681 }
00682 }
00683
00684
00685 static ListObj* moveNotInwards(const ListObj* const & p)
00686 {
00687 const char* opp = op(p)->str_;
00688
00689 if (strcmp(opp, "!")==0) return new ListObj((*p)[1]);
00690
00691 if (strcmp(opp, "^")==0)
00692 {
00693 ListObj* n = NULL;
00694 int numDisj = 0;
00695 ListObj* firstDisj = NULL;
00696
00697 for (int i = 1; i < p->size(); i++)
00698 {
00699 numDisj++;
00700 if (numDisj == 1) { firstDisj = moveNotInwards((*p)[i]); continue; }
00701 else
00702 if (numDisj == 2) {n=new ListObj; n->append("v"); n->append(firstDisj);}
00703 n->append(moveNotInwards((*p)[i]));
00704 }
00705 if (numDisj == 1) return firstDisj;
00706 return n;
00707 }
00708
00709 if (strcmp(opp, "v")==0)
00710 {
00711 ListObj* n = NULL;
00712 int numConj = 0;
00713 ListObj* firstConj = NULL;
00714
00715 for (int i = 1; i < p->size(); i++)
00716 {
00717 numConj++;
00718 if (numConj == 1) { firstConj = moveNotInwards((*p)[i]); continue; }
00719 else
00720 if (numConj == 2) { n=new ListObj; n->append("^");n->append(firstConj);}
00721 n->append(moveNotInwards((*p)[i]));
00722 }
00723
00724 if (numConj == 1) return firstConj;
00725 return n;
00726 }
00727
00728 if (strcmp(opp, "FORALL")==0)
00729 {
00730 ListObj* n = new ListObj;
00731 n->append("EXIST");
00732 n->append(new ListObj((*p)[1]));
00733 n->append(moveNotInwards((*p)[2]));
00734 return n;
00735 }
00736
00737 if (strcmp(opp, "EXIST")==0)
00738 {
00739 ListObj* n = new ListObj;
00740 n->append("FORALL");
00741 n->append(new ListObj((*p)[1]));
00742 n->append(moveNotInwards((*p)[2]));
00743 return n;
00744 }
00745
00746 ListObj* n = new ListObj; n->append("!"); n->append(new ListObj(p));
00747 return n;
00748 }
00749
00750
00751 static ListObj* disjunctionAndAppend(const ListObj* const & p1,
00752 const ListObj* const & p2)
00753 {
00754 bool p1IsDisjunc = (strcmp(op(p1)->str_, "v")==0);
00755 int ibeg = (p1IsDisjunc) ? 1 : 0;
00756 int iend = (p1IsDisjunc) ? p1->size() : 1;
00757
00758 bool p2IsDisjunc = (strcmp(op(p2)->str_, "v")==0);
00759 int jbeg = (p2IsDisjunc) ? 1 : 0;
00760 int jend = (p2IsDisjunc) ? p2->size() : 1;
00761
00762 ListObj* n = new ListObj();
00763 if (p1->size()+p2->size() > 1) n->append("v");
00764
00765 for (int i = ibeg; i < iend; i++)
00766 {
00767 if (p1IsDisjunc) n->append(new ListObj((*p1)[i]));
00768 else n->append(new ListObj(p1));
00769 }
00770
00771 for (int j = jbeg; j < jend; j++)
00772 {
00773 if (p2IsDisjunc) n->append(new ListObj((*p2)[j]));
00774 else n->append(new ListObj(p2));
00775 }
00776 return n;
00777 }
00778
00779
00780 static ListObj* mergeDisjuncts(const ListObj* const & ddisjuncts,
00781 const int& numDisj)
00782 {
00783 assert(ddisjuncts->size() >= 1);
00784 if (numDisj == 1) return new ListObj((*ddisjuncts)[ ddisjuncts->size()-1 ]);
00785
00786 ListObj* y = mergeDisjuncts(ddisjuncts, numDisj-1);
00787 ListObj* x = new ListObj((*ddisjuncts)[ ddisjuncts->size()-numDisj ]);
00788 int numConj = 0;
00789 ListObj* result = NULL;
00790 ListObj* firstConj = NULL;
00791 ListObj* yj, * xi;
00792
00793 bool yIsConj = strcmp(op(y)->str_, "^")==0;
00794 int jbeg = (yIsConj) ? 1 : 0;
00795 int jmax = (yIsConj) ? y->size() : 1;
00796
00797 bool xIsConj = strcmp(op(x)->str_, "^")==0;
00798 int xbeg = (xIsConj) ? 1 : 0;
00799 int xmax = (xIsConj) ? x->size() : 1;
00800
00801 for (int j = jbeg; j < jmax; j++)
00802 {
00803 if (yIsConj) yj = (*y)[j];
00804 else yj = y;
00805
00806 for (int i = xbeg; i < xmax; i++)
00807 {
00808 if (xIsConj) xi = (*x)[i];
00809 else xi = x;
00810
00811 numConj++;
00812 if (numConj == 1)
00813 {
00814 firstConj = disjunctionAndAppend(xi, yj);
00815 continue;
00816 }
00817 else
00818 if (numConj == 2)
00819 {
00820 result = new ListObj();
00821 result->append("^");
00822 result->append(firstConj);
00823 }
00824
00825 result->append(disjunctionAndAppend(xi, yj));
00826 }
00827 }
00828
00829 delete y; delete x;
00830 if (numConj == 1) return firstConj;
00831 return result;
00832 }
00833
00834
00835 static bool isVariable(const ListObj* const & x)
00836 {
00837 if (strlen(x->str_) == 0) return false;
00838 return ((x->str_)[0] == '$');
00839 }
00840
00841
00842 static ListObj* newVariable(const ListObj* const & var)
00843 {
00844 assert(var->isStr());
00845 string s;
00846 if (!isVariable(var)) s.append("$");
00847 char buf[128];
00848 sprintf(buf, "%d", ++newVarCounter_);
00849 s.append(var->str_).append(".").append(buf);
00850 return new ListObj(s.c_str());
00851 }
00852
00853
00854 static ListObj* skolemConstant(const ListObj* const & name)
00855 {
00856 assert(name->isStr());
00857 char buf[1024];
00858 sprintf(buf, "$%s_%d", name->str_, ++newVarCounter_);
00859 return new ListObj(buf);
00860 }
00861
00862
00863 static ListObj* cons(ListObj* const & p1, const ListObj* const & p2)
00864 {
00865 assert(p2->isList());
00866 ListObj* n = new ListObj;
00867 n->append(p1);
00868 for (int i = 0; i < p2->size(); i++)
00869 n->append(new ListObj((*p2)[i]));
00870 return n;
00871 }
00872
00873
00874 static ListObj* skolemize(const ListObj* const & p,
00875 const ListObj* const & vars,
00876 const ListObj* const & outsideVars)
00877 {
00878 ListObj* pcopy = new ListObj(p);
00879
00880 ListObj* skolemSym = new ListObj;
00881 if (outsideVars->size() == 0)
00882 {
00883 for (int i = 0; i < vars->size(); i++)
00884 skolemSym->append(skolemConstant((*vars)[i]));
00885 }
00886 else
00887 {
00888 for (int i = 0; i < vars->size(); i++)
00889 skolemSym->append( cons(skolemConstant((*vars)[i]),outsideVars) );
00890 }
00891 assert(skolemSym->size() == vars->size());
00892
00893 for (int i = 0; i < pcopy->size(); i++)
00894 for (int j = 0; j < skolemSym->size(); j++)
00895 (*pcopy)[i]->sub((*vars)[j], (*skolemSym)[j]);
00896
00897 delete skolemSym;
00898
00899 return pcopy;
00900 }
00901
00902
00903 static bool containsVarName(const ListObj* const & vars,
00904 const char* const & varName)
00905 {
00906 for (int i = 0; i < vars->size(); i++)
00907 if (strcmp((*vars)[i]->getStr(), varName)==0) return true;
00908 return false;
00909 }
00910
00911
00912
00913 static void removeRedundantPredicates(ListObj* const & p)
00914 {
00915 const char* opp = op(p)->str_;
00916
00917
00918 if (strcmp(opp,"v")!=0) return;
00919
00920 Array<ListObj*> preds, redundantPreds;
00921 for (int i = 1; i < p->size(); i++)
00922 {
00923 bool unique = true;
00924 for (int j = i+1; j < p->size(); j++)
00925 if (same((*p)[i],(*p)[j])) { unique = false; break; }
00926 if (unique) preds.append((*p)[i]);
00927 else redundantPreds.append((*p)[i]);
00928 }
00929
00930 ListObj* orOper = (*p)[0];
00931 assert(strcmp(orOper->str_,"v")==0);
00932 for (int i = 0; i < redundantPreds.size(); i++)
00933 delete redundantPreds[i];
00934 p->clear();
00935
00936 if (preds.size() > 1)
00937 {
00938 p->append(orOper);
00939 for (int i = 0; i < preds.size(); i++) p->append(preds[i]);
00940 }
00941 else if (preds.size() == 1)
00942 {
00943 p->str_ = preds[0]->str_;
00944 p->list_ = preds[0]->list_;
00945 }
00946 }
00947
00948
00949 static bool subsetOf(const ListObj* const & p, const ListObj* const & q)
00950 {
00951 if (p->size() > q->size()) return false;
00952 for (int i = 0; i < p->size(); i++)
00953 {
00954 bool sameAsOneElt = false;
00955 for (int j = 0; j < q->size(); j++)
00956 if (same((*p)[i],(*q)[j])) { sameAsOneElt = true; break; }
00957 if (!sameAsOneElt) return false;
00958 }
00959 return true;
00960 }
00961
00962
00963 private:
00964
00965
00966
00967
00968
00969 Array<ListObj*> list_;
00970
00971 char* str_;
00972
00973 static int newVarCounter_;
00974 static ListObj* null_;
00975 };
00976
00977
00978 inline
00979 ostream& operator<<(ostream& out, const ListObj& p) { return p.print(out); }
00980
00981
00982 #endif