Sympy: Substitution with functions - function

I have a function f:
f = Function('f')(x,y).
The output of my program is a large polynomial with terms XYf, Xf, Yf for variables X and Y. I would like to define the substitution such that
X f(x,y) = f(x+1,y)
Y f(x,y) = f(x,y+1)
Similarly, XY f(x,y) = f(x+1,y+1).
I have used the following code to define the operation of X and Y.
poly = poly.subs(X*f, f.subs(x,x+1))
poly = poly.subs(Y*f, f.subs(y,y+1))
Though this works with terms of Xf and Yf, it does not work with terms of XYf. XYf gives the output as Yf(x+1,y) instead of f(x+1,y+1).
How do I force Y to act on the "new" f?

XYf gives Yf(x+1, y) because it matches Xf and that's the first substitution you do. To replace all three in the way that you want, you should do them in an order such that you don't match later instances, like
poly = poly.subs(X*Y*f, f.subs(x,x+1).subs(y, y + 1))
poly = poly.subs(X*f, f.subs(x,x+1))
poly = poly.subs(Y*f, f.subs(y,y+1))
That way, you replace all X*Y*f(x, y) first, so when you replace X*f(x, y) and Y*f(x, y) it won't replace X*Y*f(x, y) (because they will already be replaced).
As a side note, in terms of code clarity, it's going to be simpler if you just define
f = Function('f')
and then explicitly write f(x, y), f(x + 1, y), and so on (rather than letting f = f(x, y) and using subs to create f(x + 1, y) and so on).

Related

Octave - gradients of a circle function do not plot correctly

Question
Trying to follow Gradients, Gradient Plots and Tangent Planes.
The gradient vectors of (X^2 + Y^2) do not show up correctly in Octave 4.2.0 on Windows. With the code, expected the gradients of a circle diverge from center outwards. However the actual is diagonal.
Please assist to understand what is wrong.
syms x y
f1 = x^2 + y^2;
gradf1 = jacobian(f1,[x,y]);
f1fun = function_handle(f1);
f1xfun = function_handle(gradf1(1));
f1yfun = function_handle(gradf1(2));
[xx, yy] = meshgrid(-1:.1:1,-1:.1:1);
hold on
contour(xx, yy, f1fun(xx, yy), 10)
quiver(xx, yy, f1xfun(xx, yy), f1yfun(xx, yy), 0.5)
axis equal tight
hold off
Expected
Actual
When you perform:
f1xfun = function_handle(gradf1(1));
f1yfun = function_handle(gradf1(2));
The output is:
f1xfun =
#(x) 2 * x % note: single-argument function
f1yfun =
#(y) 2 * y % note: single-argument function
that is AS OPPOSED TO
f1xfun =
#(x,y) 2 * x % two-argument function
f1yfun =
#(x,y) 2 * y % two-argument function
which is what you seem to think was happening. (i.e. the resulting functions actually only take a single input, not both x and y).
Therefore later on when you call f1yfun with two inputs, the second input (i.e. y) is simply silently discarded, and you are essentially calculating 2*x in both axes, hence the diagonal arrows.
tl;dr Your call to quiver should be:
quiver(xx, yy, f1xfun(xx), f1yfun(yy), 0.5);
I think you have a bug in your code and the call to quiver should be
quiver(xx, yy, f1xfun(xx), f1yfun(yy), 0.5)
which then gives (with colormap("jet"))

Writing simple equations in Octave

Imagine I want to define a function in Octave z(var1, var2) = a(var1) + b(var1) + c(var2) + d(var2) + const. Prior to this definition, I would like to define all the neccessary functions, something like: a(var1) = var1^2 + const, b(var1) = cos(var1), c(var) = sqrt(var2 - const) etc. Later in time, I add all those functions and form the final one, z function. Afterwards, I'd like to get partial derivatives of the function z in respect to var1 and var2.
So far, my only concern is defining the functions above to work as i imagined; is it possible and how ?
You can use function handles and anonymous functions:
a = #(x) x^2 + c1;
b = #cos;
c = #(x) sqrt(x - c2);
d = #exp;
b and d are handles to existing functions. You can call them as regular functions using b(...) or d(...). a and c are anonymous functions. They provide the argument list and definition of the handle right there in the assignment, somewhat like Python's lambdas. You could do something like b = #(x) cos(x), but there is really no point since there are no additional operations necessary.
Now you can do
z = #(x, y) a(x) + b(x) + c(y) + d(y) + c3;
The alternative is to write separate m-files for each function, which I am assuming you would like to avoid.
Using the function, for example to take partial derivatives, is now fairly straightforward. Function handles are called just like any other builtin or m-file-defined function:
(z(x + delta, y) - z(x - delta, y)) / (2 * delta)
Update
Just for fun, I ran the following script (using Octave 3.4.3 on Red Hat 6.5):
octave:1> c1 = -100;
octave:2> c2 = -10;
octave:3> c3 = 42;
octave:4> a = #(x) x^2 + c1;
octave:5> b = #cos;
octave:6> c = #(x) sqrt(x - c2);
octave:7> d = #exp;
octave:8> z = #(x, y) a(x) + b(x) + c(y) + d(y) + c3;
octave:9> [X, Y] = meshgrid([-10:0.1:10], [-10:0.1:10]);
octave:10> surf(X, Y, z(X, Y));
The result is not especially interesting, but it does demonstrate the effectiveness of this technique:
Here is an IDEOne link to play with.

Octave: defining a function to interpolate data points

Write an octave function to implement f(x) = sin(3x)/(0.4+(x-2)^2).
Write an octave script to interpolate between the values of f(x) = sin(3x)/(0.4+(x-2)^2) sampled uniformly at up to 9 points in the interval x = [0,4].
I'm confused as to what this question is asking. I interpreted the 1st part as defining a function fx that can be called from anywhere to return the values of f(x) for a given x, but I'm not sure if the x's have to be inputs.
For the 2nd part, am I correct in using the interpl function?
My attempt:
Function file fx.m
function fx
x=(0:0.25:4);
y = sin(3*x)/(0.4+(x-2))^2
endfunction
But this only returns 1 value for y. I need to return 9 uniformly spaced samples. I feel as though I need to use a for loop somehow...
Script intpl.m
1;
yi=interpl(x,y,0.4:0.4:3.6)
I think your teacher wants something like:
function y = f(x)
y = ....x..... (fill your formula here but use elementwise operations [1])
endfunction
and then use this function for the given range:
x = linspace (0, 4, 9);
y = f(x)
if you want to have this in one file foo.m be sure to not start the file with the function definition. I normally use "1;" so your script foo.m becomes:
1;
function y = f(x)
x = ....;
endfunction
x = linspace (...);
y = f(x)
plot (x, y) # if you want to plot it
[1] https://www.gnu.org/software/octave/doc/interpreter/Arithmetic-Ops.html

Error plotting a function of 2 variables

I am trying to plot the function
f(x, y) = (x – 3).^2 – (y – 2).^2.
x is a vector from 2 to 4, and y is a vector from 1 to 3, both with increments of 0.2. However, I am getting the error:
"Subscript indices must either be real positive integers or logicals".
What do I do to fix this error?
I (think) I see what you are trying to achieve. You are writing your syntax like a mathematical function definition. Matlab is interpreting f as a 2-dimensional data type and trying to assign the value of the expression to data indexed at x,y. The values of x and y are not integers, so Matlab complains.
If you want to plot the output of the function (we'll call it z) as a function of x and y, you need to define the function quite differently . . .
f = #(x,y)(x-3).^2 - (y-2).^2;
x=2:.2:4;
y=1:.2:3;
z = f( repmat(x(:)',numel(y),1) , repmat(y(:),1,numel(x) ) );
surf(x,y,z);
xlabel('X'); ylabel('Y'); zlabel('Z');
This will give you an output like this . . .
The f = #(x,y) part of the first line states you want to define a function called f taking variables x and y. The rest of the line is the definition of that function.
If you want to plot z as a function of both x and y, then you need to supply all possible combinations in your range. This is what the line containing the repmat commands is for.
EDIT
There is a neat Matlab function meshgrid that can replace the repmat version of the script as suggested by #bas (welcome bas, please scroll to bas' answer and +1 it!) ...
f = #(x,y)(x-3).^2 - (y-2).^2;
x=2:.2:4;
y=1:.2:3;
[X,Y] = meshgrid(x,y);
surf(x,y,f(X,Y));
xlabel('x'); ylabel('y'); zlabel('z');
I typically use the MESHGRID function. Like so:
x = 2:0.2:4;
y = 1:0.2:3;
[X,Y] = meshgrid(x,y);
F = (X-3).^2-(Y-2).^2;
surf(x,y,F);
xlabel('x');ylabel('y');zlabel('f')
This is identical to the answer by #learnvst. it just does the repmat-ing for you.
Your problem is that the function you are using uses integers, and you are trying to assign a double to it. Integers cannot have decimal places. To fix this, you can make it to where it increases in increments of 1, instead of 0.2

calling arrayfun; parameter estimation;

I have a problem with estimation.
I have a function, which is dependent on the values of an unknown vector V = [v1, …, v4].
I also have a vector of reference data YREF = [yref1, …, yrefn].
I would like to write a function, which returns the vector Y (in order to compare it later, say using lsqnonlin). I am aware of the “arrayfun”, but it seems not to work.
I have a subfunction, which returns a concrete value from the range [-100, 100],
%--------------------------------------------------------------------------
function y = SubFunction(Y, V)
y = fzero(#(x) v(1).*sinh(x./v(2)) + v(3).*x - Y, [-100 100]);
end
%--------------------------------------------------------------------------
then I make some operations on the results:
%--------------------------------------------------------------------------
function y = SomeFunction(Y,V)
temp = SubFunction (Y,V);
y = temp + v(4).*Y;
end
%--------------------------------------------------------------------------
These functions work well for a single value of Y, but not for the whole vector. How to store the results into a matrix for future comparison?
Thanks in advance
Chris
If Y is a vector, then the anonymous function defined as an argument to fzero returns a vector, not a scalar.
You can solve it by using a loop (notice the Y(k) inside the anonymous function definition):
function y = SubFunction(Y, v)
y = zeros (size(Y));
for k = 1 : length (Y)
y(k) = fzero(#(x) v(1).*sinh(x./v(2)) + v(3).*x - Y(k), [-100 100]);
end
end