Using Mathematica I need to evaluate the integral of a function. Since it is taking the program too much to compute it, would it be possible to use parallel computation to shorten the time needed? If so, how can I do it?
I uploaded a picture of the integrand function:
I need to integrate it with respect to (x3, y3, x, y) all of them ranging in a certain interval (x3 and y3 from 0 to 1) (x and y from 0 to 100). The parameters (a,b,c...,o) are preventing the NIntegrate function to work. Any suggestions?
If you evaluate this
expr=E^((-(x-y)^4-(x3-y3)^4)/10^4)*
(f x+e x^2+(m+n x)x3-f y-e y^2-(m+n y)y3)*
((378(x-y)^2(f x+e x^2+(m+n x)x3-f y-e y^2-(m+n y)y3))/
(Pi(1/40+Sqrt[((x-y)^2+(x3-y3)^2)^3]))+
(378(x-y)(x3-y3)(h x+g x^2+(o+p x)x3-h y-g y^2-(o+p y)y3))/
(Pi(1/40+Sqrt[((x-y)^2+(x3-y3)^2)^3])))+
(h x+g x^2+(o+p x)x3-h y-g y^2-(o +p y) y3)*
((378(x-y)(x3-y3)(f x+e x^2+(m+n x)x3-f y-e y^2-(m+n y)y3))/
(Pi(1/40+Sqrt[((x-y)^2+(x3-y3)^2)^3]))+
(378 (x3 - y3)^2 (h x + g x^2 + (o + p x)x3-h y-g y^2-(o+p y)y3))/
(Pi(1/40+Sqrt[((x-y)^2+(x3-y3)^2)^3])));
list=List ## Expand[expr]
then you will get a list of 484 expressions, each very similar in form to this
(378*f*h*x^3*x3)/(Pi*(1/40+Sqrt[(x^2+x3^2-2*x*y+y^2-2*x3*y3+y3^2)^3]))
Notice that you can then use NIntegrate in this way
f*h*NIntegrate[(378*x^3*x3)/(Pi*(1/40+Sqrt[(x^2+x3^2-2*x*y+y^2-2*x3*y3+y3^2)^3])),
{x,0,100},{y,0,100},{x3,0,1},{y3,0,1}]
but it gives warnings and errors about the convergence and accuracy, almost certainly due to your fractional powers in the denominator.
If you can find a way to pull out the scalar multipliers which are independent of x,y,x3,y3 and then perform that integration without warnings and errors and get an accurate result which isn't infinity then you could perhaps perform these integrals in parallel and total the results.
Some of the integrands are scalar multiples of others and if you combine similar integrands then you can reduce this down to 300 unique integrands.
I doubt this is going to lead to an acceptable solution for you.
Please check all this very carefully to make certain that no mistakes have been made.
EDIT
Since the variables that are independent of the integration appear to be easily separated from the dependent variables in the problem posed above, I think this will allow parallel NIntegrate
independentvars[z_] := (z/(z//.{e->1, f->1, g->1, h->1, m->1, n->1, o->1, p->1}))*
NIntegrate[(z//.{e->1, f->1, g->1, h->1, m->1, n->1, o->1, p->1}),
{x, 0, 100}, {y, 0, 100}, {x3, 0, 1}, {y3, 0, 1}]
Total[ParallelMap[independentvars, list]]
As I mentioned previously, the fractional powers in the denominator result in a flood of warnings and errors about convergence failing.
You can test this with the following much simpler example
expr = f x + f g x3 + o^2 x x3;
list = List ## Expand[expr];
Total[ParallelMap[independentvars, list]]
which instantly returns
500000. f + 5000. f g + 250000. o^2
This is a very primitive method of pulling independent symbolic variables outside an NIntegrate. This gives absolutely no warning if one of the integrands is not in a form where this primitive attempt at extraction is not appropriate or fails.
There may be a far better method that someone else has written out there somewhere. If someone could show a far better method of doing this then I would appreciate it.
It might be nice if Wolfram would consider incorporating something like this into NIntegrate itself.
Related
Sorry for the basic question, but it's quite hard to find too much discussion on Maxima specifics.
I'm trying to learn some Maxima and wanted to use something like
x:2
x+=2
which as far as I can tell doesn't exist in Maxima. Then I discovered that I can define my own operators as infix operators, so I tried doing
infix("+=");
"+=" (a,b):= a:(a+b);
However this doesn't work, as if I first set x:1 then try calling x+=2, the function returns 3, but if I check the value of x I see it hasn't changed.
Is there a way to achieve what I was trying to do in Maxima? Could anyone explain why the definition I gave fails?
Thanks!
The problem with your implementation is that there is too much and too little evaluation -- the += function doesn't see the symbol x so it doesn't know to what variable to assign the result, and the left-hand side of an assignment isn't evaluated, so += thinks it is assigning to a, not x.
Here's one way to get the right amount of evaluation. ::= defines a macro, which is just a function which quotes its arguments, and for which the return value is evaluated again. buildq is a substitution function which quotes the expression into which you are substituting. So the combination of ::= and buildq here is to construct the x: x + 2 expression and then evaluate it.
(%i1) infix ("+=") $
(%i2) "+="(a, b) ::= buildq ([a, b], a: a + b) $
(%i3) x: 100 $
(%i4) macroexpand (x += 1);
(%o4) x : x + 1
(%i5) x += 1;
(%o5) 101
(%i6) x;
(%o6) 101
(%i7) x += 1;
(%o7) 102
(%i8) x;
(%o8) 102
So it is certainly possible to do so, if you want to do that. But may I suggest maybe you don't need it? Modifying a variable makes it harder to keep track, mentally, what is going on. A programming policy such as one-time assignment can make it easier for the programmer to understand the program. This is part of a general approach called functional programming; perhaps you can take a look at that. Maxima has various features which make it possible to use functional programming, although you are not required to use them.
Is there any standard math function for this operation:
f(x)=max(x,0)
I was wondering maybe there is a well-known function for this operation in mathematics literature.
Any idea?
This is usually denoted as (x)+, sometimes also x⊔0 or x∨0, where the symbol alludes to the shape of the kinks in the maximum of two functions, for instance in |x|=max(x,-x).
In Lebesgue integration theory, for example, a function is first split into its positive and negative part, so that the integration theory can be reduced to non-negative functions.
Another application is splines, the cubic B-spline has the representation
B3(x)=1/6 * ( (x+2)+3 - 4 * (x+1)+3 + 6 * (x)+3 - 4 * (x-1)+3 + (x-2)+3 )
I guess, you are looking for:
(abs(x)+x)/2
https://www.wolframalpha.com/input/?i=%28%7Cx%7C%2Bx%29%2F2
Another way it might be characterised is as
x H(x)
where H(x) is the Heaviside unit step function.
H(x) = ( x >= 0 ? 1 : 0 )
i.e. 1 for positive x, 0 for negative x and either 0, 1, or 1/2 at x=0. This is used in control theory, signal processing and Fourier analysis. Its quite common to use f(x) H(x) for functions which start at a particular time, say switching some electronics on. So in this area of study x H(x) might be the best way to answer your question.
Keep getting the error Arguments are not sufficiently instantiated for the multiplication by addition rule I wrote as shown below.
mult(_, 0, 0). %base case for multiplying by 0
mult(X, 1, X). % another base case
mult(X, Y, Z) :-
Y > 1,
Y1 is Y - 1,
mult(X, Y1, Z1),
Z is X + Z1.
I am new to Prolog and really struggling with even such simple problems.
Any recommendations for books or online tutorials would be great.
I am running it on SWI-Prolog on Ubuntu Linux.
In your definition of mult/3 the first two arguments have to be known. If one of them is still a variable, an instantiation error will occur. Eg. mult(2, X, 6) will yield an instantiation error, although X = 3 is a correct answer ; in fact, the only answer.
There are several options you have:
successor-arithmetics, constraints, or meta-logical predicates.
Here is a starting point with successor arithmetics:
add(0,Y,Y).
add(s(X),Y,s(Z)) :- add(X,Y,Z).
Another approach would be to use constraints over the integers. YAP and SWI have a library(clpfd) that can be used in a very flexible manner: Both for regular integer computations and the more general constraints. Of course, multiplication is already predefined:
?- A * B #= C.
A*B#=C.
?- A * B #= C, C = 6.
C = 6, A in -6.. -1\/1..6, A*B#=6, B in -6.. -1\/1..6.
?- A * B #= C, C = 6, A = 2.
A = 2, B = 3, C = 6.
Meta-logical predicates: I cannot recommend this option in which you would use var/1, nonvar/1, ground/1 to distinguish various cases and handle them differently. This is so error prone that I have rarely seen a correct program using them. In fact, even very well known textbooks contain serious errors!
I think you got the last two calls reversed. Don't you mean:
mult(X,Y,Z):- Y>1,Y1 is Y-1, Z1 is X+Z, mult(X,Y1,Z1).
Edit: nevermind that, looked at the code again and it doesn't make sense. I believe your original code is correct.
As for why that error is occuring, I need to know how you're calling the predicate. Can you give an example input?
The correct way of calling your predicate is mult(+X, +Y, ?Z):
?- mult(5,0,X).
X = 0
?- mult(5,1,X).
X = 5
?- mult(5,5,X).
X = 25
?- mult(4,4,16).
yes
?- mult(3,3,10).
no
etc. Calling it with a free variable in the first two arguments will produce that error, because one of them will be used in the right side of an is or in either side of the <, and those predicates expect ground terms to succeed.
My Calculus teacher gave us a program on to calculate the definite integrals of a given interval using the trapezoidal rule. I know that programmed functions take an input and produce an output as arithmetic functions would but I don't know how to do the inverse: find the input given the output.
The problem states:
"Use the trapezoidal rule with varying numbers, n, of increments to estimate the distance traveled from t=0 to t=9. Find a number D for which the trapezoidal sum is within 0.01 unit of this limit (468) when n > D."
I've estimated the limit through "plug and chug" with the calculator and I know that with a regular algebraic function, I could easily do:
limit (468) = algebraic expression with variable x
(then solve for x)
However, how would I do this for a programmed function? How would I determine the input of a programmed function given output?
I am calculating the definite integral for the polynomial, (x^2+11x+28)/(x+4), between the interval 0 and 9. The trapezoidal rule function in my calculator calculates the definite integral between the interval 0 and 9 using a given number of trapezoids, n.
Overall, I want to know how to do this:
Solve for n:
468 = trapezoidal_rule(a = 0, b = 9, n);
The code for trapezoidal_rule(a, b, n) on my TI-83:
Prompt A
Prompt B
Prompt N
(B-A)/N->D
0->S
A->X
Y1/2->S
For(K,1,N-1,1)
X+D->X
Y1+S->S
End
B->X
Y1/2+S->S
SD->I
Disp "INTEGRAL"
Disp I
Because I'm not familiar with this syntax nor am I familiar with computer algorithms, I was hoping someone could help me turn this code into an algebraic equation or point me in the direction to do so.
Edit: This is not part of my homework—just intellectual curiosity
the polynomial, (x^2+11x+28)/(x+4)
This is equal to x+7. The trapezoidal rule should give exactly correct results for this function! I'm guessing that this isn't actually the function you're working with...
There is no general way to determine, given the output of a function, what its input was. (For one thing, many functions can map multiple different inputs to the same output.)
So, there is a formula for the error when you apply the trapezoidal rule with a given number of steps to a given function, and you could use that here to work out the value of n you need ... but (1) it's not terribly beautiful, and (2) it doesn't seem like a very reasonable thing to expect you to do when you're just starting to look at the trapezoidal rule. I'd guess that your teacher actually just wanted you to "plug and chug".
I don't know (see above) what function you're actually integrating, but let's pretend it's just x^2+11x+28. I'll call this f(x) below. The integral of this from 0 to 9 is actually 940.5. Suppose you divide the interval [0,9] into n pieces. Then the trapezoidal rule gives you: [f(0)/2 + f(1*9/n) + f(2*9/n) + ... + f((n-1)*9/n) + f(9)/2] * 9/n.
Let's separate this out into the contributions from x^2, from 11x, and from 28. It turns out that the trapezoidal approximation gives exactly the right result for the latter two. (Exercise: Work out why.) So the error you get from the trapezoidal rule is exactly the same as the error you'd have got from f(x) = x^2.
The actual integral of x^2 from 0 to 9 is (9^3-0^3)/3 = 243. The trapezoidal approximation is [0/2 + 1^2+2^2+...+(n-1)^2 + n^2/2] * (9/n)^2 * (9/n). (Exercise: work out why.) There's a standard formula for sums of consecutive squares: 1^2 + ... + n^2 = n(n+1/2)(n+1)/3. So our trapezoidal approximation to the integral of x^2 is (9/n)^3 times [(n-1)(n-1/2)n/3 + n^2/2] = (9/n)^3 times [n^3/3+1/6] = 243 + (9/n)^3/6.
In other words, the error in this case is exactly (9/n)^3/6 = (243/2) / n^3.
So, for instance, the error will be less than 0.01 when (243/2) / n^3 < 0.01, which is the same as n^3 > 100*243/2 = 12150, which is true when n >= 23.
[EDITED to add: I haven't checked any of my algebra or arithmetic carefully; there may be small errors. I take it what you're interested is the ideas rather than the specific numbers.]
Reading this question got me thinking: For a given function f, how can we know that a loop of this form:
while (x > 2)
x = f(x)
will stop for any value x? Is there some simple criterion?
(The fact that f(x) < x for x > 2 doesn't seem to help since the series may converge).
Specifically, can we prove this for sqrt and for log?
For these functions, a proof that ceil(f(x))<x for x > 2 would suffice. You could do one iteration -- to arrive at an integer number, and then proceed by simple induction.
For the general case, probably the best idea is to use well-founded induction to prove this property. However, as Moron pointed out in the comments, this could be impossible in the general case and the right ordering is, in many cases, quite hard to find.
Edit, in reply to Amnon's comment:
If you wanted to use well-founded induction, you would have to define another strict order, that would be well-founded. In case of the functions you mentioned this is not hard: you can take x << y if and only if ceil(x) < ceil(y), where << is a symbol for this new order. This order is of course well-founded on numbers greater then 2, and both sqrt and log are decreasing with respect to it -- so you can apply well-founded induction.
Of course, in general case such an order is much more difficult to find. This is also related, in some way, to total correctness assertions in Hoare logic, where you need to guarantee similar obligations on each loop construct.
There's a general theorem for when then sequence of iterations will converge. (A convergent sequence may not stop in a finite number of steps, but it is getting closer to a target. You can get as close to the target as you like by going far enough out in the sequence.)
The sequence x, f(x), f(f(x)), ... will converge if f is a contraction mapping. That is, there exists a positive constant k < 1 such that for all x and y, |f(x) - f(y)| <= k |x-y|.
(The fact that f(x) < x for x > 2 doesn't seem to help since the series may converge).
If we're talking about floats here, that's not true. If for all x > n f(x) is strictly less than x, it will reach n at some point (because there's only a limited number of floating point values between any two numbers).
Of course this means you need to prove that f(x) is actually less than x using floating point arithmetic (i.e. proving it is less than x mathematically does not suffice, because then f(x) = x may still be true with floats when the difference is not enough).
There is no general algorithm to determine whether a function f and a variable x will end or not in that loop. The Halting problem is reducible to that problem.
For sqrt and log, we could safely do that because we happen to know the mathematical properties of those functions. Say, sqrt approaches 1, log eventually goes negative. So the condition x < 2 has to be false at some point.
Hope that helps.
In the general case, all that can be said is that the loop will terminate when it encounters xi≤2. That doesn't mean that the sequence will converge, nor does it even mean that it is bounded below 2. It only means that the sequence contains a value that is not greater than 2.
That said, any sequence containing a subsequence that converges to a value strictly less than two will (eventually) halt. That is the case for the sequence xi+1 = sqrt(xi), since x converges to 1. In the case of yi+1 = log(yi), it will contain a value less than 2 before becoming undefined for elements of R (though it is well defined on the extended complex plane, C*, but I don't think it will, in general converge except at any stable points that may exist (i.e. where z = log(z)). Ultimately what this means is that you need to perform some upfront analysis on the sequence to better understand its behavior.
The standard test for convergence of a sequence xi to a point z is that give ε > 0, there is an n such that for all i > n, |xi - z| < ε.
As an aside, consider the Mandelbrot Set, M. The test for a particular point c in C for an element in M is whether the sequence zi+1 = zi2 + c is unbounded, which occurs whenever there is a |zi| > 2. Some elements of M may converge (such as 0), but many do not (such as -1).
Sure. For all positive numbers x, the following inequality holds:
log(x) <= x - 1
(this is a pretty basic result from real analysis; it suffices to observe that the second derivative of log is always negative for all positive x, so the function is concave down, and that x-1 is tangent to the function at x = 1). From this it follows essentially immediately that your while loop must terminate within the first ceil(x) - 2 steps -- though in actuality it terminates much, much faster than that.
A similar argument will establish your result for f(x) = sqrt(x); specifically, you can use the fact that:
sqrt(x) <= x/(2 sqrt(2)) + 1/sqrt(2)
for all positive x.
If you're asking whether this result holds for actual programs, instead of mathematically, the answer is a little bit more nuanced, but not much. Basically, many languages don't actually have hard accuracy requirements for the log function, so if your particular language implementation had an absolutely terrible math library this property might fail to hold. That said, it would need to be a really, really terrible library; this property will hold for any reasonable implementation of log.
I suggest reading this wikipedia entry which provides useful pointers. Without additional knowledge about f, nothing can be said.