Function plot from points result of other function combinations - matlab

I have 2 functions declared in wxmaxima: f1(x, y) and f2(x, y). Both contain if-then-else statements and basic arithmetic operations: addition, subtraction, multiplication and division.
For example (just an example, real functions look much more complicated):
f1(x, y) := block([],
if x * y < 123 then x + y
else if x / y > 7 then x - y
);
In both functions x and y change from 0.1 to 500000.
I need a 3D plot (graph) of the following points:
(x, y, z), where f1(x, y) == f2(z, x)
Note that it's impossible to extract z out from the equation above (and get a new shiny function f3(x, y)), since f1 and f2 are too complex.
Is this something possible to achieve using any computational software?
Thanks in advance!
EDIT:
What I need is the plot for
F(x, y, z) = 0
where
F(x, y, z) = f1(x, y) - f2(z, x)

For Maxima, try implicit_plot(f1(x, y) = f2(x, y), [x, <x0>, <x1>], [y, <y0>, <y1>]) where <x0>, <x1>, <y0>, <y1> are some floating point numbers which are the range of the plot. Note that load(implicit_plot) is needed since implicit_plot is not loaded by default.
As an aside, I see that your function f1 has the form if <condition1> then ... else if <condition2> then ... and that's all. That means if both <condition1> and <condition2> are false, then the function will return false, not a number. Either you must ensure that the conditions are exhaustive, or put else ... at the end of the if so that it will return a number no matter what the input.

set = Table[{i,j,0},{i,1,10},{j,0,10}];
Gives a list of desired x and y values and use those with a replace all /.
set = set /.{a_ ,b_ ,c_} -> {a,b, f1[a,b] - f2[a,b]} (*Simplified of course*)
Set is a 2d list of lists so it needs to be flattened by 1 dimension.
set = Flatten[set,1];
ListPlot3D[set (*add plot options*)]

Related

Reference elements in matrices in Julia while assigning values in other matrices

I have a vector X whose elements are zeros and ones. I want to create another vector Z of the same size as X where each element of Z is 0 if the corresponding element in X is zero, otherwise it is a random draw from a. uniform distribution. In Matlab I can easily do this by:
n = 1000;
X = randi([0, 1], [1, n]);
Z(X) = rand(); #Here wherever X takes a value of 1, the element of Z is a draw from a uniform distribution.
I want to implement this in Julia. Is there a cleaner way of doing this instead of using if conditionals. Thanks!!
Here's one way to do it:
julia> n = 1000;
julia> x = rand(Bool, n);
julia> z = zeros(n);
julia> using Distributions
julia> z[x] .= rand.(Uniform(-10, 10));
julia> z
100-element Vector{Float64}:
-2.6946644136672004
0.0
0.0
⋮
You can adjust the parameters of the Uniform distribution to what you need, or leave that argument out if the default [0, 1) range is what you need.
The line z[x] .= rand.(Uniform(-10, 10)) uses Julia's logical indexing (same as MATLAB) and broadcasting features - for every x value that is true, the rand call is made and the result assigned to that element of z.
The advantage of using the broadcast (compared to creating rand(Uniform(-10, 10), count(x)) and assigning that to z[x] for eg.) is that the values are directly assigned in-place to their destination in z, and so there's no extra unnecessary memory allocated (as mentioned by #DNF in the comments).
First of all, your Matlab code doesn't work in Matlab, for two reasons: Firstly because logical indices must be boolean, they cannot be 0 and 1. And secondly, because Z(X) = rand() will draw only a single random number and assign it to all the corresponding elements of Z.
Instead, you may want something like this Matlab code:
X = rand(1, n) > 0.5
Z(X) = rand(sum(X), 1)
In Julia you could do
X = rand(Bool, n)
Z = float.(X) # you have to initialize Z
Z[X] .= rand.()
Edit: Here's an alternative with a comprehension, where you don't need to initialize Z:
X = rand(Bool, n)
Z = [x ? float(x) : rand() for x in X]
Technically, what you are sampling from here is a left-censored uniform distribution -- equivalent to the mixture of a Dirac distibution at 0 and Uniform(0, 1). The next release of Distributions.jl will have an implementation for censored, which will remove the need to do any fancy assignment at all:
Z = rand(censored(Uniform(-1.0, 1.0), lower=0.0), N)
where the extent to the left is chosen so that the mixture components have equal weight.

Get an array of results of a function using as input an array of values (in Matlab)

I want to get the array of results of a function using as input an array of values. The function receives two variables (x1, x2) and a constant x3, so I'm trying to input all combination of it in a range using mesh.
The result is incorrect, I'm missing something.
Sample:
fun = #(x1,x2,x3) (x2-x1^2)^2+(1-x1)^2 + x3;
x3 = 7;
fun2 = #(x) fun(x(1,1),x(1,2),x3);
x0 = [2 3];
min = fminsearch(fun2, x0);
disp(min);
x = min(1)-10:1:min(1)+10;
y = min(2)-10:1:min(2)+10;
[X,Y] = meshgrid(x,y);
% I'm getting strange values here, like z < 0, how it is possible if everything is squared in the function.
Z = fun(X,Y,x3);
It's important to note that there is a difference between matrix and element-wise operations in MATLAB.
Matrix operations are defined via plain operators, such as *, or ^. So for example, A*B performs a matrix multiplication between A and B.
Element-wise operators make use of the dot . before the operator, i.e., .*, .^, and so on. Thus, A.*B performs an element-wise multiplication of A and B. The end result of this operation is an array of the same size as A and B (whose sizes must be equal), where the jj'th element of the array is equal to A(jj)*B(jj).
Now, consider your definition of fun:
fun = #(x1,x2,x3) (x2-x1^2)^2+(1-x1)^2 + x3;
What happens when MATLAB evaluates this expression is that it applies the matrix operations, such as ^ to the input arrays. However, to obtain your desired result of applying the operation to every individual element in your input arrays x1, x2, you should be using element-wise operations.
A new definition
fun = #(x1,x2,x3) (x2-x1.^2).^2+(1-x1).^2 + x3;
should provide the desired result.

Error plot matlab

i have a list of functions:
[ x - 3^(1/2)/2, x - 4967757600021511/81129638414606681695789005144064, x + 3^(1/2)/2, x - 4160783518353059/4503599627370496, x - 1723452963400281/4503599627370496, x + 3446905926800561/9007199254740992, x + 4160783518353059/4503599627370496, x - 8566355544790271/9007199254740992, x - 2647149443198255/4503599627370496, x - 4967757600021511/81129638414606681695789005144064, x + 5294298886396509/9007199254740992, x + 8566355544790271/9007199254740992, x - 8700286382685973/9007199254740992, x - 2^(1/2)/2, x - 291404338770025/1125899906842624, x + 2331234710160199/9007199254740992, x + 2^(1/2)/2, x + 2175071595671493/2251799813685248, x - 8781369964030313/9007199254740992, x - 7042111946219083/9007199254740992, x - 3908077291623905/9007199254740992, x - 4967757600021511/81129638414606681695789005144064, x + 122127415363247/281474976710656, x + 880263993277385/1125899906842624, x + 4390684982015157/4503599627370496]
and I would like to plot the functions with this command "plot(funciones_che(1))" but when I make the plot throws me the following error:
Error using plot. A numeric or double convertible argument is expected
I have also tried x = -10: 10 and plot (x, funciones_che (1)) but I get the same error
You do not have a vector of functions. The variable funciones_che is just a long concatenated sequence of numbers. If you run size(funciones_che), you should get 1 x m*n where m is length(x) and n is the number of "functions" you have. Having a true vector of functions would actually complicate your life unnecessarily.
If you have a symbolic expression somewhere along the line, it may be a bit difficult to clear: http://www.mathworks.com/help/symbolic/clear-assumptions-and-reset-the-symbolic-engine.html. My recommendation is to reset the entire symbolic engine with all its assumptions just to be safe: reset(symengine).
MATLAB is very good at plotting matrices like the one you have, but the size has to be right:
Separate your plots with semi-colons (;) rather than commas (,):
funciones_che=[ x - 3^(1/2)/2; x - 4967757600021511/81129638414606681695789005144064; x + 3^(1/2)/2; .....]
Now size(funciones_che) will be n x m.
Transpose the matrix (to make plot interpret it correctly):
funciones_che = funciones_che';
Now size(funciones_che) will be m x n.
Plot as you wanted to: plot(funciones_che(:, 1)) for the first vector, or plot(funciones_che) to put all of them on the same plot. If you are not interested in the second version, you do not have to transpose the matrix. If you do not transpose the matrix, plot using plot(funciones_che(1, :)) instead.
Final point: you do need to initialize x, for example to -10:10 as you tried.

What is the Haskell / hmatrix equivalent of the MATLAB pos function?

I'm translating some MATLAB code to Haskell using the hmatrix library. It's going well, but
I'm stumbling on the pos function, because I don't know what it does or what it's Haskell equivalent will be.
The MATLAB code looks like this:
[U,S,V] = svd(Y,0);
diagS = diag(S);
...
A = U * diag(pos(diagS-tau)) * V';
E = sign(Y) .* pos( abs(Y) - lambda*tau );
M = D - A - E;
My Haskell translation so far:
(u,s,v) = svd y
diagS = diag s
a = u `multiply` (diagS - tau) `multiply` v
This actually type checks ok, but of course, I'm missing the "pos" call, and it throws the error:
inconsistent dimensions in matrix product (3,3) x (4,4)
So I'm guessing pos does something with matrix size? Googling "matlab pos function" didn't turn up anything useful, so any pointers are very much appreciated! (Obviously I don't know much MATLAB)
Incidentally this is for the TILT algorithm to recover low rank textures from a noisy, warped image. I'm very excited about it, even if the math is way beyond me!
Looks like the pos function is defined in a different MATLAB file:
function P = pos(A)
P = A .* double( A > 0 );
I can't quite decipher what this is doing. Assuming that boolean values cast to doubles where "True" == 1.0 and "False" == 0.0
In that case it turns negative values to zero and leaves positive numbers unchanged?
It looks as though pos finds the positive part of a matrix. You could implement this directly with mapMatrix
pos :: (Storable a, Num a) => Matrix a -> Matrix a
pos = mapMatrix go where
go x | x > 0 = x
| otherwise = 0
Though Matlab makes no distinction between Matrix and Vector unlike Haskell.
But it's worth analyzing that Matlab fragment more. Per http://www.mathworks.com/help/matlab/ref/svd.html the first line computes the "economy-sized" Singular Value Decomposition of Y, i.e. three matrices such that
U * S * V = Y
where, assuming Y is m x n then U is m x n, S is n x n and diagonal, and V is n x n. Further, both U and V should be orthonormal. In linear algebraic terms this separates the linear transformation Y into two "rotation" components and the central eigenvalue scaling component.
Since S is diagonal, we extract that diagonal as a vector using diag(S) and then subtract a term tau which must also be a vector. This might produce a diagonal containing negative values which cannot be properly interpreted as eigenvalues, so pos is there to trim out the negative eigenvalues, setting them to 0. We then use diag to convert the resulting vector back into a diagonal matrix and multiply the pieces back together to get A, a modified form of Y.
Note that we can skip some steps in Haskell as svd (and its "economy-sized" partner thinSVD) return vectors of eigenvalues instead of mostly 0'd diagonal matrices.
(u, s, v) = thinSVD y
-- note the trans here, that was the ' in Matlab
a = u `multiply` diag (fmap (max 0) s) `multiply` trans v
Above fmap maps max 0 over the Vector of eigenvalues s and then diag (from Numeric.Container) reinflates the Vector into a Matrix prior to the multiplys. With a little thought it's easy to see that max 0 is just pos applied to a single element.
(A>0) returns the positions of elements of A which are larger than zero,
so forexample, if you have
A = [ -1 2 -3 4
5 6 -7 -8 ]
then B = (A > 0) returns
B = [ 0 1 0 1
1 1 0 0]
Note that we have ones corresponding to an elemnt of A which is larger than zero, and 0 otherwise.
Now if you multiply this elementwise with A using the .* notation, then you are multipling each element of A that is larger than zero with 1, and with zero otherwise. That is, A .* B means
[ -1*0 2*1 -3*0 4*1
5*1 6*1 -7*0 -8*0 ]
giving finally,
[ 0 2 0 4
5 6 0 0 ]
So you need to write your own function that will return positive values intact, and negative values set to zero.
And also, u and v does not match in dimension, for a generall SVD decomposition, so you actually would need to REDIAGONALIZE pos(diagS - Tau), so that u* diagnonalized_(diagS -tau) agrres to v

Generate matrix with for-loop in matlab

Say I have two functions f(x), g(x), and a vector:
xval=1:0.01:2
For each of these individual x values, I want to define a vector of y-values, covering the y-interval bounded by the two functions (or possibly a matrix where columns are x-values, and rows are y-values).
How would I go about creating a loop that would handle this for me? I have absolutely no idea myself, but I'm sure some of you have something right up your sleeve. I've been sweating over this problem for a few hours by now.
Thanks in advance.
Since you wish to generate a matrix, I assume the number of values between f(x) and g(x) should be the same for every xval. Let's call that number of values n_pt. Then, we also know what the dimensions of your result matrix rng will be.
n_pt = 10;
xval = 1 : 0.01 : 2;
rng = zeros(n_pt, length(xval));
Now, into the loop. Once we know what the y-values returned by f(x) and g(x) are, we can use linspace to give us n_pt equally spaced points between them.
for n = 1 : length(xval)
y_f = f(xval(n))
y_g = g(xval(n))
rng(:, n) = linspace(y_f, y_g, n_pt)';
end
This is nice because with linspace you don't need to worry about whether y_f > y_g, y_f == y_g or y_f < y_g. That's all taken care of already.
For demsonstration, I run this example for xval = 1 : 0.1 : 2 and the two sinusoids f = #(x) sin(2 * x) and g = #(x) sin(x) * 2. The points are plotted using plot(xval, rng, '*k');.