COPASI API  4.16.103
CNormalProduct.cpp
Go to the documentation of this file.
1 // Begin CVS Header
2 // $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/compareExpressions/CNormalProduct.cpp,v $
3 // $Revision: 1.24 $
4 // $Name: $
5 // $Author: ssahle $
6 // $Date: 2012/04/22 14:51:18 $
7 // End CVS Header
8 
9 // Copyright (C) 2012 by Pedro Mendes, Virginia Tech Intellectual
10 // Properties, Inc., University of Heidelberg, and The University
11 // of Manchester.
12 // All rights reserved.
13 
14 // Copyright (C) 2008 by Pedro Mendes, Virginia Tech Intellectual
15 // Properties, Inc., EML Research, gGmbH, University of Heidelberg,
16 // and The University of Manchester.
17 // All rights reserved.
18 
19 // Copyright (C) 2001 - 2007 by Pedro Mendes, Virginia Tech Intellectual
20 // Properties, Inc. and EML Research, gGmbH.
21 // All rights reserved.
22 
23 #ifdef WIN32
24 # pragma warning (disable: 4786)
25 # pragma warning (disable: 4243)
26 // warning C4355: 'this' : used in base member initializer list
27 # pragma warning (disable: 4355)
28 #endif // WIN32
29 
30 #include <set>
31 #include <cmath>
32 #include <sstream>
33 
34 #include "copasi.h"
35 
36 #include "CNormalSum.h"
37 #include "CNormalLcm.h"
38 #include "CNormalItem.h"
39 #include "CNormalItemPower.h"
40 #include "CNormalProduct.h"
41 #include "CNormalFunction.h"
42 #include "CNormalGeneralPower.h"
43 #include "CNormalChoice.h"
44 #include "CNormalFraction.h"
45 
46 bool compareItemPowers::operator()(const CNormalItemPower* itemPower1, const CNormalItemPower* itemPower2)
47 {
48  return *itemPower1 < *itemPower2;
49 }
50 
51 /**
52  * Default constructor
53  */
55 {}
56 
57 /**
58  * Copy contructor
59  */
60 CNormalProduct::CNormalProduct(const CNormalProduct& src): CNormalBase(src), mFactor(src.mFactor)
61 {
62  std::set<CNormalItemPower*, compareItemPowers >::const_iterator it;
63  std::set<CNormalItemPower*, compareItemPowers >::const_iterator itEnd = src.mItemPowers.end();
64  const CNormalItemPower* pSrcItemPower = NULL;
65  CNormalItemPower* pDestItemPower = NULL;
66 
67  for (it = src.mItemPowers.begin(); it != itEnd; ++it)
68  {
69  pSrcItemPower = *it;
70  pDestItemPower = new CNormalItemPower(*pSrcItemPower);
71  bool result = this->mItemPowers.insert(pDestItemPower).second;
72  assert(result == true);
73  }
74 }
75 
76 /**
77  * Assignment operator
78  */
80 {
81  mFactor = src.mFactor;
82  std::set<CNormalItemPower*, compareItemPowers >::const_iterator it;
83  std::set<CNormalItemPower*, compareItemPowers >::const_iterator itEnd = src.mItemPowers.end();
84 
85  for (it = src.mItemPowers.begin(); it != itEnd; ++it)
86  mItemPowers.insert(new CNormalItemPower(**it));
87 
88  return *this;
89 }
90 
91 /**
92  * Destructor
93  */
95 {
96  std::set<CNormalItemPower*, compareItemPowers >::const_iterator it;
97  std::set<CNormalItemPower*, compareItemPowers >::const_iterator itEnd = mItemPowers.end();
98 
99  for (it = mItemPowers.begin(); it != itEnd; ++it)
100  delete *it;
101 }
102 
103 /**
104  * Set the factor for this product.
105  * @return true.
106  */
108 {
109  mFactor = number;
110 
111  if (fabs(mFactor) < 1.0E-100)
112  {
113  std::set<CNormalItemPower*, compareItemPowers>::iterator it = mItemPowers.begin(), endit = mItemPowers.end();
114 
115  while (it != endit)
116  {
117  delete *it;
118  ++it;
119  }
120 
121  mItemPowers.clear();
122  //mPowers.clear();
123  }
124 
125  return true;
126 }
127 
128 /**
129  * Multiply this product with a number.
130  * @return true.
131  */
133 {
134  mFactor = mFactor * number;
135 
136  if (fabs(mFactor) < 1.0E-100)
137  {
138  std::set<CNormalItemPower*, compareItemPowers>::iterator it = mItemPowers.begin(), endit = mItemPowers.end();
139 
140  while (it != endit)
141  {
142  delete *it;
143  ++it;
144  }
145 
146  mItemPowers.clear();
147  //mPowers.clear();
148  }
149 
150  return true;
151 }
152 
153 /**
154  * Multiply an choice to this product.
155  * @return true.
156  */
158 {
159  if (fabs(mFactor) < 1.0E-100)
160  return true;
161 
162  std::set <CNormalItemPower*, compareItemPowers >::const_iterator it;
163  std::set <CNormalItemPower*, compareItemPowers >::const_iterator itEnd = mItemPowers.end();
164 
165  for (it = mItemPowers.begin(); it != itEnd; ++it)
166  {
167  if ((*it)->getItem().areEqual(choice) == true)
168  {
169  (*it)->setExp((*it)->getExp() + 1.0);
170  return true;
171  }
172  }
173 
174  CNormalItemPower* tmp = new CNormalItemPower(choice, 1.0);
175  mItemPowers.insert(tmp);
176  return true;
177 }
178 
179 /**
180  * Multiply an item to this product.
181  * @return true.
182  */
184 {
185  if (fabs(mFactor) < 1.0E-100)
186  return true;
187 
188  std::set <CNormalItemPower*, compareItemPowers >::const_iterator it;
189  std::set <CNormalItemPower*, compareItemPowers >::const_iterator itEnd = mItemPowers.end();
190 
191  for (it = mItemPowers.begin(); it != itEnd; ++it)
192  {
193  if ((*it)->getItem().areEqual(pow) == true)
194  {
195  (*it)->setExp((*it)->getExp() + 1.0);
196  return true;
197  }
198  }
199 
200  CNormalItemPower* tmp = new CNormalItemPower(pow, 1.0);
201  mItemPowers.insert(tmp);
202  return true;
203 }
204 
205 /**
206  * Multiply an item to this product.
207  * @return true.
208  */
210 {
211  if (fabs(mFactor) < 1.0E-100)
212  return true;
213 
214  std::set <CNormalItemPower*, compareItemPowers >::const_iterator it;
215  std::set <CNormalItemPower*, compareItemPowers >::const_iterator itEnd = mItemPowers.end();
216 
217  for (it = mItemPowers.begin(); it != itEnd; ++it)
218  {
219  if ((*it)->getItem().areEqual(fun) == true)
220  {
221  (*it)->setExp((*it)->getExp() + 1.0);
222  return true;
223  }
224  }
225 
226  CNormalItemPower* tmp = new CNormalItemPower(fun, 1.0);
227  mItemPowers.insert(tmp);
228  return true;
229 }
230 
231 /**
232  * Multiply an item to this product.
233  * @return true.
234  */
236 {
237  if (fabs(mFactor) < 1.0E-100)
238  return true;
239 
240  std::set <CNormalItemPower*, compareItemPowers >::const_iterator it;
241  std::set <CNormalItemPower*, compareItemPowers >::const_iterator itEnd = mItemPowers.end();
242 
243  for (it = mItemPowers.begin(); it != itEnd; ++it)
244  {
245  if ((*it)->getItem().areEqual(item) == true)
246  {
247  (*it)->setExp((*it)->getExp() + 1.0);
248  return true;
249  }
250  }
251 
252  CNormalItemPower* tmp = new CNormalItemPower(item, 1.0);
253  mItemPowers.insert(tmp);
254  return true;
255 }
256 
257 /**
258  * Multiply an itempower to this product.
259  * @return true.
260  */
262 {
263  if (fabs(mFactor) < 1.0E-100)
264  return true;
265 
266  std::set <CNormalItemPower*, compareItemPowers >::const_iterator it;
267  std::set <CNormalItemPower*, compareItemPowers >::const_iterator itEnd = mItemPowers.end();
268 
269  for (it = mItemPowers.begin(); it != itEnd; ++it)
270  {
271  if ((*it)->getItem().areEqual(itemPower.getItem()))
272  {
273  (*it)->setExp((*it)->getExp() + itemPower.getExp());
274  return true;
275  }
276  }
277 
278  CNormalItemPower* tmp = new CNormalItemPower(itemPower);
279  mItemPowers.insert(tmp);
280  return true;
281 }
282 
283 /**
284  * Multiply a list of itempowers to this product.
285  * @return true.
286  */
287 bool CNormalProduct::multiply(const std::set <CNormalItemPower*, compareItemPowers >& itemPowers)
288 {
289  if (fabs(mFactor) < 1.0E-100)
290  return true;
291 
292  std::set <CNormalItemPower*, compareItemPowers >::const_iterator it;
293  std::set <CNormalItemPower*, compareItemPowers >::const_iterator itEnd = itemPowers.end();
294 
295  for (it = itemPowers.begin(); it != itEnd; ++it)
296  multiply(**it);
297 
298  return true;
299 }
300 
301 /**
302  * Remove an itempower from this product, provided it is a factor of it.
303  * @return true.
304  */
305 bool CNormalProduct::remove(std::set<CNormalItemPower*, compareItemPowers >::iterator it)
306 {
307  delete(*it);
308  mItemPowers.erase(it);
309  return true;
310 }
311 
312 /**
313  * Remove an itempower from this product, provided it is a factor of it.
314  * -used in multiplication with lcm-
315  * @return true.
316  */
318 {
319  std::set <CNormalItemPower*, compareItemPowers >::iterator it;
320  std::set <CNormalItemPower*, compareItemPowers >::iterator itEnd = mItemPowers.end();
321 
322  for (it = mItemPowers.begin(); it != itEnd; ++it)
323  {
324  if ((*it)->getItem().areEqual(itemPower.getItem()))
325  {
326  C_FLOAT64 dif = (*it)->getExp() - itemPower.getExp();
327 
328  if (dif >= 1.0E-100)
329  {
330  (*it)->setExp(dif);
331  return true;
332  }
333 
334  if (fabs(dif) < 1.0E-100)
335  {
336  delete(*it);
337  mItemPowers.erase(it);
338  return true;
339  }
340 
341  return false;
342  }
343  }
344 
345  return false;
346 }
347 
348 /**
349  * Multiply this product with another product.
350  * @return true
351  */
353 {
354  multiply(product.getFactor());
355 
356  if (fabs(mFactor) < 1.0E-100)
357  return true;
358 
359  multiply(product.getItemPowers());
360  return true;
361 }
362 
363 /**
364  * Multiply this product with a sum NOT CONTAINING FRACTIONS!.
365  * @return sum.
366  */
368 {
369  if (fabs(mFactor) < 1.0E-100)
370  {
371  CNormalSum* zeroSum = new CNormalSum();
372  zeroSum->add(*this);
373  return zeroSum;
374  }
375 
376  CNormalSum* tmp = new CNormalSum(sum);
377  CNormalSum* newsum = new CNormalSum();
378  std::set<CNormalProduct*, compareProducts>::const_iterator it;
379  std::set<CNormalProduct*, compareProducts>::const_iterator itEnd = tmp->getProducts().end();
380 
381  for (it = tmp->getProducts().begin(); it != itEnd; ++it)
382  {
383  (*it)->multiply(*this);
384  newsum->add(**it);
385  }
386 
387  delete tmp;
388  return newsum;
389 }
390 
391 /**
392  * Multiply this product with a lcm.
393  * @return true
394  */
396 {
397  if (fabs(mFactor) < 1.0E-100)
398  {
399  CNormalSum* zeroSum = new CNormalSum();
400  zeroSum->add(*this);
401  return zeroSum;
402  }
403 
404  CNormalLcm* tmp = new CNormalLcm(lcm);
405  multiply(tmp->getItemPowers());
406  CNormalSum* sum = new CNormalSum();
407  sum->add(*this);
408  std::vector<CNormalSum*>::const_iterator it;
409  std::vector<CNormalSum*>::const_iterator itEnd = tmp->getSums().end();
410 
411  for (it = tmp->getSums().begin(); it != itEnd; ++it)
412  {
413  sum->multiply(**it);
414  }
415 
416  delete tmp;
417  return sum;
418 }
419 
420 /**
421  * Retrieve the factor of this product.
422  * @return mFactor.
423  */
425 {
426  return mFactor;
427 }
428 
429 /**
430  * Retrieve the set of itempowers of this product.
431  * @return mItemPowers.
432  */
433 const std::set <CNormalItemPower*, compareItemPowers >& CNormalProduct::getItemPowers() const
434 {
435  return mItemPowers;
436 }
437 
439 {
440  if (mItemPowers.size() != rhs.mItemPowers.size())
441  return false;
442 
443  std::set< CNormalItemPower*, compareItemPowers >::const_iterator it;
444  std::set< CNormalItemPower*, compareItemPowers >::const_iterator itEnd = mItemPowers.end();
445  std::set< CNormalItemPower*, compareItemPowers >::const_iterator it2;
446  //std::set< CNormalItemPower*, compareItemPowers >::const_iterator it2End = rhs.mItemPowers.end();
447 
448  for (it = mItemPowers.begin(), it2 = rhs.mItemPowers.begin(); it != itEnd; ++it, ++it2)
449  {
450  if (!(**it == **it2))
451  return false;
452  }
453 
454  return true;
455 }
456 
458 {
459  if (mFactor != rhs.mFactor)
460  return false;
461 
462  if (checkSamePowerList(rhs))
463  return true;
464 
465  return false;
466 }
467 
468 std::ostream & operator<< (std::ostream &os, const CNormalProduct & d)
469 {
470  os << d.toString();
471  return os;
472 }
473 
474 std::string CNormalProduct::toString() const
475 {
476  std::ostringstream os;
477  bool firstFactor = true;
478 
479  if ((fabs(this->mFactor - 1.0) >= 1.0E-100) || (this->mItemPowers.size() == 0))
480  {
481  if (this->mFactor < 0.0)
482  os << "(" << this->mFactor << ")";
483  else
484  {
485  os.precision(18);
486  os << this->mFactor;
487  }
488 
489  firstFactor = false;
490  }
491 
492  std::set <CNormalItemPower*, compareItemPowers >::const_iterator it;
493  std::set <CNormalItemPower*, compareItemPowers >::const_iterator itEnd = this->mItemPowers.end();
494 
495  for (it = this->mItemPowers.begin(); it != itEnd; ++it)
496  {
497  if (firstFactor == false)
498  os << " * ";
499 
500  os << **it;
501  firstFactor = false;
502  }
503 
504  return os.str();
505 }
506 
508 {
509  return new CNormalProduct(*this);
510 }
511 
513 {
514  bool result = false;
515 
516  if (this->mFactor < rhs.mFactor)
517  {
518  result = true;
519  }
520  else if (this->mFactor == rhs.mFactor)
521  {
522  if (this->mItemPowers.size() < rhs.mItemPowers.size())
523  {
524  result = true;
525  }
526  else if (this->mItemPowers.size() == rhs.mItemPowers.size())
527  {
528  std::set<CNormalItemPower*, compareItemPowers >::const_iterator it = this->mItemPowers.begin(), endit = this->mItemPowers.end();
529  std::set<CNormalItemPower*, compareItemPowers >::const_iterator it2 = rhs.mItemPowers.begin();
530  compareItemPowers comp;
531 
532  while (result == false && it != endit)
533  {
534  if (comp(*it, *it2))
535  {
536  result = true;
537  }
538 
539  if (comp(*it2, *it))
540  {
541  break;
542  }
543 
544  ++it;
545  ++it2;
546  }
547  }
548  }
549 
550  return result;
551 }
552 
553 void CNormalProduct::setItemPowers(const std::set<CNormalItemPower*, compareItemPowers>& set)
554 {
555  std::set<CNormalItemPower*, compareItemPowers>::const_iterator it = this->mItemPowers.begin(), endit = this->mItemPowers.end();
556 
557  while (it != endit)
558  {
559  delete *it;
560  ++it;
561  }
562 
563  it = set.begin(), endit = set.end();
564  this->mItemPowers.clear();
565 
566  while (it != endit)
567  {
568  this->mItemPowers.insert(new CNormalItemPower(**it));
569  ++it;
570  }
571 }
572 
574 {
575  bool result = true;
576  // don't work on the items in the set directly
577  // make a copy, otherwise the set will be messed up
578  std::set<CNormalItemPower*, compareItemPowers> itemPowersCopy(this->mItemPowers);
579  std::set<CNormalItemPower*, compareItemPowers>::iterator it = itemPowersCopy.begin(), endit = itemPowersCopy.end();
580  CNormalItemPower* pTmpItemPower = NULL;
581  this->mItemPowers.clear();
582 
583  while (it != endit && result == true)
584  {
585  pTmpItemPower = *it;
586  result = pTmpItemPower->simplify();
587 
588  if (result)
589  {
590  this->multiply(*pTmpItemPower);
591  }
592 
593  delete pTmpItemPower;
594  ++it;
595  }
596 
597  // we should combine all general power items of type power into
598  // one large general power item which is again simplified
599  // this we only do if the CNormalItemPower parent has an exponent of 1
600  it = this->mItemPowers.begin();
601  endit = this->mItemPowers.end();
602  std::vector<CNormalItemPower*> tmpV;
603  // create a unit CNormalItemPower with one unit CNormalGeneralPower
604  // and an exponent of 1
605  CNormalGeneralPower* pGeneralPower = NULL; //CNormalGeneralPower::createUnitGeneralPower();
606 
607  while (it != endit)
608  {
609  if ((*it)->getExp() == 1.0 && (*it)->getItemType() == CNormalItemPower::POWER &&
610  dynamic_cast<CNormalGeneralPower*>(&(*it)->getItem())->getType() == CNormalGeneralPower::POWER
611  &&
612  dynamic_cast<CNormalGeneralPower*>(&(*it)->getItem())->getRight().checkIsOne()
613  )
614  {
615  if (pGeneralPower)
616  {
617  pGeneralPower->multiply(*static_cast<CNormalGeneralPower*>(&(*it)->getItem()));
618  }
619  else
620  {
621  pGeneralPower = static_cast<CNormalGeneralPower*>(&(*it)->getItem());
622  pGeneralPower = new CNormalGeneralPower(*pGeneralPower);
623  }
624 
625  delete *it;
626  }
627  else
628  {
629  if ((*it)->getItemType() == CNormalItemPower::POWER &&
630  dynamic_cast<CNormalGeneralPower*>(&(*it)->getItem())->getType() == CNormalGeneralPower::POWER &&
631  dynamic_cast<CNormalGeneralPower*>(&(*it)->getItem())->getLeft().checkIsOne()
632  )
633  {
634  delete *it;
635  }
636  else
637  {
638  tmpV.push_back(*it);
639  }
640  }
641 
642  ++ it;
643  }
644 
645  if (pGeneralPower && !pGeneralPower->checkIsOne())
646  {
647  CNormalItemPower* pTmpItemPower = new CNormalItemPower();
648  pTmpItemPower->setExp(1.0);
649  pTmpItemPower->setItem(*pGeneralPower);
650  tmpV.push_back(pTmpItemPower);
651  }
652 
653  delete pGeneralPower;
654  // clear the current set of items and add all the item in tmpV
655  this->mItemPowers.clear();
656  std::vector<CNormalItemPower*>::iterator vIt = tmpV.begin();
657  std::vector<CNormalItemPower*>::iterator vEndIt = tmpV.end();
658 
659  while (vIt != vEndIt)
660  {
661  this->multiply(**vIt);
662  delete *vIt;
663  ++vIt;
664  }
665 
666  return result;
667 }
668 
670 {
671  // go though all items that are general powers and check for general items
672  // of type power that have denominators in their base that differ from 1
673  // from all those denominators create a common denoninator and return it
674 
675  // first we generate a general power that is 1
678  CNormalSum* pTmpSum = new CNormalSum();
679  CNormalFraction* pTmpFrac = new CNormalFraction();
680  CNormalProduct* pTmpProduct = new CNormalProduct();
681  pTmpSum->add(*pTmpProduct);
682  delete pTmpProduct;
683  pTmpFrac->setNumerator(*pTmpSum);
684  pTmpFrac->setDenominator(*pTmpSum);
685  pResult->setLeft(*pTmpFrac);
686  pResult->setRight(*pTmpFrac);
687  delete pTmpFrac;
688  std::set<CNormalItemPower*, compareItemPowers>::const_iterator it = this->mItemPowers.begin(), endit = this->mItemPowers.end();
689 
690  while (it != endit)
691  {
692  if ((*it)->getItemType() == CNormalItemPower::POWER)
693  {
694  CNormalGeneralPower* pTmpPow = dynamic_cast<CNormalGeneralPower*>(&(*it)->getItem());
695  assert(pTmpPow != NULL);
696 
697  // only set the numerator to 1 if it is a power item and the
698  // denominator is not 1
699  if (pTmpPow->getType() == CNormalGeneralPower::POWER && !pTmpPow->getLeft().checkDenominatorOne())
700  {
701  // set the numerator to 1
702  pTmpPow = new CNormalGeneralPower(*pTmpPow);
703  pTmpPow->getLeft().setNumerator(*pTmpSum);
704  pResult->multiply(*pTmpPow);
705  delete pTmpPow;
706  }
707  }
708 
709  ++it;
710  }
711 
712  delete pTmpSum;
713  return pResult;
714 }
715 
717 {
718  // goes through all items and sets the denominators of the bases of all
719  // general power items of type power to one
720  CNormalSum* pTmpSum = new CNormalSum();
721  CNormalProduct* pTmpProduct = new CNormalProduct();
722  pTmpSum->add(*pTmpProduct);
723  delete pTmpProduct;
724  std::set<CNormalItemPower*, compareItemPowers>::iterator it = this->mItemPowers.begin(), endit = this->mItemPowers.end();
725 
726  while (it != endit)
727  {
728  if ((*it)->getItemType() == CNormalItemPower::POWER)
729  {
730  CNormalGeneralPower* pGenPow = dynamic_cast<CNormalGeneralPower*>(&(*it)->getItem());
731  assert(pGenPow != NULL);
732 
733  // only set the denominator to 1 if it is a power item
734  if (pGenPow->getType() == CNormalGeneralPower::POWER)
735  {
736  pGenPow->getLeft().setDenominator(*pTmpSum);
737  }
738  }
739 
740  ++it;
741  }
742 
743  delete pTmpSum;
744 }
745 
747 {
748  return new CNormalProduct();
749 }
C_FLOAT64 mFactor
static CNormalProduct * createUnitProduct()
virtual std::string toString() const
std::ostream & operator<<(std::ostream &os, const CNormalProduct &d)
CNormalFraction & getLeft()
virtual bool simplify()
const std::vector< CNormalSum * > & getSums() const
Definition: CNormalLcm.cpp:275
virtual bool simplify()
void multiply(const CNormalGeneralPower &generalPower)
CNormalGeneralPower * getDenominator() const
std::set< CNormalItemPower *, compareItemPowers > mItemPowers
bool add(const CNormalProduct &product)
Definition: CNormalSum.cpp:156
bool setItem(const CNormalBase &item)
virtual ~CNormalProduct()
bool setDenominator(const CNormalSum &denominator)
const std::set< CNormalItemPower *, compareItemPowers > & getItemPowers() const
bool operator<(const CNormalProduct &rhs) const
bool setFactor(const C_FLOAT64 &number)
const C_FLOAT64 & getExp() const
virtual CNormalBase * copy() const
const C_FLOAT64 & getFactor() const
void setRight(const CNormalFraction &right)
const CArrayAnnotation * pResult
bool checkDenominatorOne() const
bool setNumerator(const CNormalSum &numerator)
bool checkSamePowerList(const CNormalProduct &rhs) const
void setItemPowers(const std::set< CNormalItemPower *, compareItemPowers > &set)
CNormalProduct & operator=(const CNormalProduct &src)
#define C_FLOAT64
Definition: copasi.h:92
void setLeft(const CNormalFraction &left)
CNormalBase & getItem()
bool operator()(const CNormalItemPower *itemPower1, const CNormalItemPower *itemPower2)
bool multiply(const C_FLOAT64 &number)
bool remove(std::set< CNormalItemPower *, compareItemPowers >::iterator it)
const std::set< CNormalProduct *, compareProducts > & getProducts() const
Definition: CNormalSum.cpp:416
const std::set< CNormalItemPower *, compareItemPowers > & getItemPowers() const
Definition: CNormalLcm.cpp:266
bool setExp(const C_FLOAT64 &number)
bool operator==(const CNormalProduct &rhs) const