5406 | | """ |
5407 | | return self.parent()(self._maxima_().fullratsimp()) |
| 5496 | |
| 5497 | With ``map=True`` each term in a sum is simplified separately |
| 5498 | and thus the resuls are shorter for functions which are |
| 5499 | combination of rational and nonrational funtions. In the |
| 5500 | following example, we use this option if we want not to |
| 5501 | combine logarithm and the rational function into one |
| 5502 | fraction:: |
| 5503 | |
| 5504 | sage: f=(x^2-1)/(x+1)-ln(x)/(x+2) |
| 5505 | sage: f.simplify_rational() |
| 5506 | (x^2 + x - log(x) - 2)/(x + 2) |
| 5507 | sage: f.simplify_rational(map=True) |
| 5508 | x - log(x)/(x + 2) - 1 |
| 5509 | |
| 5510 | With option ``method='noexpand'`` we only convert to common |
| 5511 | denominators and add. No expansion of products is performed:: |
| 5512 | |
| 5513 | sage: f=1/(x+1)+x/(x+2)^2 |
| 5514 | sage: f.simplify_rational() |
| 5515 | (2*x^2 + 5*x + 4)/(x^3 + 5*x^2 + 8*x + 4) |
| 5516 | sage: f.simplify_rational(method='noexpand') |
| 5517 | ((x + 1)*x + (x + 2)^2)/((x + 1)*(x + 2)^2) |
| 5518 | |
| 5519 | """ |
| 5520 | self_m = self._maxima_() |
| 5521 | if method == 'full': |
| 5522 | maxima_method = 'fullratsimp' |
| 5523 | elif method == 'simple': |
| 5524 | maxima_method = 'ratsimp' |
| 5525 | elif method == 'noexpand': |
| 5526 | maxima_method = 'xthru' |
| 5527 | else: |
| 5528 | raise NotImplementedError, "unknown method, see the help for available methods" |
| 5529 | P = self_m.parent() |
| 5530 | self_str=self_m.str() |
| 5531 | if map: |
| 5532 | cmd = "if atom(%s) then %s(%s) else map(%s,%s)"%(self_str,maxima_method,self_str,maxima_method,self_str) |
| 5533 | else: |
| 5534 | cmd = "%s(%s)"%(maxima_method,self_m.str()) |
| 5535 | res = P(cmd) |
| 5536 | return self.parent()(res) |
| 5638 | def simplify_log(self,method=None): |
| 5639 | r""" |
| 5640 | Simplifies symbolic expression, which can contain logs. |
| 5641 | |
| 5642 | Recursively scans the expression self, transforming |
| 5643 | subexpressions of the form a1*log(b1) + a2*log(b2) + c into |
| 5644 | log(b1^a1 * b2^a2) + c and simplifies inside logarithm. User |
| 5645 | can specify, which conditions must satisfy a1 and a2 to use |
| 5646 | this transformation in optional parameter ``method``. |
| 5647 | |
| 5648 | INPUT: |
| 5649 | |
| 5650 | - ``self`` - expression to be simplified |
| 5651 | |
| 5652 | - ``method`` - (default: None) optional, governs the condition |
| 5653 | on a1 and a2 which must be satisfied to contract expression |
| 5654 | a1*log(b1) + a2*log(b2). Values are |
| 5655 | |
| 5656 | - None (use Maxima default, integers), |
| 5657 | |
| 5658 | - 'one' (1 and -1), |
| 5659 | |
| 5660 | - 'ratios' (integers and fractions of integers), |
| 5661 | |
| 5662 | - 'constants' (constants), |
| 5663 | |
| 5664 | - 'all' (all expressions). |
| 5665 | |
| 5666 | See also examples below. |
| 5667 | |
| 5668 | DETAILS: This uses the Maxima logcontract() command. From the |
| 5669 | Maxima documentation: "Recursively scans the expression expr, |
| 5670 | transforming subexpressions of the form a1*log(b1) + |
| 5671 | a2*log(b2) + c into log(ratsimp(b1^a1 * b2^a2)) + c. The user |
| 5672 | can control which coefficients are contracted by setting the |
| 5673 | option logconcoeffp to the name of a predicate function of one |
| 5674 | argument. E.g. if you like to generate SQRTs, you can do |
| 5675 | logconcoeffp:'logconfun$ logconfun(m):=featurep(m,integer) or |
| 5676 | ratnump(m)$ . Then logcontract(1/2*log(x)); will give |
| 5677 | log(sqrt(x))." |
| 5678 | |
| 5679 | ALIAS: :meth:`log_simplify` and :meth:`log_simplify` are the |
| 5680 | same |
| 5681 | |
| 5682 | EXAMPLES:: |
| 5683 | |
| 5684 | sage: x,y,t=var('x y t') |
| 5685 | |
| 5686 | Only two first terms are contracted in the following example , |
| 5687 | the logarithm with coefficient 1/2 is not contracted:: |
| 5688 | |
| 5689 | sage: f = log(x)+2*log(y)+1/2*log(t) |
| 5690 | sage: f.simplify_log() |
| 5691 | log(x*y^2) + 1/2*log(t) |
| 5692 | |
| 5693 | To contract all terms in previous example use option ``method``:: |
| 5694 | |
| 5695 | sage: f.simplify_log(method='ratios') |
| 5696 | log(sqrt(t)*x*y^2) |
| 5697 | |
| 5698 | This shows that the option ``method`` from the previous call |
| 5699 | has no influence to future calls (we changed some default |
| 5700 | Maxima flag and have to ensure, that this flag has been |
| 5701 | restored):: |
| 5702 | |
| 5703 | sage: f.simplify_log('one') |
| 5704 | 1/2*log(t) + log(x) + 2*log(y) |
| 5705 | |
| 5706 | sage: f.simplify_log('ratios') |
| 5707 | log(sqrt(t)*x*y^2) |
| 5708 | |
| 5709 | sage: f.simplify_log() |
| 5710 | log(x*y^2) + 1/2*log(t) |
| 5711 | |
| 5712 | To contract terms with no coefficient (more preciselly, with |
| 5713 | coefficients 1 and -1) use option ``method``:: |
| 5714 | |
| 5715 | sage: f = log(x)+2*log(y)-log(t) |
| 5716 | sage: f.simplify_log('one') |
| 5717 | 2*log(y) + log(x/t) |
| 5718 | |
| 5719 | :: |
| 5720 | |
| 5721 | sage: f = log(x)+log(y)-1/3*log((x+1)) |
| 5722 | sage: f.simplify_log() |
| 5723 | -1/3*log(x + 1) + log(x*y) |
| 5724 | |
| 5725 | sage: f.simplify_log('ratios') |
| 5726 | log(x*y/(x + 1)^(1/3)) |
| 5727 | |
| 5728 | `\pi` is irrational number, to contract logarithms in the following example |
| 5729 | we have to put ``method`` to ``constants`` or ``all``:: |
| 5730 | |
| 5731 | sage: f = log(x)+log(y)-pi*log((x+1)) |
| 5732 | sage: f.simplify_log('constants') |
| 5733 | log(x*y/(x + 1)^pi) |
| 5734 | |
| 5735 | x*log(9) is contracted only if ``method`` is ``all``:: |
| 5736 | |
| 5737 | sage: (x*log(9)).simplify_log() |
| 5738 | x*log(9) |
| 5739 | sage: (x*log(9)).simplify_log('all') |
| 5740 | log(9^x) |
| 5741 | |
| 5742 | TESTS:: |
| 5743 | |
| 5744 | This shows that the issue at trac #7344 is fixed:: |
| 5745 | |
| 5746 | sage: (log(sqrt(2)-1)+log(sqrt(2)+1)).simplify_full() |
| 5747 | 0 |
| 5748 | |
| 5749 | AUTHORS: |
| 5750 | |
| 5751 | - Robert Marik (11-2009) |
| 5752 | """ |
| 5753 | from sage.calculus.calculus import maxima |
| 5754 | maxima.eval('domain: real$ savelogexpand:logexpand$ logexpand:false$') |
| 5755 | if method is not None: |
| 5756 | maxima.eval('logconcoeffp:\'logconfun$') |
| 5757 | if method == 'ratios': |
| 5758 | maxima.eval('logconfun(m):= featurep(m,integer) or ratnump(m)$') |
| 5759 | elif method == 'one': |
| 5760 | maxima.eval('logconfun(m):= is(m=1) or is(m=-1)$') |
| 5761 | elif method == 'constants': |
| 5762 | maxima.eval('logconfun(m):= constantp(m)$') |
| 5763 | elif method == 'all': |
| 5764 | maxima.eval('logconfun(m):= true$') |
| 5765 | elif method is not None: |
| 5766 | raise NotImplementedError, "unknown method, see the help for available methods" |
| 5767 | res = self.parent()(self._maxima_().logcontract()) |
| 5768 | maxima.eval('domain: complex$') |
| 5769 | if method is not None: |
| 5770 | maxima.eval('logconcoeffp:false$') |
| 5771 | maxima.eval('logexpand:savelogexpand$') |
| 5772 | return res |
| 5773 | |
| 5774 | log_simplify = simplify_log |
| 5775 | |
| 5776 | def expand_log(self,method='products'): |
| 5777 | r""" |
| 5778 | Simplifies symbolic expression, which can contain logs. |
| 5779 | |
| 5780 | Expands logarithms of powers, logarithms of products and |
| 5781 | logarithms of quotients. the option ``mehotd`` tells, which |
| 5782 | expression should be expanded. |
| 5783 | |
| 5784 | INPUT: |
| 5785 | |
| 5786 | - ``self`` - expression to be simplified |
| 5787 | |
| 5788 | - ``method`` - (default: 'product') optional, governs which |
| 5789 | expression is expanded. Possible values are |
| 5790 | |
| 5791 | - 'nothing' (no expansion), |
| 5792 | |
| 5793 | - 'powers' (log(a^r) is expanded), |
| 5794 | |
| 5795 | - 'products' (like 'powers' and also log(a*b) are expanded), |
| 5796 | |
| 5797 | - 'all' (all possible expansion). |
| 5798 | |
| 5799 | See also examples below. |
| 5800 | |
| 5801 | DETAILS: This uses the Maxima simplifier and sets |
| 5802 | ``logexpand`` option for this simplifier. From the Maxima |
| 5803 | documentation: "Logexpand:true causes log(a^b) to become |
| 5804 | b*log(a). If it is set to all, log(a*b) will also simplify to |
| 5805 | log(a)+log(b). If it is set to super, then log(a/b) will also |
| 5806 | simplify to log(a)-log(b) for rational numbers a/b, |
| 5807 | a#1. (log(1/b), for integer b, always simplifies.) If it is |
| 5808 | set to false, all of these simplifications will be turned |
| 5809 | off. " |
| 5810 | |
| 5811 | ALIAS: :meth:`log_expand` and :meth:`expand(log)` are the same |
| 5812 | |
| 5813 | EXAMPLES:: |
| 5814 | |
| 5815 | By default powers and products (and quotients) are expanded, |
| 5816 | but not quotients of integers:: |
| 5817 | |
| 5818 | sage: (log(3/4*x^pi)).log_expand() |
| 5819 | pi*log(x) + log(3/4) |
| 5820 | |
| 5821 | To expand also log(3/4) use ``method='all'``:: |
| 5822 | |
| 5823 | sage: (log(3/4*x^pi)).log_expand('all') |
| 5824 | pi*log(x) + log(3) - log(4) |
| 5825 | |
| 5826 | To expand only the power use ``method='powers'``.:: |
| 5827 | |
| 5828 | sage: (log(x^6)).log_expand('powers') |
| 5829 | 6*log(x) |
| 5830 | |
| 5831 | The expression ``log((3*x)^6)`` is not expanded with |
| 5832 | ``method='powers'``, since it is converted into product |
| 5833 | first:: |
| 5834 | |
| 5835 | sage: (log((3*x)^6)).log_expand('powers') |
| 5836 | log(729*x^6) |
| 5837 | |
| 5838 | |
| 5839 | AUTHORS: |
| 5840 | |
| 5841 | - Robert Marik (11-2009) |
| 5842 | """ |
| 5843 | from sage.calculus.calculus import maxima |
| 5844 | maxima.eval('domain: real$') |
| 5845 | if method == 'nothing': |
| 5846 | maxima_method='false' |
| 5847 | elif method == 'powers': |
| 5848 | maxima_method='true' |
| 5849 | elif method == 'products': |
| 5850 | maxima_method='all' |
| 5851 | elif method == 'all': |
| 5852 | maxima_method='super' |
| 5853 | else: |
| 5854 | raise NotImplementedError, "unknown method, see the help for available methods" |
| 5855 | self_m = self._maxima_() |
| 5856 | res = self_m.ev("logexpand:%s"%maxima_method) |
| 5857 | res = res.sage() |
| 5858 | maxima.eval('domain: complex$') |
| 5859 | return res |
| 5860 | |
| 5861 | log_expand = expand_log |
| 5862 | |