COPASI API  4.16.103
CNormalFraction.cpp
Go to the documentation of this file.
1 // Begin CVS Header
2 // $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/compareExpressions/CNormalFraction.cpp,v $
3 // $Revision: 1.17 $
4 // $Name: $
5 // $Author: ssahle $
6 // $Date: 2012/04/22 14:51:17 $
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 <vector>
31 #include <cmath>
32 #include <sstream>
33 
34 #include "copasi.h"
35 
36 #include "CNormalProduct.h"
37 #include "CNormalSum.h"
38 #include "CNormalLcm.h"
39 #include "CNormalItemPower.h"
40 #include "CNormalFraction.h"
41 //#include "CNormalLogical.h"
42 //#include "CNormalChoice.h"
43 
44 /**
45  * Default constructor
46  */
47 CNormalFraction::CNormalFraction(): CNormalBase(), mpNumerator(new CNormalSum()), mpDenominator(new CNormalSum()) {}
48 
49 /**
50  * Copy contructor
51  */
53  mpNumerator(new CNormalSum(*src.mpNumerator)),
54  mpDenominator(new CNormalSum(*src.mpDenominator)) {}
55 
56 /**
57  * Assignment operator
58  */
60 {
61  if (this->mpNumerator != NULL) delete this->mpNumerator;
62 
63  if (this->mpDenominator != NULL) delete this->mpDenominator;
64 
65  this->mpNumerator = new CNormalSum(*src.mpNumerator);
66  this->mpDenominator = new CNormalSum(*src.mpDenominator);
67  return *this;
68 }
69 
71 {
72  if (mpNumerator != NULL) delete mpNumerator;
73 
74  if (mpDenominator != NULL) delete mpDenominator;
75 }
76 
77 /**
78  * Set numerator of this fraction
79  * @return true.
80  */
82 {
83  if (mpNumerator != NULL)
84  {
85  delete mpNumerator;
86  }
87 
88  mpNumerator = new CNormalSum(numerator);
89  return true;
90 }
91 
92 /**
93  * Set denominator of this fraction.
94  * @return true.
95  */
97 {
98  if (mpDenominator != NULL)
99  {
100  delete mpDenominator;
101  }
102 
103  mpDenominator = new CNormalSum(denominator);
104 
105  if (mpDenominator->getSize() == 0)
106  return false;
107 
108  return true;
109 }
110 
111 /**
112  * Check if the denominator of this fraction equals 1.
113  * @return bool
114  */
116 {
117  return this->mpNumerator->checkIsOne();
118 }
119 
120 /**
121  * Check if the denominator of this fraction equals 1.
122  * @return bool
123  */
125 {
126  return this->mpDenominator->checkIsOne();
127 }
128 
129 /**
130  * Set the denominator of this fraction equal 1.
131  * @return true.
132  */
134 {
135  CNormalProduct* product = new CNormalProduct();
136  CNormalSum* sum = new CNormalSum();
137  sum->add(*product);
138  delete product;
139  setDenominator(*sum);
140  delete sum;
141  return true;
142 }
143 
144 /**
145  * Retrieve the numerator of this fraction.
146  * @return mpNumerator.
147  */
149 {
150  return *mpNumerator;
151 }
152 
153 /**
154  * Retrieve the denominator of this fraction.
155  * @return mpDenominator.
156  */
158 {
159  return *mpDenominator;
160 }
161 
162 /**
163  * Retrieve the numerator of this fraction.
164  * @return mpNumerator.
165  */
167 {
168  return *mpNumerator;
169 }
170 
171 /**
172  * Retrieve the denominator of this fraction.
173  * @return mpDenominator.
174  */
176 {
177  return *mpDenominator;
178 }
179 
180 /**
181  * Check if this fraction contains further fractions.
182  * @return bool.
183  */
185 {
186  if (mpNumerator->getFractions().size() + mpDenominator->getFractions().size() == 0)
187  return false;
188 
189  return true;
190 }
191 
192 /**
193  * Expand this fraction by a lcm.
194  * @return true.
195  */
197 {
198  mpNumerator->multiply(lcm);
199  mpDenominator->multiply(lcm);
200 
201  if (mpDenominator->getSize() == 0)
202  return false;
203 
204  return true;
205 }
206 
207 /**
208  * Cancel common items of mpNumerator and mpDenominator.
209  * @return true.
210  */
212 {
213  if (mpNumerator->getProducts().size() != 0 || mpNumerator->getFractions().size() != 0 || mpDenominator->getProducts().size() != 0 || mpDenominator->getFractions().size() != 0)
214  {
215  if (*mpDenominator == *mpNumerator)
216  {
219  return true;
220  }
221 
222  if (mpDenominator->getProducts().size() != 0)
223  {
224  C_FLOAT64 factor = (*mpDenominator->getProducts().begin())->getFactor();
225 
226  if (fabs(factor) < 1.0E-100)
227  return false;
228  else
229  {
230  mpNumerator->multiply(1.0 / factor); //factor != 0 as checked earlier
231  mpDenominator->multiply(1.0 / factor);
232  }
233  }
234 
235  if (checkForFractions() == false)
236  {
237  if (mpDenominator->getProducts().size() != 0 && (*mpDenominator->getProducts().begin())->getItemPowers().size() != 0)
238  {
239  std::set<CNormalItemPower*, compareItemPowers >::const_iterator it = (*mpDenominator->getProducts().begin())->getItemPowers().begin();
240  std::set<CNormalItemPower*, compareItemPowers >::const_iterator itEnd = (*mpDenominator->getProducts().begin())->getItemPowers().end();
241  std::vector<CNormalItemPower*> tmpV;
242 
243  while (it != itEnd)
244  {//runs through all item powers in the first product of the denominator
245  C_FLOAT64 exp = mpNumerator->checkFactor(**it);
246 
247  if (fabs(exp) >= 1.0E-100)
248  {
249  exp = mpDenominator->checkFactor(**it) < exp ? mpDenominator->checkFactor(**it) : exp;
250 
251  if (fabs(exp) >= 1.0E-100)
252  {
253  CNormalItemPower* itemPower = new CNormalItemPower((*it)->getItem(), exp);
254  tmpV.push_back(itemPower);
255  }
256  }
257 
258  ++it;
259  }
260 
261  std::vector<CNormalItemPower*>::iterator it2 = tmpV.begin();
262  std::vector<CNormalItemPower*>::iterator itEnd2 = tmpV.end();
263 
264  while (it2 != itEnd2)
265  {
266  mpNumerator->divide(**it2);
267  mpDenominator->divide(**it2);
268  delete *it2;
269  ++it2;
270  }
271  }
272  }
273  }
274 
275  return true;
276 }
277 
278 /**
279  * Multiply this fraction with a number.
280  * @return true.
281  */
283 {
284  mpNumerator->multiply(number);
285 
286  if (mpNumerator->getSize() == 0)
288 
289  return true;
290 }
291 
292 /**
293  * Multiply a fraction with an itempower.
294  * @return true.
295  */
297 {
298  C_FLOAT64 exp = mpDenominator->checkFactor(itemPower);
299  C_FLOAT64 tmpExp;
300 
301  if (fabs(exp) >= 1.0E-100)
302  {
303  CNormalItemPower* pTmp1 = new CNormalItemPower(itemPower.getItem(), exp);
304  mpDenominator->divide(*pTmp1);
305  delete pTmp1;
306 
307  if ((tmpExp = fabs(itemPower.getExp() - exp)) >= 1.0E-100)
308  {
309  // :TODO: Memory leak?
310  CNormalItemPower * pTmp2 =
311  new CNormalItemPower(itemPower.getItem(), tmpExp);
312  mpNumerator->multiply(*pTmp2);
313  delete pTmp2;
314  return true;
315  }
316 
317  return true;
318  }
319  else
320  mpNumerator->multiply(itemPower);
321 
322  return true;
323 }
324 
325 /**
326  * Find lcm of denominators of respective fractions contained in this fraction.
327  * @return pointer to lcm.
328  */
330 {
331  CNormalLcm* lcm = new CNormalLcm();
332 
333  std::set<CNormalFraction*>::const_iterator it;
334  std::set<CNormalFraction*>::const_iterator itEnd = mpNumerator->getFractions().end();
335 
336  for (it = mpNumerator->getFractions().begin(); it != itEnd; ++it)
337  {
338  lcm->add((*it)->getDenominator());
339  }
340 
341  std::set<CNormalFraction*>::const_iterator it2;
342  std::set<CNormalFraction*>::const_iterator it2End = mpDenominator->getFractions().end();
343 
344  for (it2 = mpDenominator->getFractions().begin(); it2 != it2End; ++it2)
345  {
346  lcm->add((*it2)->getDenominator());
347  }
348 
349  return lcm;
350 }
351 
352 /**
353  * Multiply this fraction by a lcm.
354  * @return CNormalSum*, pointer to result of multiplication ie. a normal sum.
355  * This fraction is useless now.
356  */
358 {
359  if (mpDenominator->getFractions().size() != 0)
360  {
361  return NULL;
362  }
363 
364  if (lcm.remove(*mpDenominator) == false)
365  {
366  return NULL;
367  }
368 
369  mpNumerator->multiply(lcm);
370  CNormalSum * sum = new CNormalSum(*mpNumerator);
371  return sum;
372 }
373 
374 /**
375  * Check if numerator and denominator contain fractions,
376  * find lcm of respective denominators, expand this fraction by lcm and cancel.
377  * @return true
378  */
380 {
381  bool result = true;
382  result = this->mpNumerator->simplify();
383 
384  if (result == true)
385  {
386  result = this->mpDenominator->simplify();
387  }
388 
389  if (result == true)
390  {
391  if (mpNumerator->getFractions().size() + mpDenominator->getFractions().size() > 0)
392  {
393  // TODO the following code does not work if there are fractions left.
394  const CNormalLcm* lcm = findLcm();
395  assert(expand(*lcm) == true);
396  delete lcm;
397  }
398  }
399 
400  cancel();
401  return result;
402 }
403 
405 {
406  if ((*mpNumerator == *rhs.mpNumerator) && (*mpDenominator == *rhs.mpDenominator))
407  return true;
408  else
409  return false;
410 }
411 
412 std::ostream & operator<< (std::ostream &os, const CNormalFraction & d)
413 {
414  os << d.toString();
415  return os;
416 }
417 
418 std::string CNormalFraction::toString() const
419 {
420  std::ostringstream os;
421 
422  if (this->checkDenominatorOne() == true)
423  {
424  os << *this->mpNumerator;
425  }
426  else
427  {
428  os << "(" << *this->mpNumerator << ")/(" << *this->mpDenominator << ")";
429  }
430 
431  return os.str();
432 }
433 
435 {
436  return new CNormalFraction(*this);
437 }
438 
440 {
441  bool result = false;
442 
443  if ((*this->mpNumerator) < (*src.mpNumerator))
444  {
445  result = true;
446  }
447  else if ((*this->mpNumerator) == (*src.mpNumerator))
448  {
449  if ((*this->mpDenominator) < (*src.mpDenominator))
450  {
451  result = true;
452  }
453  }
454 
455  return result;
456 }
457 
458 /*
459 std::set<const CNormalLogical*> CNormalFraction::findLogicals() const
460 {
461  std::set<const CNormalLogical*> set;
462  std::set<CNormalProduct*>::const_iterator it=this->mpDenominator->getProducts().begin();
463  std::set<CNormalProduct*>::const_iterator endit=this->mpDenominator->getProducts().end();
464  while(it!=endit)
465  {
466  std::set<CNormalItemPower*,compareItemPowers>::const_iterator it2=(*it)->getItemPowers().begin();
467  std::set<CNormalItemPower*,compareItemPowers>::const_iterator endit2=(*it)->getItemPowers().end();
468  while(it2!=endit2)
469  {
470  if((*it2)->getItemType()==CNormalItemPower::CHOICE)
471  {
472  const CNormalChoice* pChoice=dynamic_cast<const CNormalChoice*>(&(*it2)->getItem());
473  const CNormalLogical* pLogical=&pChoice->getCondition();
474  set.insert(pLogical);
475  std::set<const CNormalLogical*> tmpSet=pLogical->findLogicals();
476  set.insert(tmpSet.begin(),tmpSet.end());
477  }
478  else if((*it2)->getItemType()==CNormalItemPower::FUNCTION)
479  {
480  }
481  else if((*it2)->getItemType()==CNormalItemPower::POWER)
482  {
483  }
484  ++it2;
485  }
486  ++it;
487  }
488  it=this->mpNumerator->getProducts().begin();
489  endit=this->mpNumerator->getProducts().end();
490  while(it!=endit)
491  {
492  std::set<CNormalItemPower*,compareItemPowers>::const_iterator it2=(*it)->getItemPowers().begin();
493  std::set<CNormalItemPower*,compareItemPowers>::const_iterator endit2=(*it)->getItemPowers().end();
494  while(it2!=endit2)
495  {
496  if((*it2)->getItemType()==CNormalItemPower::CHOICE)
497  {
498  const CNormalChoice* pChoice=dynamic_cast<const CNormalChoice*>(&(*it2)->getItem());
499  const CNormalLogical* pLogical=&pChoice->getCondition();
500  set.insert(pLogical);
501  std::set<const CNormalLogical*> tmpSet=pLogical->findLogicals();
502  set.insert(tmpSet.begin(),tmpSet.end());
503  }
504  else if((*it2)->getItemType()==CNormalItemPower::FUNCTION)
505  {
506  }
507  else if((*it2)->getItemType()==CNormalItemPower::POWER)
508  {
509  }
510  ++it2;
511  }
512  ++it;
513  }
514  return set;
515 }
516  */
517 
519 {
520  // the fraction is one if numerator and denominator are equal
521  return ((*mpNumerator) == (*mpDenominator));
522 }
523 
525 {
526  // the fraction is 0.0 if the numerator is 0.0
527  return this->mpNumerator->checkIsZero();
528 }
529 
531 {
532  CNormalFraction* pFraction = new CNormalFraction();
533  delete pFraction->mpNumerator;
534  delete pFraction->mpDenominator;
535  pFraction->mpNumerator = CNormalSum::createUnitSum();
537  return pFraction;
538 }
virtual bool simplify()
virtual bool simplify()
Definition: CNormalSum.cpp:623
CNormalSum & getNumerator()
bool checkIsOne() const
int getSize() const
Definition: CNormalSum.cpp:147
bool remove(const CNormalItemPower &itemPower)
Definition: CNormalLcm.cpp:176
bool multiply(const C_FLOAT64 &number)
bool checkForFractions() const
virtual CNormalBase * copy() const
bool checkNumeratorOne() const
bool add(const CNormalItemPower &itemPower)
Definition: CNormalLcm.cpp:105
bool operator<(const CNormalFraction &src) const
bool operator==(const CNormalFraction &rhs) const
bool add(const CNormalProduct &product)
Definition: CNormalSum.cpp:156
C_FLOAT64 checkFactor(const CNormalItemPower &itemPower) const
Definition: CNormalSum.cpp:382
virtual ~CNormalFraction()
static CNormalFraction * createUnitFraction()
CNormalFraction & operator=(const CNormalFraction &src)
const std::set< CNormalFraction * > & getFractions() const
Definition: CNormalSum.cpp:425
CNormalSum * mpNumerator
bool divide(const CNormalItemPower &itemPower)
Definition: CNormalSum.cpp:371
CNormalSum & getDenominator()
bool setDenominator(const CNormalSum &denominator)
bool checkIsZero() const
const C_FLOAT64 & getExp() const
std::ostream & operator<<(std::ostream &os, const CNormalFraction &d)
bool checkDenominatorOne() const
CNormalSum * mpDenominator
bool setNumerator(const CNormalSum &numerator)
virtual std::string toString() const
#define C_FLOAT64
Definition: copasi.h:92
bool checkIsOne() const
Definition: CNormalSum.cpp:850
bool checkIsZero() const
Definition: CNormalSum.cpp:874
CNormalBase & getItem()
static CNormalSum * createUnitSum()
Definition: CNormalSum.cpp:889
const CNormalLcm * findLcm() const
const std::set< CNormalProduct *, compareProducts > & getProducts() const
Definition: CNormalSum.cpp:416
bool expand(const CNormalLcm &lcm)
bool multiply(const C_FLOAT64 &number)
Definition: CNormalSum.cpp:249