Advertisement
faiuwle

MythMuse

Dec 12th, 2013
208
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.03 KB | None | 0 0
  1. #include <iostream>
  2. #include <fstream>
  3. #include <string>
  4. #include <queue>
  5. #include <vector>
  6. #include <cstdlib>
  7. #include <ctime>
  8. #include <cstdarg>
  9. using namespace std;
  10.  
  11. #define UNAVAILABLE 0
  12. #define AVAILABLE 1
  13. #define CHOSEN 2
  14. #define PERM_UNAVAILABLE 3
  15.  
  16. vector<string> output;
  17. vector<string> errors;
  18.  
  19. class MotifNode  {
  20.   public:
  21.     MotifNode (MotifNode*, string, string);
  22.     ~MotifNode ();
  23.    
  24.     bool insertNode (queue<string>, string);
  25.     bool deleteNode (queue<string>);
  26.     void printNode (int);
  27.  
  28.     bool selectRandom (int);
  29.     void resetAvailable ();
  30.     void printChosen ();
  31.  
  32.     void setRandomWeight (queue<string>, int);
  33.     void setStoryWeight (queue<string>, int);
  34.     void makeExclusive (vector< queue<string> >);
  35.  
  36.   private:
  37.     vector<MotifNode*> getAvailable (vector<MotifNode*>);
  38.     string getFullClassification ();
  39.     bool choose ();
  40.     vector<MotifNode*> classificationToPointer
  41.                           (queue<string>, vector<MotifNode*>);
  42.  
  43.     MotifNode *parent;
  44.     vector<MotifNode*> children;
  45.  
  46.     string classification;
  47.     string description;
  48.  
  49.     int availability;
  50.  
  51.     int randomWeight;
  52.     int storyWeight;
  53.     vector<MotifNode*> exclusiveWith;
  54. };
  55.  
  56. MotifNode::MotifNode (MotifNode *p, string cls, string desc)  {
  57.   parent = p;
  58.   classification = cls;
  59.   description = desc;
  60.   availability = UNAVAILABLE;
  61.   randomWeight = 100;
  62.   storyWeight = 100;
  63. }
  64.  
  65. MotifNode::~MotifNode ()  {
  66. //  cout << "Destructor: deleting children (" << description << ")" << endl;
  67.  
  68.   for (int x = 0; x < children.size (); x++)
  69.     delete children[x];
  70. }
  71.  
  72. bool MotifNode::insertNode (queue<string> cls, string desc)  {
  73.   if (cls.empty ())
  74.     return false;
  75.  
  76.   int next = -1;
  77.  
  78.   for (int x = 0; x < children.size (); x++)
  79.     if (children[x]->classification == cls.front ())  {
  80.       next = x;
  81.       break;
  82.     }
  83.  
  84.   if (cls.size () == 1)  {
  85.     if (next >= 0)  {
  86.       errors.push_back ("Replacing node with new description (" + desc + ")");
  87.       children[next]->description = desc;
  88.       return true;
  89.     }
  90.  
  91. //    cout << "Adding new node (" << desc << ")" << endl;
  92.     MotifNode *newNode = new MotifNode (this, cls.front (), desc);
  93.     children.push_back (newNode);
  94.     return true;
  95.   }
  96.  
  97.   if (next < 0)  {
  98.     errors.push_back ("Adding unknown intermediate node");
  99.     next = children.size ();
  100.     MotifNode *newNode = new MotifNode (this, cls.front (), "(Unknown)");
  101.     children.push_back (newNode);
  102.   }
  103.  
  104.   cls.pop ();
  105.   return children[next]->insertNode (cls, desc);
  106. }
  107.  
  108. bool MotifNode::deleteNode (queue<string> cls)  {
  109.   if (cls.empty ())
  110.     return false;
  111.  
  112.   int victim = -1;
  113.  
  114.   for (int x = 0; x < children.size (); x++)
  115.     if (children[x]->classification == cls.front ())  {
  116.       victim = x;
  117.       break;
  118.     }
  119.  
  120.   if (victim < 0)  {
  121.     errors.push_back ("Error: Motif node does not exist");
  122.     return false;
  123.   }
  124.  
  125.   if (cls.size () == 1)  {
  126.     errors.push_back ("Deleting node (" + children[victim]->description + ")");
  127.     delete children[victim];
  128.     return true;
  129.   }
  130.  
  131.   cls.pop ();
  132.   return children[victim]->deleteNode (cls);
  133. }
  134.  
  135. void MotifNode::printNode (int indent)  {
  136. //  for (int x = 0; x < indent; x++)
  137. //    cout << " ";
  138.  
  139.   if (parent != NULL)
  140.     output.push_back (getFullClassification () + ": " + description);
  141.  
  142.   for (int x = 0; x < children.size (); x++)
  143.     children[x]->printNode (indent + 2);
  144. }
  145.  
  146. bool MotifNode::selectRandom (int num)  {
  147. //  cout << "Selecting " << num << " random motifs.\n";
  148.   int x = num * 100;
  149. //  cout << "total story: " << x << endl;
  150.  
  151.   while (x > 0)  {
  152.     vector<MotifNode*> choices = getAvailable (vector<MotifNode*>());
  153.  
  154.     if (choices.empty ()) break;
  155.  
  156.     int totalRandom = 0;
  157.     for (int r = 0; r < choices.size (); r++)
  158.       totalRandom += choices[r]->randomWeight;
  159.  
  160.     int roll = rand () % totalRandom;
  161.     int index = 0;
  162.     int threshold = 0;
  163.    
  164.     for (int i = 0; i < choices.size (); i++)  {
  165.       threshold += choices[i]->randomWeight;
  166.       if (threshold > roll)  {
  167.         index = i;
  168.         break;
  169.       }
  170.     }
  171.  
  172. //    cout << "chose " << choices[index]->storyWeight << " worth of story"
  173. //         << endl;
  174.     choices[index]->choose ();
  175.    
  176.     x -= choices[index]->storyWeight;
  177. //    cout << x << " left to choose" << endl;
  178.   }
  179.  
  180.   return true;
  181. }
  182.  
  183. void MotifNode::resetAvailable ()  {
  184.   if (parent == NULL)
  185.     availability = CHOSEN;
  186.   else if (parent->availability == CHOSEN)
  187.     availability = AVAILABLE;
  188.   else availability = UNAVAILABLE;
  189.  
  190.   for (int x = 0; x < children.size (); x++)
  191.     children[x]->resetAvailable ();
  192. }
  193.  
  194. void MotifNode::printChosen ()  {
  195.   if (availability != CHOSEN)
  196.     return;
  197.  
  198.   if (parent != NULL)
  199.     output.push_back (description);
  200.  
  201.   for (int x = 0; x < children.size (); x++)
  202.     children[x]->printChosen ();
  203. }
  204.  
  205. void MotifNode::setRandomWeight (queue<string> cls, int weight)  {
  206.   if (cls.empty ())
  207.     randomWeight = weight;
  208.  
  209.   else if (cls.front () == "*")  {
  210.     cls.pop ();
  211.  
  212.     for (int x = 0; x < children.size (); x++)
  213.       children[x]->setRandomWeight (cls, weight);
  214.   }
  215.  
  216.   else for (int x = 0; x < children.size (); x++)
  217.     if (children[x]->classification == cls.front ())  {
  218.       cls.pop ();
  219.       children[x]->setRandomWeight (cls, weight);
  220.       break;
  221.     }
  222. }
  223.  
  224. void MotifNode::setStoryWeight (queue<string> cls, int weight)  {
  225.   if (cls.empty ())
  226.     storyWeight = weight;
  227.  
  228.   else if (cls.front () == "*")  {
  229.     cls.pop ();
  230.  
  231.     for (int x = 0; x < children.size (); x++)
  232.       children[x]->setStoryWeight (cls, weight);
  233.   }
  234.  
  235.   else for (int x = 0; x < children.size (); x++)
  236.     if (children[x]->classification == cls.front ())  {
  237.       cls.pop ();
  238.       children[x]->setStoryWeight (cls, weight);
  239.       break;
  240.     }
  241. }
  242.  
  243. void MotifNode::makeExclusive (vector< queue<string> > clslist)  {
  244.   vector<MotifNode*> nodelist;
  245.  
  246.   for (int x = 0; x < clslist.size (); x++)  {
  247.     vector<MotifNode*> tempnodelist =
  248.       classificationToPointer (clslist[x], vector<MotifNode*>());
  249.  
  250.     for (int t = 0; t < tempnodelist.size (); t++)
  251.       nodelist.push_back (tempnodelist[t]);
  252.   }
  253.  
  254.   for (int x = 0; x < nodelist.size (); x++)
  255.     for (int n = 0; n < nodelist.size (); n++)  {
  256.       if (nodelist[n] == NULL || x == n)
  257.         continue;
  258.       nodelist[x]->exclusiveWith.push_back (nodelist[n]);
  259.     }
  260. }
  261.  
  262. vector<MotifNode*> MotifNode::getAvailable (vector<MotifNode*> avail)  {  
  263.   if (availability == AVAILABLE)
  264.     avail.push_back (this);
  265.  
  266.   if (availability != UNAVAILABLE && availability != PERM_UNAVAILABLE)
  267.     for (int x = 0; x < children.size (); x++)
  268.       avail = children[x]->getAvailable (avail);
  269.  
  270.   return avail;
  271. }
  272.  
  273. string MotifNode::getFullClassification ()  {
  274.   if (parent == NULL)
  275.     return "";
  276.  
  277.   string cls = parent->getFullClassification ();
  278.   if (cls != "") cls += ".";
  279.  
  280.   return cls + classification;
  281. }
  282.  
  283. bool MotifNode::choose ()  {
  284. //  cout << "Choosing " << description << endl;
  285.  
  286.   availability = CHOSEN;
  287.  
  288.   for (int x = 0; x < children.size (); x++)
  289.     if (children[x]->availability != PERM_UNAVAILABLE)
  290.       children[x]->availability = AVAILABLE;
  291.  
  292.   for (int x = 0; x < exclusiveWith.size (); x++)
  293.     exclusiveWith[x]->availability = PERM_UNAVAILABLE;
  294.  
  295.   return true;
  296. }
  297.  
  298. vector<MotifNode*> MotifNode::classificationToPointer
  299.                            (queue<string> cls, vector<MotifNode*> nodelist)  {
  300.   if (cls.empty ())
  301.     nodelist.push_back (this);
  302.  
  303.   else if (cls.front () == "*")  {
  304.     cls.pop ();
  305.  
  306.     for (int x = 0; x < children.size (); x++)
  307.       nodelist = children[x]->classificationToPointer (cls, nodelist);
  308.   }
  309.  
  310.   else for (int x = 0; x < children.size (); x++)
  311.     if (children[x]->classification == cls.front ())  {
  312.       cls.pop ();
  313.       nodelist = children[x]->classificationToPointer (cls, nodelist);
  314.     }
  315.  
  316.   return nodelist;
  317. }
  318.  
  319. void readOptionsFile (string, MotifNode*);
  320. void readMotifFile (string, MotifNode*);
  321. void chooseRandomMotifs (MotifNode*);
  322. void finish ();
  323.  
  324. vector<string> tokenize (istream&, bool, int, ...);
  325. queue<string> tokenize (string, char);
  326.  
  327. int count = 10;
  328. string outFile = "out.txt";
  329. string errorFile = "error.txt";
  330.  
  331. int main (int argc, char *argv[])  {
  332.   srand (time (0));
  333.  
  334.   MotifNode *root = new MotifNode (NULL, "", "(Root)");
  335.  
  336.   readOptionsFile ("options.txt", root);
  337.  
  338.   output.push_back ("Printing a random collection of motifs:");
  339.   chooseRandomMotifs (root);
  340.  
  341.   finish ();
  342.  
  343.   return 0;
  344. }
  345.  
  346. void readOptionsFile (string filename, MotifNode *root)  {
  347.   if (root == NULL) return;
  348.  
  349.   ifstream optFile (filename.c_str ());
  350.  
  351.   if (optFile.fail ())  {
  352.     errors.push_back ("Error: could not read option file: " + filename);
  353.     return;
  354.   }
  355.  
  356.   errors.push_back ("Reading option file: " + filename);
  357.  
  358.   vector<string> subFiles;
  359.  
  360.   // parse filenames and count
  361.   vector<string> tokens = tokenize (optFile, true, 2, ' ');
  362.   for (; !tokens.empty (); tokens = tokenize (optFile, true, 2, ' '))  {
  363.     if (tokens[0] == "motif-file")
  364.       for (int x = 1; x < tokens.size (); x++)
  365.         readMotifFile (tokens[x], root);
  366.  
  367.     else if (tokens[0] == "options-file")
  368.       for (int x = 1; x < tokens.size (); x++)
  369.         subFiles.push_back (tokens[x]);
  370.  
  371.     else if (tokens[0] == "out-file")  {
  372.       if (tokens.size () > 1)
  373.         outFile = tokens[1];
  374.     }
  375.  
  376.     else if (tokens[0] == "error-file")  {
  377.       if (tokens.size () > 1)
  378.         errorFile = tokens[1];
  379.     }
  380.  
  381.     else if (tokens[0] == "count")  {
  382.       if (tokens.size () > 1)
  383.         count = atoi (tokens[1].c_str ());
  384.     }
  385.   }
  386.  
  387.   optFile.close ();
  388.  
  389.   for (int x = 0; x < subFiles.size (); x++)
  390.     readOptionsFile (subFiles[x], root);
  391.  
  392.   // read weights
  393.   optFile.open (filename.c_str ());
  394.  
  395.   if (optFile.fail ())  {
  396.     errors.push_back ("Error: could not reopen option file: " + filename);
  397.     return;
  398.   }
  399.  
  400.   tokens = tokenize (optFile, true, 2, ' ');
  401.   for (; !tokens.empty (); tokens = tokenize (optFile, true, 2, ' '))  {
  402.     if (tokens[0] == "weight")  {
  403.       if (tokens.size () != 3)  {
  404.         errors.push_back
  405.           ("Error: \"weight\" takes exactly two arguments (a classification and a weight)");
  406.         continue;
  407.       }
  408.  
  409.       queue<string> cls = tokenize (tokens[1], '.');
  410.       int weight = atoi (tokens[2].c_str ());
  411.  
  412.       root->setRandomWeight (cls, weight);
  413.     }
  414.  
  415.     else if (tokens[0] == "value")  {
  416.       if (tokens.size () != 3)  {
  417.         errors.push_back
  418.           ("Error: \"value\" takes exactly two arguments (a classification and a value)");
  419.         continue;
  420.       }
  421.  
  422.       queue<string> cls = tokenize (tokens[1], '.');
  423.       int weight = atoi (tokens[2].c_str ());
  424.  
  425.       root->setStoryWeight (cls, weight);
  426.     }
  427.  
  428.     else if (tokens[0] == "exclusive")  {
  429.       vector< queue<string> > clslist;
  430.  
  431.       for (int c = 1; c < tokens.size (); c++)
  432.         clslist.push_back (tokenize (tokens[c], '.'));
  433.  
  434.       root->makeExclusive (clslist);
  435.     }
  436.   }
  437. }
  438.  
  439. void readMotifFile (string filename, MotifNode *root)  {
  440.   if (root == NULL) return;
  441.  
  442.   ifstream motifFile (filename.c_str ());
  443.  
  444.   if (motifFile.fail ())  {
  445.     errors.push_back ("Error: could not open motif file");
  446.     return;
  447.   }
  448.  
  449.   errors.push_back ("Reading motif file: " + filename);
  450.  
  451.   vector<string> tokens = tokenize (motifFile, false, 2, ' ');
  452.   for (; !tokens.empty (); tokens = tokenize (motifFile, false, 2, ' '))  {
  453.     if (tokens.size () < 2)
  454.       errors.push_back ("Error: did not find description for " + tokens[0]);
  455.  
  456.     queue<string> cls = tokenize (tokens[0], '.');
  457.     string description = tokens.size () >= 2 ? tokens[1] : "";
  458.  
  459.     if (cls.size ())
  460.       root->insertNode (cls, description);
  461.     else errors.push_back ("Error: invalid classification: " + tokens[0]);
  462.   }
  463.  
  464.   motifFile.close ();
  465. }
  466.  
  467. void chooseRandomMotifs (MotifNode *root)  {
  468.   root->resetAvailable ();
  469.   root->selectRandom (count);
  470.   root->printChosen ();
  471. }
  472.  
  473. void finish ()  {
  474.   ofstream out (outFile.c_str (), ios_base::app);
  475.  
  476.   if (!out.fail ())
  477.     for (int x = 0; x < output.size (); x++)
  478.       out << output[x] << endl;
  479.  
  480.   out.close ();
  481.  
  482.   ofstream error (errorFile.c_str (), ios_base::out | ios_base::trunc);
  483.  
  484.   if (!error.fail ())
  485.     for (int x = 0; x < errors.size (); x++)
  486.       error << errors[x] << endl;
  487.  
  488.   error.close ();
  489. }
  490.  
  491. vector<string> tokenize (istream &in, bool cont, int num, ...)  {
  492.   vector<string> tokens;
  493.  
  494.   if (!in.good () || num < 1) return tokens;
  495.  
  496.   string line;
  497.   bool foundLine = false;
  498.  
  499.   // read lines until we find something tokenizable
  500.   while (in.good ())  {
  501.     line = "";
  502.     while (line == "" && in.good ()) // skip blank lines
  503.       getline (in, line, '\n');
  504.  
  505.     if (line == "") break;  // eof
  506.  
  507.     // comments are defined as lines where the first
  508.     // non-whitespace character is #
  509.     // we would also like to skip lines containing only whitespace
  510.     int firstChar = 0; // index of first non-whitespace
  511.  
  512.     while (firstChar < line.size ())  {
  513.       if (line[firstChar] == ' ' || line[firstChar] == '\t')
  514.         firstChar++;
  515.       else break;
  516.     }
  517.  
  518.     if (firstChar >= line.size ()) // line contains only whitespace
  519.       continue;
  520.  
  521.     if (line[firstChar] == '#')    // comment
  522.       continue;
  523.  
  524.     foundLine = true;
  525.     break;
  526.   }
  527.  
  528.   if (!foundLine)  // eof
  529.     return tokens;
  530.  
  531.   // tokenizing to a vector of size 1 is easy
  532.   if (num == 1)  {  
  533.     tokens.push_back (line);
  534.     return tokens;
  535.   }
  536.  
  537.   // tokenize!
  538.   va_list delimList;
  539.   va_start (delimList, num);
  540.   char current;  // last-used delimiter saved for later
  541.   int lastDelim = -1;  // index of last-used delimiter
  542.  
  543.   for (int x = 0; x < (num-1); x++)  {
  544.     // cstdarg doesn't like casting to char, so we cast to int first
  545.     current = va_arg (delimList, int);
  546.     int nextDelim = line.find (current, lastDelim+1);
  547.     string tok = line.substr (lastDelim+1, nextDelim-lastDelim-1);
  548.  
  549.     tokens.push_back (tok);
  550.  
  551.     lastDelim = nextDelim;
  552.  
  553.     // break if we didn't actually find the last delimiter
  554.     if (lastDelim == string::npos) break;
  555.   }
  556.  
  557.   va_end (delimList);
  558.  
  559.   // don't continue - we want exactly num tokens (or less)
  560.   if (!cont)  {
  561.     // add the final token, unless we've already run out of line
  562.     if (lastDelim != string::npos)
  563.       tokens.push_back (line.substr (lastDelim+1));
  564.     return tokens;
  565.   }
  566.  
  567.   // continue tokenizing using final delimiter until line is exhausted
  568.   while (lastDelim != string::npos)  {
  569.     int nextDelim = line.find (current, lastDelim+1);
  570.     string tok = line.substr (lastDelim+1, nextDelim-lastDelim-1);
  571.  
  572.     if (tok != "") tokens.push_back (tok);
  573.  
  574.     lastDelim = nextDelim;
  575.   }
  576.  
  577.   return tokens;
  578. }
  579.  
  580. queue<string> tokenize (string orig, char delim)  {
  581.   queue<string> tokens;
  582.  
  583.   int nextDelim = orig.find (delim);
  584.   int lastDelim = -1;
  585.  
  586.   do  {
  587.     string tok = orig.substr (lastDelim+1, nextDelim-lastDelim-1);
  588.     if (tok != "") tokens.push (tok);
  589.     lastDelim = nextDelim;
  590.     nextDelim = orig.find (delim, lastDelim+1);
  591.   } while (lastDelim != string::npos);
  592.  
  593.   return tokens;
  594. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement