How to Incorporate a numerical prefactor into a radical in Maxima? - numerical

(%i2) x : expand(cosh(1)*sqrt(3+5*t));
(%o2) cosh(1) sqrt(5 t + 3)
(%i3) expand(float(x));
0.5
(%o3) 1.543080634815244 (5.0 t + 3.0)
How can I get Maxima to incorporate the prefactor into the radical? I'm looking for something that in this case yields something like
0.5
(%o3) (11.90548922 t + 7.143293537)
For numbers as small as these this is not a big deal, but for numerical evaluations Maxima tends to substitute rational approximations that may involve very large denominators, so that I end up with expressions where the prefactor is a very small number (like 6.35324353 × 10-23) and the numbers inside the square root are very large numbers (like 5212548545863256475196584785455844385452665612552468), so that it isn't obvious even what the order of magnitude of the result is.

Here's a solution which uses pattern matching.
(%i1) matchdeclare (cc, numberp, [bb, aa], all) $
(%i2) defrule (r1f, cc*bb^0.5, foof(cc,bb));
0.5
(%o2) r1f : bb cc -> foof(cc, bb)
(%i3) defrule (r2f, aa*cc*bb^0.5, aa*foof(cc,bb));
0.5
(%o3) r2f : aa bb cc -> aa foof(cc, bb)
(%i4) foof(a,b):= (expand(a^2*b))^0.5 $
(%i5) apply1 (1.543080634815244*(5.0*t + 3.0)^0.5, r1f, r2f);
0.5
(%o5) (11.90548922770908 t + 7.143293536625449)
(%i6) apply1 (1.543080634815244*x*y*(5.0*t + 3.0)^0.5, r1f, r2f);
0.5
(%o6) (11.90548922770908 t + 7.143293536625449) x y
(%i7) apply1 (1/(1 + 345.43*(2.23e-2*u + 8.3e-4)^0.5), r1f, r2f);
1
(%o7) --------------------------------------------
0.5
(2660.87803327 u + 99.03716446700001) + 1
It took some experimentation to figure out suitable rules r1f and r2f. Note that these rules match ...^0.5 but not sqrt(...) (i.e. exponent = 1/2 instead of 0.5). Of course if you want to match sqrt(...) you can create additional rules for that.
Not guaranteed to work for you -- a rule might match too much or too little. It's worth a try, anyway.

Related

How to get the mid of 2 int32 number elegantly without overflow?

In some conditions like Segment Tree or Binary Search, I have to get the average value of 2 number.
An easy solution is mid = (a + b) / 2. But when it comes to a and b have the same plus-minus signs, The a + b thing will overflow. For example, 1234567 + 2147483647, -1234567 + (-2147483647) in int32 type.
I searched online and got to know mid = (b - a) / 2 + a, it can avoid the situation above, but still not perfect. When it comes to a and b have the different plus-minus signs, mid = (a + b) / 2 won't overflow but (b - a) / 2 + a will. For example, -2147483648 + 2147483647 in int32 type.
To thoroughly solve this problem, I've written the code in pic below. I divide the 2 situations by the plus-minus signs. (I use some bit operations to improve its efficiency.) But it is way too complex for such a simple problem, right?
Is there some elegant solution to this problem?
I tried to divide the problem to 2 situations and solve them respectively.
But I still want a more elegant solution.
Got the answer!
mid = (a & b) + ((a ^ b) >> 1)
a & b keeps the same bits that a and b have in common, they need not to be distributed averagely. Like when you find the average value of 102 and 110, you don't need to calculate the 100 they have in common. You can just keep that, and deal with the 2 and 10 part, distribute them averagely to 2 number. As (102 + 110) / 2 = (2 * 100 + 2 + 10) / 2 = 100 + (2 + 10) / 2 = 100 + 6 = 106.
(a ^ b) >> 1 deals with the "2 and 10 part", it gets all the bits that a and b don't have in common, and divide it by 2.
Adds up 2 parts above so we get the average value of a and b. Not a strict proof, though.

Numerically stable evaluation of sqrt(x+a) - sqrt(x)

Is there an elegant way of numerically stable evaluating the following expression for the full parameter range x,a >= 0?
f(x,a) = sqrt(x+a) - sqrt(x)
Also is there any programming language or library that does provide this kind of function? If yes, under what name? I have no specific problem using the above expression right now, but encountered it many times in the past and always thought that this problem must have been solved before!
Yes, there is! Provided that at least one of x and a is positive, you can use:
f(x, a) = a / (sqrt(x + a) + sqrt(x))
which is perfectly numerically stable, but hardly worth a library function in its own right. Of course, when x = a = 0, the result should be 0.
Explanation: sqrt(x + a) - sqrt(x) is equal to (sqrt(x + a) - sqrt(x)) * (sqrt(x + a) + sqrt(x)) / (sqrt(x + a) + sqrt(x)). Now multiply the first two terms to get sqrt(x+a)^2 - sqrt(x)^2, which simplifies to a.
Here's an example demonstrating the stability: the troublesome case for the original expression is where x + a and x are very close in value (or equivalently when a is much smaller in magnitude than x). For example, if x = 1 and a is small, we know from a Taylor expansion around 1 that sqrt(1 + a) should be 1 + a/2 - a^2/8 + O(a^3), so sqrt(1 + a) - sqrt(1) should be close to a/2 - a^2/8. Let's try that for a particular choice of small a. Here's the original function (written in Python, in this case, but you can treat it as pseudocode):
def f(x, a):
return sqrt(x + a) - sqrt(x)
and here's the stable version:
def g(x, a):
if a == 0:
return 0.0
else:
return a / ((sqrt(x + a) + sqrt(x))
Now let's see what we get with x = 1 and a = 2e-10:
>>> a = 2e-10
>>> f(1, a)
1.000000082740371e-10
>>> g(1, a)
9.999999999500001e-11
The value we should have got is (up to machine accuracy): a/2 - a^2/8 - for this particular a, the cubic and higher order terms are insignificant in the context of IEEE 754 double-precision floats, which only provide around 16 decimal digits of precision. Let's compute that value for comparison:
>>> a/2 - a**2/8
9.999999999500001e-11

How to calculate the explicit form of a recursive function?

I have this recursive function:
f(n) = 2 * f(n-1) + 3 * f(n-2) + 4
f(1) = 2
f(2) = 8
I know from experience that explicit form of it would be:
f(n) = 3 ^ n - 1 // pow(3, n) - 1
I wanna know if there's any way to prove that. I googled a bit, yet didn't find anything simple to understand. I already know that generation functions probably solve it, they're too complex, I'd rather not get into them. I'm looking for a simpler way.
P.S.
If it helps I remember something like this solved it:
f(n) = 2 * f(n-1) + 3 * f(n-2) + 4
// consider f(n) = x ^ n
x ^ n = 2 * x ^ (n-1) + 3 * x ^ (n-2) + 4
And then you somehow computed x that lead to explicit form of the recursive formula, yet I can't quite remember
f(n) = 2 * f(n-1) + 3 * f(n-2) + 4
f(n+1) = 2 * f(n) + 3 * f(n-1) + 4
f(n+1)-f(n) = 2 * f(n) - 2 * f(n-1) + 3 * f(n-1) - 3 * f(n-2)
f(n+1) = 3 * f(n) + f(n-1) - 3 * f(n-2)
Now the 4 is gone.
As you said the next step is letting f(n) = x ^ n
x^(n+1) = 3 * x^n + x^(n-1) - 3 * x^(n-2)
divide by x^(n-2)
x^3 = 3 * x^2 + x - 3
x^3 - 3 * x^2 - x + 3 = 0
factorise to find x
(x-3)(x-1)(x+1) = 0
x = -1 or 1 or 3
f(n) = A * (-1)^n + B * 1^n + C * 3^n
f(n) = A * (-1)^n + B + C * 3^n
Now find A,B and C using the values you have
f(1) = 2; f(2) = 8; f(3) = 26
f(1) = 2 = -A + B + 3C
f(2) = 8 = A + B + 9C
f(3) = 26 = -A + B + 27C
solving for A,B and C:
f(3)-f(1) = 24 = 24C => C = 1
f(2)-f(1) = 6 = 2A + 6 => A = 0
2 = B + 3 => B = -1
Finally
f(n) = 3^n - 1
Ok, I know you didn't want generating functions (GF from now on) and all the complicated stuff, but my problem turned out to be nonlinear and simple linear methods didn't seem to work. So after a full day of searching, I found the answer and hopefully these findings will be of help to others.
My problem: a[n+1]= a[n]/(1+a[n]) (i.e. not linear (nor polynomial), but also not completely nonlinear - it is a rational difference equation)
if your recurrence is linear (or polynomial), wikihow has step-by-step instructions (with and without GF)
if you want to read something about GF, go to this wiki, but I didn't get it till I started doing examples (see next)
GF usage example on Fibonacci
if the previous example didn't make sense, download GF book and read the simplest GF example (section 1.1, ie a[n+1]= 2 a[n]+1, then 1.2, a[n+1]= 2 a[n]+1, then 1.3 - Fibonacci)
(while I'm on the book topic) templatetypedef mentioned Concrete Mathematics, download here, but I don't know much about it except it has a recurrence, sums, and GF chapter (among others) and a table of simple GFs on page 335
as I dove deeper for nonlinear stuff, I saw this page, using which I failed at z-transforms approach and didn't try linear algebra, but the link to rational difference eqn was the best (see next step)
so as per this page, rational functions are nice because you can transform them into polynomials and use linear methods of step 1. 3. and 4. above, which I wrote out by hand and probably made some mistake, because (see 8)
Mathematica (or even the free WolframAlpha) has a recurrence solver, which with RSolve[{a[n + 1] == a[n]/(1 + a[n]), a[1] == A}, a[n], n] got me a simple {{a[n] -> A/(1 - A + A n)}}. So I guess I'll go back and look for mistake in hand-calculations (they are good for understanding how the whole conversion process works).
Anyways, hope this helps.
In general, there is no algorithm for converting a recursive form into an iterative one. This problem is undecidable. As an example, consider this recursive function definition, which defines the Collatz sequence:
f(1) = 0
f(2n) = 1 + f(n)
f(2n + 1) = 1 + f(6n + 4)
It's not known whether or not this is even a well-defined function or not. Were an algorithm to exist that could convert this into a closed-form, we could decide whether or not it was well-defined.
However, for many common cases, it is possible to convert a recursive definition into an iterative one. The excellent textbook Concrete Mathematics spends much of its pages showing how to do this. One common technique that works quite well when you have a guess of what the answer is is to use induction. As an example for your case, suppose that you believe that your recursive definition does indeed give 3^n - 1. To prove this, try proving that it holds true for the base cases, then show that this knowledge lets you generalize the solution upward. You didn't put a base case in your post, but I'm assuming that
f(0) = 0
f(1) = 2
Given this, let's see whether your hunch is correct. For the specific inputs of 0 and 1, you can verify by inspection that the function does compute 3^n - 1. For the inductive step, let's assume that for all n' < n that f(n) = 3^n - 1. Then we have that
f(n) = 2f(n - 1) + 3f(n - 2) + 4
= 2 * (3^{n-1} - 1) + 3 * (3^{n-2} - 1) + 4
= 2 * 3^{n-1} - 2 + 3^{n-1} - 3 + 4
= 3 * 3^{n-1} - 5 + 4
= 3^n - 1
So we have just proven that this recursive function does indeed produce 3^n - 1.

PageRank problem

I am embarrassed to ask such question; but I haven't use math for a long time I can not recall many concepts learned many years ago.
In the url http://www.javadev.org/files/Ranking.pdf, an example is used for illustrate the page rank mechanism. The relation between page A, B, and C is A links to B and C, B links to C, and C links to A. So the PageRank equation is as below
Equation A)
PR(A) = 0.5 + 0.5 PR(C)
PR(B) = 0.5 + 0.5 (PR(A) / 2)
PR(C) = 0.5 + 0.5 (PR(A) / 2 + PR(B))
and it comes up with the result
Result B)
PR(A) = 14/13 = 1.07692308
PR(B) = 10/13 = 0.76923077
PR(C) = 15/13 = 1.15384615
My question is how Result B is derived from Equation A?
I try e.g. replacing PR(C) in equation PR(A)
PR(A) = 0.5 + 0.5 (0.5 + 0.5 (PR(A) / 2 + PR(B)))
this seems to end up with an infinite loop. So I am confused how it can derive the result e.g. PR(A) value is 1.07692308?
Appologize for such stupid question.
I appreciate any advice.
Not a stupid question, you're just rusty.
Take your equation and multiply by 16 (not really necessary, but it makes things look nicer):
16 PR(A) = 12 + 2 PR(A) + 4 PR(B)
Now subtract 2 PR(A) from both sides:
14 PR(A) = 12 + 4 PR(B)
Now replace PR(B), using the second part of "equation A":
14 PR(A) = 12 + 2 + PR(A)
13 PR(A) = 14
PR(A) = 14/13
And the others follow the same way. If you find that an equation winds up being the same on both sides (X = X), it probably means that you did the same substitution twice; just back up and try again. With a little practice you'll get the hang of it.

WolframAlpha: Solve Multiple Functions

I'm trying to use WolframAlpha to solve for a variable.
I have
u(k, r) = (900-3k)r^(k-1)
and
s(n, r) = sum u(k, r), k=1 to n
and I want to solve for r with
s(5000, r) = -600000000000
I've tried various incantations, but can't seem to get it working. I can't even get s defined to evaluate it.
If you care, it is to solve this problem : http://projecteuler.net/index.php?section=problems&id=235
WARNING: Spoiler below!
You should ask WA to FullSimplify the expression of s(n,r) after you substitute u(k,r) into it. It should give
(3 (299 - 300 r + r^n (-299 + n + 300 r - n r)))/(-1 + r)^2
Solving the final equality is then just finding the root of a (high degree) polynomial:
299 + 200000000000 (-1 + r)^2 + (4701 - 4700 r) r^5000 == 300 r
where r != 1 since that was a pole of the original expression. Note that r must be positive so that the positive quadratic gets negated by the high-degree term. Plotting the function shows that It is positive for r < 1, and negative for r >~ 1, so the solution is somewhere past r=1. Now change variables so that x = r-1 and look near x=0:
200000000000 x^2 + (1 + x)^5000 (1 - 4700 x) - 1 - 300 x == 0
This should be enlightnening:
Plot[200000000000 x^2 + (1 + x)^5000 (1 - 4700 x) - 1 - 300 x, {x, 0, 0.003}]
Using FindRoot with a good guess gives x=0.002322108633 or r=1.002322108633.
The WA commands follow.
First I used
FullSimplify[Sum[(900-3k)r^(k-1),{k,1,n]]
Then you would have to retype the expression it spits out:
Plot[(3 (299 - 300 r + r^5000 (-299 + 5000 + 300 r - 5000 r)))/(-1 + r)^2 + 6000000000,{r,-2,2}]
At this point I manually replaced r with x+1:
Plot[200000000000 x^2 + (1 + x)^5000 (1 - 4700 x) - 1 - 300 x, {x, 0, 0.003}]
And solving for the root:
FindRoot[200000000000 x^2 + (1 + x)^5000 (1 - 4700 x) - 1 - 300 x, {x, 0.0023}]
Which doesn't give enough precision, and this is as far as you can go using only WA. You can try to subtract off the first few digits that WA gives you, and do another substitution with y = x + 0.00232211 to get the next few digits, but that is too tedious for me to try.

Resources