- Main Page
- Namespaces
- Classes
- Files
- Related Pages

# /Users/fpy/titan-1-5-MBARI/Mers/Solvers/SAT/GATSAT/VsatBfig/GenGenTestTradeoff.cpp

    00001
    00002 //
    00003 // Copyright (c) 2004           Model-based Embedded and Robotic Systems Group
    00004 // All Rights Reserved          Massachusetts Institute of Technology
    00005 //
    00006 // This software is provided as is. Model-based Embedded and Robotic Systems
    00007 // (MERS) group does not assume any responsibility.
    00008 //
    00010 //# CHECKED MJP 08-07-2002
    00011
    00012 #ifdef _MSC_VER
    00013 #pragma warning( disable : 4786 )
    00014 #endif
    00015
    00016 #include <cstdlib>
    00017 #include <cstdio>
    00018 #include <cassert>
    00019 #include <iostream>
    00020 #include <fstream>
    00021 #include <string>
    00022 #include <cmath>
    00023 #include <ctime>
    00024 #include <list>
    00025 #include <vector>
    00026
    00028
    00029 using std::ostream;
    00030 using std::ofstream;
    00031 using std::vector;
    00032 using std::string;
    00033 using std::cerr;
    00034 using std::cout;
    00035 using std::endl;
    00036
    00038
    00042 class DomainElement
    00043 {
    00044 public:
    00046         string value;
    00048         double probability;
    00049
    00057         DomainElement(string v, double p)
    00058                 : value(v), probability(p)
    00059         {
    00060         }
    00061
    00068         DomainElement(DomainElement const & de)
    00069                 : value(de.value), probability(de.probability)
    00070         {
    00071         }
    00072 };
    00073
    00075
    00079 class ConstraintElement
    00080 {
    00081 public:
    00083         string variable;
    00085         string value;
    00087         bool sign;
    00088
    00099         ConstraintElement(string var, string val, bool s)
    00100                 : variable(var), value(val), sign(s)
    00101         {
    00102         }
    00103
    00109         ConstraintElement(ConstraintElement const & ce)
    00110                 : variable(ce.variable), value(ce.value), sign(ce.sign)
    00111         {
    00112         }
    00113 };
    00114
    00116
    00123 double randDouble()
    00124 {
    00125         // Compute a random value in the range [0, RAND_MAX].
    00126         int n = rand();
    00127
    00128         // Rescale the value into the range [0, 1].
    00129         double res = (double) n / (double) RAND_MAX;
    00130
    00131         // Verify our assertions.
    00132         assert(0.0 <= res && res <= 1.0);
    00133
    00134         // Return our answer.
    00135         return res;
    00136 }
    00137
    00139
    00146 double randDoubleNI()
    00147 {
    00148         // Compute a random value in the range [0, RAND_MAX].
    00149         int n = rand();
    00150
    00151         // Rescale the value into the range [0, 1).  Note that we assume
    00152         // that RAND_MAX is probably MAX_INT, so we need to convert it to a
    00153         // double before adding 1.
    00154         double res = (double) n / (((double) RAND_MAX) + 1);
    00155
    00156         // Verify our assertions.
    00157         assert(0.0 <= res && res < 1.0);
    00158
    00159         // Return our answer.
    00160         return res;
    00161 }
    00162
    00164
    00174 int randRange(int low, int high)
    00175 {
    00176         // Get a random value in the range [0, 1].
    00177         double rVal = randDoubleNI();
    00178
    00179         // Get a value between [0, high - low], with an equal distribution.
    00180         int offset = (int) ( rVal * (high - low + 1) );
    00181
    00182         // Rescale in the range of [low, high].
    00183         int res = low + offset;
    00184
    00185         // Verify our assertions.
    00186         assert(low <= res && res <= high);
    00187
    00188         // Return our answer.
    00189         return res;
    00190 }
    00191
    00193
    00201 int randRange(int high)
    00202 {
    00203         return randRange(0, high);
    00204 }
    00205
    00207
    00213 bool file_exist(const char * filename)
    00214 {
    00215         // Open the file in read-only mode.  This function fails if the file
    00216         // does not exist.
    00217         FILE * file = fopen(filename,"r");
    00218
    00219         // If the function failed, the file does not exist.
    00220         if ( file == NULL )
    00221                 return false;
    00222
    00223         // Make sure we close the file before returning.
    00224         fclose(file);
    00225         return true;
    00226 }
    00227
    00229
    00237 vector< double > createProbabilities(unsigned int len)
    00238 {
    00239         // We're going to attempt to re-use the space we're creating.  So
    00240         // we'll make two passes on the list of doubles.
    00241         double sum = 0;
    00242
    00243         // Our list of doubles.
    00244         vector< double > res;
    00245
    00246         // First pass - determine an initial distribution, keeping track of the sum.
    00247         for (unsigned int i = 0; i < len; ++i)
    00248         {
    00249                 // Get a number in the range [0, 1].
    00250                 double prob = randDouble();
    00251                 // Add it to our list.
    00252                 res.push_back(prob);
    00253                 // Keep a running sum.
    00254                 sum += prob;
    00255         }
    00256
    00257         // For debugging reasons, just make sure that the sum is in fact about 1.
    00258         double sumCheck = 0;
    00259
    00260         // Second pass - rescale the values by sum.
    00261         for (unsigned int i2 = 0; i2 < len; ++i2)
    00262         {
    00263                 // Rescale by the sum.
    00264                 res[i2] /= sum;
    00265                 // Verify that our sum stays small enough.
    00266                 assert( (sumCheck += res[i2]) <= 1.001 );
    00267         }
    00268
    00269         // Make sure that our sum is large enough.
    00270         assert( sumCheck >= 0.999 );
    00271
    00272         // Return our answer.
    00273         return res;
    00274 }
    00275
    00277
    00289 vector<int> createCosts(unsigned int len, int minCost, int maxCost)
    00290 {
    00291         // Our set of values.
    00292         vector<int> res;
    00293
    00294         // Generate a set of costs in the specified range.
    00295         for (unsigned int i = 0; i < len; ++i)
    00296         {
    00297                 // Add a new entry in the range [minCost, maxCost].
    00298                 res.push_back( randRange(minCost, maxCost) );
    00299         }
    00300         // Return our answer.
    00301         return res;
    00302 }
    00303
    00305
    00319 vector<string> createNames(unsigned int len, bool upperCase = true)
    00320 {
    00321         // We can at most generate a name of length 14, with a 64 bit
    00322         // integer, given than we're working in base 26.  We need to keep
    00323         // one extra space for the null terminator.
    00324         // We compute this as (64 * log_26(2) = 64 * ln(2) / ln(26)).
    00325         char name[15];
    00326
    00327         // Set our base character depending on whether or not we're upper case.
    00328         char base = upperCase ? 'A' : 'a';
    00329
    00330         // Our list of names will be stored here.
    00331         vector<string> res;
    00332
    00333         // Generate each name in sequence.
    00334         for (unsigned int i = 0; i < len; ++i)
    00335         {
    00336                 // This identifier is the value we're trying to convert to a name.
    00337                 unsigned int resid = i;
    00338                 // We're going to compute our name incrementally start at the head
    00339                 // of the name.
    00340                 char * pos = name;
    00341
    00342                 // Start by storing our id modulo 26, mapped to 'a'..'z'.
    00343                 *pos = base + (resid % 26);
    00344
    00345                 // Point to the next position.
    00346                 ++pos;
    00347
    00348                 // Divide out the portion of the id that we just mapped.
    00349                 resid /= 26;
    00350
    00351                 // While we still have a value left, keep adding more values.
    00352                 while (resid)
    00353                 {
    00354                         // At this point, resid will always be at least 1, since
    00355                         // resid >= 26 and so resid / 26 >= 1.
    00356                         // If resid is in the range [1, 26], then we only need to place
    00357                         // one more character (offset by one).
    00358                         if(resid <= 26){
    00359                                 // Store our last character, which needs to be offset from
    00360                                 // [1, 26], to [0, 25].
    00361                                 *pos = base + resid - 1;
    00362                                 // resid is now 0.
    00363                                 resid = 0;
    00364                         }else{
    00365                                 // Otherwise, we account for a space in each non-empty square,
    00366                                 // so our range will always run from [0, 26], and we will
    00367                                 // ignore the 0.
    00368                                 --resid;
    00369                                 // Store our next value.
    00370                                 *pos = base + (resid % 26);
    00371
    00372                                 // Rescale by 26.
    00373                                 resid /= 26;
    00374                         }
    00375                         // Move to the next spot.
    00376                         ++pos;
    00377                 }
    00378                 // Null-terminate our name.
    00379                 *pos = '\0';
    00380                 // create a string for our name.
    00381                 string nameStr(name);
    00382                 // Add it to our list.
    00383                 res.push_back(nameStr);
    00384         }
    00385
    00386         // Return our list.
    00387         return res;
    00388 }
    00389
    00391
    00399 vector< DomainElement > createDomain(unsigned int len)
    00400 {
    00401         // We will store our result here.
    00402         vector< DomainElement > res;
    00403         // Get a list of name for our domain.  Values are lower case.
    00404         vector<string> vals  = createNames(len, false);
    00405         // Get a list of probabilities.
    00406         vector<double> probs = createProbabilities(len);
    00407
    00408         // For each value, initialize it with the names and probabilities.
    00409         vector<string>::const_iterator vIter;
    00410         vector<double>::const_iterator pIter;
    00411         for (vIter = vals.begin(), pIter = probs.begin(); vIter != vals.end();
    00412                 ++vIter, ++pIter)
    00413         {
    00414                 // Get our name.
    00415                 string v = *vIter;
    00416                 // Get our probability.
    00417                 double p = *pIter;
    00418                 // Add a new domain entry.
    00419                 res.push_back(DomainElement(v,p));
    00420         }
    00421
    00422         // Return our answer.
    00423         return res;
    00424 }
    00425
    00427
    00439 vector< DomainElement >
    00440 createDomainRandom(unsigned int minDomain, unsigned int maxDomain)
    00441 {
    00442         // The size of the domain we desire will be stored here.
    00443         unsigned int domainSize;
    00444
    00445         // If our random range is a point (or empty), just use use the
    00446         // maximum value.
    00447         if(minDomain >= maxDomain)
    00448                 domainSize = maxDomain;
    00449         else
    00450                 // Otherwise compute a random value.
    00451                 domainSize = (unsigned int)randRange(minDomain, maxDomain);
    00452
    00453         // Return a new domain of size domainSize.
    00454         return createDomain(domainSize);
    00455 }
    00456
    00458
    00470 vector< DomainElement >
    00471 createDomain(unsigned int len, int minCost, int maxCost)
    00472 {
    00473         // We will store our result here.
    00474         vector< DomainElement > res;
    00475         // Get a list of name for our domain.  Values are lower case.
    00476         vector<string> vals  = createNames(len, false);
    00477         // Get a list of probabilities.
    00478         vector<int> costs = createCosts(len, minCost, maxCost);
    00479
    00480         // For each value, initialize it with the names and probabilities.
    00481         vector<string>::const_iterator vIter;
    00482         vector<int>::const_iterator pIter;
    00483         for (vIter = vals.begin(), pIter = costs.begin(); vIter != vals.end();
    00484                 ++vIter, ++pIter)
    00485         {
    00486                 // Get our name.
    00487                 string v = *vIter;
    00488                 // Get our probability.
    00489                 int c = *pIter;
    00490                 // Add a new domain entry.
    00491                 res.push_back(DomainElement(v,c));
    00492         }
    00493
    00494         // Return our answer.
    00495         return res;
    00496 }
    00497
    00499
    00515 vector< DomainElement >
    00516 createDomainRandom(unsigned int minDomain, unsigned int maxDomain,
    00517         int minCost, int maxCost)
    00518 {
    00519         // The size of the domain we desire will be stored here.
    00520         unsigned int domainSize;
    00521
    00522         // If our random range is a point (or empty), just use use the
    00523         // maximum value.
    00524         if(minDomain >= maxDomain)
    00525                 domainSize = maxDomain;
    00526         else
    00527                 // Otherwise compute a random value.
    00528                 domainSize = (unsigned int)randRange(minDomain, maxDomain);
    00529
    00530         // Return a new domain of size domainSize.
    00531         return createDomain(domainSize, minCost, maxCost);
    00532 }
    00533
    00535
    00549 void printVariable(string name, vector< DomainElement > domain, bool useCosts,
    00550         ostream & os = cout)
    00551 {
    00552         // Print the name.
    00553         os << name << "  ";
    00554
    00555         // Print each domain element.
    00556         vector<DomainElement>::const_iterator dIter;
    00557         for (dIter = domain.begin(); dIter != domain.end(); ++dIter)
    00558         {
    00559                 const DomainElement &de = (*dIter);
    00560                 // Print the name of the value.
    00561                 os << de.value << " ";
    00562                 // Print out the probability, if useCosts is true.
    00563                 if( useCosts )
    00564                         os << de.probability << " " ;
    00565         }
    00566         // A variable entry is always terminated by the end of the line.
    00567         os << endl;
    00568 }
    00569
    00571
    00579 void printConstraintElement(ConstraintElement ce, ostream & os = cout)
    00580 {
    00581         // Print the sign ('!') if negative.
    00582         if (!ce.sign)
    00583                 os << "!";
    00584
    00585         // Print out the variable and value of the literal.
    00586         os << "[" << ce.variable << "=" << ce.value << "]";
    00587 }
    00588
    00590
    00598 void printConstraint(vector< ConstraintElement > c, ostream & os = cout)
    00599 {
    00600         // Loop over each litera.
    00601         vector<ConstraintElement>::const_iterator cIter;
    00602         for (cIter = c.begin(); cIter != c.end(); ++cIter)
    00603         {
    00604                 // Print out a space if we're not the first element.
    00605                 if( cIter != c.begin() )
    00606                         os << " " ;
    00607
    00608                 // Print out this constraint.
    00609                 printConstraintElement((*cIter), os);
    00610         }
    00611
    00612         // Constraints are terminated by the end of the line.
    00613         os << endl;
    00614 }
    00615
    00617
    00627 ConstraintElement createConstraintElement(vector<string>  varNames,
    00628         vector< vector<DomainElement> > varDomains)
    00629 {
    00630         // The sign is positive or negative - fifty-fifty.
    00631         bool sign = (randDouble() <= 0.5);
    00632
    00633         // The index of variable that we want to use.
    00634         unsigned int varIndex = (unsigned int)randRange(0, varNames.size() - 1);
    00635
    00636         // The domain of the variable we chose.
    00637         vector<DomainElement> &domain = varDomains[varIndex];
    00638
    00639         // The index of the value that we want to use.
    00640         unsigned int valIndex = (unsigned int)randRange(0, domain.size() - 1);
    00641
    00642         // The name of the variable we chose.
    00643         string var = varNames[varIndex];
    00644
    00645         // The name of the value we chose.
    00646         string val = domain[valIndex].value;
    00647
    00648         // Return a new constraint element.
    00649         return ConstraintElement(var, val, sign);
    00650 }
    00651
    00653
    00666 vector<ConstraintElement>
    00667 createConstraint(vector<string>  varNames,
    00668         vector< vector<DomainElement> > varDomains, unsigned int numConstraint)
    00669 {
    00670         // Loop over each constraint we desire and create a literal.
    00671         vector<ConstraintElement> res;
    00672         for (unsigned int i = 0; i < numConstraint; ++i)
    00673         {
    00674                 // This variable determines our termination condition.
    00675                 bool ok;
    00676
    00677                 // Our next literal.
    00678                 ConstraintElement next("", "", true);
    00679
    00680                 // Create a literal, making sure that we don't repeat any of them.
    00681                 do {
    00682                         // Create a single literal
    00683                         next = createConstraintElement(varNames, varDomains);
    00684
    00685                         // At first, always assume that our literal is going to be ok.
    00686                         ok = true;
    00687
    00688                         // Loop over everything we've generated thus far and see if we
    00689                         // repeat anything.
    00690                         vector<ConstraintElement>::const_iterator cIter;
    00691                         for (cIter = res.begin(); cIter != res.end() && ok; ++cIter)
    00692                         {
    00693                                 const ConstraintElement &ce = (*cIter);
    00694
    00695                                 // If we find a match, we're not ok.
    00696                                 if (next.variable == ce.variable && next.value == ce.value)
    00697                                         ok = false;
    00698                         }
    00699                         // Terminate if we're ok.
    00700                 } while (!ok);
    00701
    00702                 // This is our next value.
    00703                 res.push_back(next);
    00704         }
    00705
    00706         // return our answer.
    00707         return res;
    00708 }
    00709
    00711
    00726 vector<ConstraintElement>
    00727 createConstraint(vector<string>  varNames,
    00728         vector< vector<DomainElement> > varDomains,
    00729         unsigned int minConstraint, unsigned int maxConstraint)
    00730 {
    00731         // The actual length we're going to use.
    00732         unsigned int len;
    00733
    00734         // If we're asked for a single size (or an empty size), use the
    00735         // maximum value.
    00736         if(minConstraint >= maxConstraint)
    00737                 len = maxConstraint;
    00738         else
    00739                 // Otherwise generate a random length in the range specified.
    00740                 len = (unsigned int)randRange(minConstraint, maxConstraint);
    00741
    00742         // Return a clause of this exact length.
    00743         return createConstraint(varNames, varDomains, len);
    00744 }
    00745
    00747
    00791
    00792
    00798 void printUse(const char * progName)
    00799 {
    00800         cout << "Program use.  [x] denotes the default value:" << endl <<
    00801                 progName << endl <<
    00802                 " -v #Vars - Number of variables [manditory]" << endl <<
    00803                 " -mind #Vals - Minimum number of values [maxd]" << endl <<
    00804                 " -maxd #Vals - Maximum number of values [manditory]" << endl <<
    00805                 " -o <Filename> - The name of the output file [TestCase.tests]" << endl <<
    00806                 " -c #Cons - Number of constraints [manditory]" << endl <<
    00807                 " -minl #Lits  - Minimum number of literals [maxl]" << endl <<
    00808                 " -maxl #Lits  - Maximum number of literals [manditory]" << endl <<
    00809                 " -minCost #cost - Minimum cost associated with nodes (integer).  -maxCost"
    00810                 " must be specified as well. [0]" << endl <<
    00811                 " -maxCost #cost - Maximum cost associated with nodes (integer).  "
    00812                 "Defaults to probabilitie [Probabilities]" << endl <<
    00813                 " -svars #Vars - The number of search variables.  By default, a problem "
    00814                 "is generated for each ratio of search and non-search variables. "
    00815                 "[Variation]" << endl <<
    00816                 " -help - Displays this message" << endl <<
    00817                 " -tests #tests - The number of test [1]" << endl;
    00818 }
    00819
    00821
    00822 // This is a boolean function that matches STR in the standard input,
    00823 // and that at least NUM parameters are available, including the
    00824 // initial string.
    00825 #define MATCHES( STR, NUM ) \
    00826         ((strcmp( STR, argv[i] ) == 0) && ( i + NUM <= argc ))
    00827
    00828 // Scans in a single variable from the stream.
    00829 #define SCAN1( STR, FORMAT, VAR, MSG ) \
    00830         if( sscanf( STR, FORMAT, VAR ) != 1 ) { \
    00831                 cerr << "Error: " << MSG << endl; \
    00832                 dispHelp = true; \
    00833         }
    00834
    00836
    00840 int main(int argc, const char * argv[])
    00841 {
    00842         // Intialize the random number generator.
    00843         srand((unsigned int)time(NULL));
    00844
    00845         // True when the number of variables has been specified on the
    00846         // command line.
    00847         bool nVarsSpec = false;
    00848         // Number of variables that we're going to be generating.
    00849         unsigned int numVariables = 0;
    00850         // The minimum number of values that should be in the domain.
    00851         unsigned int minVals = 0;
    00852         // True if the maximun number of values that should be in the domain
    00853         // has been specified on the command line.
    00854         bool maxValsSpec = false;
    00855         // The maximun number of values that should be in the domain.
    00856         unsigned int maxVals = 0;
    00857         // The name of the file we're using to export the test cases.
    00858         const char * outFileName = "TestCase.tests";
    00859         // True if the number of constraints has been specified.
    00860         bool nConsSpec = false;
    00861         // The number of constraints that should be generated.
    00862         unsigned int numConstraints = 0;
    00863         // The minimum number of literals in each clause.
    00864         unsigned int minLit = 0;
    00865         // True if the maximum number of literals in each clause has been
    00866         // specified on the command line.
    00867         bool maxLitSpec = false;
    00868         // The maximum number of literals in each clause.
    00869         unsigned int maxLit = 0;
    00870         // The minimum cost that can be generated.
    00871         int minCost = 0;
    00872         // True if we should use probabilities, false if we should use costs.
    00873         bool useProbs = true;
    00874         // The maximum cost that can be generated.
    00875         int maxCost = 0;
    00876         // True if we've specified the desired number of search variables.
    00877         // False if we will scan all ratios.
    00878         bool searchVarSpec = false;
    00879         // The fixed number of search variables.
    00880         int searchVars = 0;
    00881         // True if we should display help.
    00882         bool dispHelp = false;
    00883         // The number of different test cases that we should generate.
    00884         unsigned int numTests = 1;
    00885
    00886         // Loop over each command-line parameter.
    00887         for (int i = 1; i < argc; ++i)
    00888         {
    00889                 // Match (-v #Vars) - variable specification
    00890                 if( MATCHES( "-v",  2 ) ) {
    00891                         // We now have a variable specification.
    00892                         nVarsSpec = true;
    00893                         // Keep count
    00894                         ++i;
    00895                         // Get the # variable specification.
    00896                         SCAN1( argv[i], "%u", &numVariables, "-v takes an integer." );
    00897                 } else if( MATCHES( "-mind", 2 ) ) {
    00898                         // Keep count
    00899                         ++i;
    00900                         // Get the minimum number of domains.
    00901                         SCAN1( argv[i], "%u", &minVals, "-mind takes an integer." );
    00902                 } else if( MATCHES( "-maxd", 2 ) ) {
    00903                         // We now have a maximum domain count.
    00904                         maxValsSpec = true;
    00905                         // Keep count
    00906                         ++i;
    00907                         // Get the maximum number of domains.
    00908                         SCAN1( argv[i], "%u", &maxVals, "-maxd takes an integer." );
    00909                         // Setup the min value if it's not set.
    00910                         if( minVals == 0 ) {
    00911                                 minVals = maxVals;
    00912                         }
    00913                 } else if( MATCHES( "-o", 2 ) ) {
    00914                         // Keep count
    00915                         ++i;
    00916                         // Get the name of our file.
    00917                         outFileName = argv[i];
    00918                 } else if( MATCHES( "-c",  2 ) ) {
    00919                         // We now have a variable specification.
    00920                         nConsSpec = true;
    00921                         // Keep count
    00922                         ++i;
    00923                         // Get the # variable specification.
    00924                         SCAN1( argv[i], "%u", &numConstraints, "-c takes an integer." );
    00925                 } else if( MATCHES( "-minl", 2 ) ) {
    00926                         // Keep count
    00927                         ++i;
    00928                         // Get the minimum number of literals.
    00929                         SCAN1( argv[i], "%u", &minLit, "-minl takes an integer." );
    00930                 } else if( MATCHES( "-maxl", 2 ) ) {
    00931                         // We now have a maximum literal count.
    00932                         maxLitSpec = true;
    00933                         // Keep count
    00934                         ++i;
    00935                         // Get the maximum number of literals.
    00936                         SCAN1( argv[i], "%u", &maxLit, "-maxl takes an integer." );
    00937                         // Setup the min value if it's not set.
    00938                         if( minLit == 0 ) {
    00939                                 minLit = maxLit;
    00940                         }
    00941                 } else if( MATCHES( "-minCost", 2 ) ) {
    00942                         // Keep count
    00943                         ++i;
    00944                         // Get the minimum cost.
    00945                         SCAN1( argv[i], "%d", &minCost, "-minCost takes an integer." );
    00946                 } else if( MATCHES( "-maxCost", 2 ) ) {
    00947                         // We now have a maximum cost, so we're not using probabilities.
    00948                         useProbs = false;
    00949                         // Keep count
    00950                         ++i;
    00951                         // Get the maximum cost.
    00952                         SCAN1( argv[i], "%d", &maxCost, "-maxCost takes an integer." );
    00953                 } else if( MATCHES( "-svars", 2 ) ) {
    00954                         // We now have a specific search variable specification.
    00955                         searchVarSpec = true;
    00956                         // Keep count
    00957                         ++i;
    00958                         // Get the number of search variables.
    00959                         SCAN1( argv[i], "%d", &searchVars, "-svars takes an integer." );
    00960                 } else if( MATCHES( "-help", 1 ) ) {
    00961                         // They want the help message.
    00962                         dispHelp = true;
    00963                 } else if( MATCHES( "-tests", 2 ) ) {
    00964                         // Keep count
    00965                         ++i;
    00966                         // Get the number of search variables.
    00967                         SCAN1( argv[i], "%u", &numTests, "-tests takes an integer." );
    00968                 } else {
    00969                         cerr << "Unrecognized option: " << argv[i] << endl;
    00970                 }
    00971         }
    00972
    00973         // Make sure we show help if we're missing data.
    00974         dispHelp = dispHelp || !nVarsSpec || !maxValsSpec || !nConsSpec;
    00975
    00976         // See that we have all the required information.
    00977         if( !nVarsSpec )
    00978                 cerr << "Must specify the number of variables." << endl;
    00979         if( !maxValsSpec )
    00980                 cerr << "Must specify the maximum domain size." << endl;
    00981         if( !nConsSpec )
    00982                 cerr << "Must specify the number of constraints." << endl;
    00983
    00984         // If we have a request for a help message, display it.
    00985         if (dispHelp) {
    00986                 printUse(argv[0]);
    00987                 return -1;
    00988         }
    00989
    00990         // We should print the parameters we're using.
    00991         cout << "Generating " << numTests << " sets of tests." << endl;
    00992         cout << "Vars: " << numVariables << " with [" << minVals << ", " <<
    00993                 maxVals << "] values" << endl;
    00994         cout << "Constraints: " << numConstraints << " with [" << minLit << ", " <<
    00995                 maxLit << "] literals" << endl;
    00996         if(useProbs)
    00997                 cout << "Using probabilistic cost model." << endl;
    00998         else
    00999                 cout << "Using costs in the range [" << minCost << ", " << maxCost <<
    01000                         "]" << endl;
    01001         if( searchVarSpec )
    01002                 cout << "Using " << searchVars << " search variables" << endl;
    01003         else
    01004                 cout << "Using [0, " << numVariables << "] search variables" << endl;
    01005         cout << "Recording data to '" << outFileName << "'" << endl;
    01006
    01007         // Load our output file.
    01008         ofstream out(outFileName);
    01009
    01010         // Create a set of variable names.  Variable names are upper case.
    01011         vector<string> varNames = createNames(numVariables, true);
    01012
    01013         // Our unique test identifier.
    01014         unsigned int testID = 0;
    01015
    01016         // The total number of search variables we're going to process.
    01017         unsigned int minNumSVars = 0;
    01018         unsigned int maxNumSVars = numVariables;
    01019
    01020         // If we specified a fixed value, use it.
    01021         if( searchVarSpec ) {
    01022                 minNumSVars = searchVars;
    01023                 maxNumSVars = searchVars;
    01024         }
    01025
    01026         // Loop over one set for each test we want.
    01027         for(unsigned int test = 0; test < numTests; ++test) {
    01028
    01029                 // Our list of variable names and value names.
    01030                 vector< vector<DomainElement> > varDomains;
    01031
    01032                 // Create a domain for each variable.
    01033                 vector<string>::const_iterator itVars;
    01034                 for( itVars = varNames.begin(); itVars != varNames.end(); ++itVars ) {
    01035                         // Create a domain.
    01036                         vector<DomainElement> domain = createDomainRandom(minVals, maxVals);
    01037                         varDomains.push_back(domain);
    01038                 }
    01039
    01040                 // Our list of constraints.
    01041                 vector< vector< ConstraintElement > > theory;
    01042
    01043                 // Create a theory.
    01044                 for ( unsigned int i = 0; i < numConstraints; ++i )
    01045                 {
    01046                         vector<ConstraintElement> con =
    01047                                 createConstraint(varNames, varDomains, minLit, maxLit);
    01048                         theory.push_back(con);
    01049                 }
    01050
    01051                 // Now loop over all theory-domain constant differences, starting
    01052                 // with the numer of search/non-search variables.
    01053                 for (unsigned int numSearch = minNumSVars; numSearch <= maxNumSVars;
    01054                         ++numSearch, ++testID) {
    01055
    01056                         // Print the header for this test.
    01057                         out << "Test" << testID << endl << "Search" << endl;
    01058
    01059                         // Loop over each variable, printing it.
    01060                         unsigned int v = 0;
    01061                         for (; v < numSearch; ++v)
    01062                         {
    01063                                 // Print out this variable.
    01064                                 printVariable(varNames[v], varDomains[v], true, out);
    01065                         }
    01066
    01067                         // Print out the non-search seperator.
    01068                         out << "NonSearch" << endl;
    01069
    01070                         // Print out the non-search variables.
    01071                         for (; v < numVariables; ++v) {
    01072                                 // Print out this variable.
    01073                                 printVariable(varNames[v], varDomains[v], false, out);
    01074                         }
    01075
    01076                         // Print out the constraints header.
    01077                         out << "Constraints" << endl;
    01078
    01079                         // Print the constraints.
    01080                         for ( unsigned int c = 0; c < numConstraints; ++c )
    01081                         {
    01082                                 // Get the constraint.
    01083                                 vector<ConstraintElement> &con = theory[c];
    01084                                 // Print the constraint.
    01085                                 printConstraint(con, out);
    01086                         }
    01087                 }
    01088         }
    01089
    01090         // All done, close our files.
    01091         out.close();
    01092
    01093         // Now exit the program.
    01094         return 0;
    01095 }
    01096