home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / graphtal / productn.c < prev    next >
C/C++ Source or Header  |  1992-10-19  |  4KB  |  162 lines

  1. /*
  2.  * Production.C - methods for L-System productions.
  3.  *
  4.  * Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
  5.  * All rights reserved.
  6.  *
  7.  * This software may be freely copied, modified, and redistributed
  8.  * provided that this copyright notice is preserved on all copies.
  9.  *
  10.  * You may not distribute this software, in whole or in part, as part of
  11.  * any commercial product without the express consent of the authors.
  12.  *
  13.  * There is no warranty or other guarantee of fitness of this software
  14.  * for any purpose.  It is provided solely "as is".
  15.  *
  16.  */
  17.  
  18. #include <stdlib.h>
  19. #include "Production.h"
  20. #include "Error.h"
  21.  
  22. implementList(SuccessorList, SuccessorPtr);
  23. implementList(ProductionList, ProductionPtr);
  24.  
  25. //___________________________________________________________ Predecessor
  26.  
  27. Predecessor::Predecessor(const Name& n, NameList* param)
  28. : name(n), formalParam(param)
  29. {}
  30.  
  31. Predecessor::~Predecessor()
  32. {
  33.   if (formalParam) {
  34.     for (long i=0; i<formalParam->count(); i++)
  35.       delete formalParam->item(i);
  36.     delete formalParam;
  37.   }
  38. }
  39.  
  40. //___________________________________________________________ Successor
  41.  
  42. Successor::Successor(double p, ProdModuleList* m)
  43. : modules(m), _probability(p)
  44. {}
  45.  
  46. Successor::~Successor()
  47. {
  48.   if (modules) {
  49.     for (long i=0; i<modules->count(); i++)
  50.       delete modules->item(i);
  51.     delete modules;
  52.   }
  53. }
  54.  
  55. // make a ModuleList out of the ProdModuleList of the successor
  56. ModuleList* Successor::clone()
  57. {
  58.   ModuleList* retval;
  59.   if (modules) {
  60.     retval = new ModuleList(modules->count());
  61.     for (register long i=0; i<modules->count(); i++)
  62.       retval->append(new Module(modules->item(i)));
  63.   }
  64.   else
  65.     retval = new ModuleList;
  66.  
  67.   return retval;
  68. }
  69.  
  70. ostream& operator<<(ostream& os, Successor& s)
  71. {
  72.   os << "-> (" << s.probability() << ") ";
  73.   if (s.modules)
  74.     for (long i=0; i<s.modules->count(); i++)
  75.       os << *s.modules->item(i) << " ";
  76.   else
  77.     os << "(empty)";
  78.  
  79.   return os;
  80. }
  81.  
  82. //___________________________________________________________ Production
  83.  
  84. Production::Production(Predecessor* p, Expression* c, SuccessorList* s)
  85. : _name(p->name), predecessor(p), condition(c), successors(s)
  86. {
  87.   arg_count = (p->formalParam) ? (int)p->formalParam->count()
  88.                                : 0;
  89.   stochastic = (successors->count() > 1);
  90. }
  91.  
  92. Production::~Production()
  93. {
  94.   delete  predecessor;
  95.   if (condition) delete condition;
  96.  
  97.   for (long i=0; i<successors->count(); i++)
  98.     delete successors->item(i);
  99.   delete successors;
  100. }
  101.  
  102. // choose a successor out of the successor list and clone it
  103. ModuleList* Production::cloneSuccessor()
  104. {
  105.   // if we have more than one successor, choose by random
  106.   if (stochastic) {
  107.     double p = drand48();
  108.     for (register long i=0; i<successors->count(); i++)
  109.       if (p <= successors->item(i)->probability())
  110.     return successors->item(i)->clone();
  111.  
  112.     // No successor choosen. VERY, VERY BAD!
  113.     Error(ERR_PANIC, "cloneSuccessor: no successor choosen");
  114.     return NULL;
  115.   }  
  116.   else
  117.     return successors->item(0)->clone();
  118. }
  119.  
  120. // The probabilities of the successor must cumulate to 1. In addition
  121. //  a preprocessing is done, e.g.:
  122. //    A -> (0.5) B    =>  A -> (0.5) B
  123. //      -> (0.5) C          -> (1.0) C
  124. //  => no arithmetic operation has to be performed will choosing a
  125. //     successor
  126. int Production::cumulateProbability()
  127. {
  128.   double sum = 0.0;
  129.  
  130.   for (long i=0; i<successors->count(); i++) {
  131.     sum += successors->item(i)->probability();
  132.     successors->item(i)->probability() = sum;
  133.   }
  134.   return ((sum > 1.01) ? 1 : 0);
  135. }
  136.  
  137. int Production::hashValue()
  138. {
  139.   extern unsigned int modHash(const char*, long);
  140.   return modHash((const char*)_name, (long)arg_count);
  141. }
  142.  
  143. ostream& operator<<(ostream& os, Production& p)
  144. {
  145.   long i;
  146.  
  147.   os << p.predecessor->name;
  148.   if (p.predecessor->formalParam) {
  149.     os << '(';
  150.     for (i=0; i<p.predecessor->formalParam->count()-1; i++)
  151.       os << *p.predecessor->formalParam->item(i) << ", ";
  152.     os << *p.predecessor->formalParam->item(i) << ")";
  153.   }
  154.   if (p.condition) os << " : " << *p.condition << ' ';
  155.  
  156.   for (i=0; i<p.successors->count()-1; i++)
  157.     os << *p.successors->item(i) << "\n\t";
  158.   os << *p.successors->item(i) << '\n';
  159.   
  160.   return os;
  161. }
  162.