How to convert this equation to Octave code and plot - plot

I have an equation that I created on Desmos website
I used the code below to try and recreate it in Octave. But when I plot it, it comes out different. How can I fix the code in Octave (without changing the main equation, if possible) so it looks like the Desmos image?
x = linspace(0,1,20);
y = linspace(0,1,20);
S=[13.2];
T=1.12;
for zz=1:1:length(S)
eq1=exp(S(1,zz)*T*log(x))+exp(S(1,zz)*T*log(y));
hold on
plot(x,eq1)
zz
end
PS: I'm using Octave 4.2.2

S = 13.2;
T = 1.12;
f = #(x)exp(log(1-exp(S*T*log(x)))./(S*T));
fplot(f, [0, 1])

Desmos.com does not plot (x,eq1) but (x,y) with the constraint that x, y satisfy the given equation. So, you solve for y for each value of x, and plot the pairs (x,y).
Since log(x), log(y) exist, x and y are >0 (otherwise you would have to plot for x<0 as well).
clear; clc;
x = linspace(0,1,150);
S = 13.2;
T = 1.12;
y = zeros(size(x));
for i = 1:length(x)
y(i) = (1-exp(S*T*log(x(i))))^(1/S/T);
end
plot(x,y)
Notes:
1) I assume by log(x) you mean ln(x) (logarithm using base e).
2) I used a more dense discretization with 150 points so that the plotted curve appears smoother.
3) Mathematically, linspace(0,1,150) should not work, as log(x=0) is not defined. However for Matlab log(0) = -inf which means that exp(-inf) = 0. That's why no runtime error is thrown.
4) By the way, the provided equation can be simplified to x^(ST) + y^(ST) = 1, with the constraints that x, y > 0.

Related

Connecting two points with a 3D logarithmic spiral (Julia)

I am calculating points along a three-dimensional logarithmic spiral between two points. I seem to be close, but I think I'm missing a conditional sign flip somewhere.
This code works relatively well:
using PlotlyJS
using LinearAlgebra
# Points to connect (`p2` spirals into `p1`)
p1 = [1,1,1]
p2 = [3,10,2]
# Number of curve revolutions
rev = 3
# Number of points defining the curve
rez = 500 # Number of points defining the line
r = norm(p1-p2)
t = range(0,r,rez)
theta_offset = atan((p1[2]-p2[2])/(p1[1]-p2[1]))
theta = range(0, 2*pi*rev, rez) .+ theta_offset
x = cos.(theta).*exp.(-t).*r.+p1[1];
y = sin.(theta).*exp.(-t).*r.+p1[2];
z = exp.(-t).*log.(r).+p1[3]
# Plot curve points
plot(scatter(x=x, y=y, z=z, marker=attr(size=2,color="red"),type="scatter3d"))
and produces the following plot. Values of the endpoints are shown on the plot, with an arrow from the coordinate to its respective marker. The first point is off, but it's close enough for my liking.
The problem comes when I flip p2 and p1 such that
p1 = [3,10,2]
p2 = [1,1,1]
In this case, I still get a spiral from p2 to p1, and the end point (p1) is highly accurate. However, the other endpoint (p2) is wildly off:
I think this is due to me changing the relative Z position of the two points, but I'm not sure, and I haven't been able to solve this riddle. Any help would be greatly appreciated. (Bonus points if you can help figure out why the Z value on p2 is off in the first example!)
Assuming this is a follow-up of your other question: Drawing an equiangular spiral between two known points in Julia
I assume you just want to add a third dimension to your previous 2D problem using cylindric coordinate system. This means that you need to separate the treatment of x and y coordinate on one side, and the z coordinate on the other side.
First you need to calculate your r on the first two coordinate:
r = norm(p1[1:2]-p2[1:2])
Then, when calculating z, you need to take only the third dimension in your formula (not sure why you used a log function there in the first place):
z = exp.(-t).*(p1[3]-p2[3]).+p2[3]
That will fix your z-axis.
Finally for your x and y coordinate, use the two argument atan function:
julia>?atan
help?> atan
atan(y)
atan(y, x)
Compute the inverse tangent of y or y/x, respectively.
For one argument, this is the angle in radians between the positive x-axis and the point (1, y), returning a value in the interval [-\pi/2, \pi/2].
For two arguments, this is the angle in radians between the positive x-axis and the point (x, y), returning a value in the interval [-\pi, \pi]. This corresponds to a standard atan2
(https://en.wikipedia.org/wiki/Atan2) function. Note that by convention atan(0.0,x) is defined as \pi and atan(-0.0,x) is defined as -\pi when x < 0.
like this:
theta_offset = atan( p1[2]-p2[2], p1[1]-p2[1] )
And finally, like in your previous question, add the p2 point instead of the p1 point at the end of x, y, and z:
x = cos.(theta).*exp.(-t).*r.+p2[1];
y = sin.(theta).*exp.(-t).*r.+p2[2];
z = exp.(-t).*(p1[3]-p2[3]).+p2[3]
In the end, I have this:
using PlotlyJS
using LinearAlgebra
# Points to connect (`p2` spirals into `p1`)
p2 = [1,1,1]
p1 = [3,10,2]
# Number of curve revolutions
rev = 3
# Number of points defining the curve
rez = 500 # Number of points defining the line
r = norm(p1[1:2]-p2[1:2])
t = range(0.,norm(p1-p2), length=rez)
theta_offset = atan( p1[2]-p2[2], p1[1]-p2[1] )
theta = range(0., 2*pi*rev, length=rez) .+ theta_offset
x = cos.(theta).*exp.(-t).*r.+p2[1];
y = sin.(theta).*exp.(-t).*r.+p2[2];
z = exp.(-t).*(p1[3]-p2[3]).+p2[3]
#show (x[begin], y[begin], z[begin])
#show (x[end], y[end], z[end]);
# Plot curve points
plot(scatter(x=x, y=y, z=z, marker=attr(size=2,color="red"),type="scatter3d"))
Which give the expected results:
p2 = [1,1,1]
p1 = [3,10,2]
(x[begin], y[begin], z[begin]) = (3.0, 10.0, 2.0)
(x[end], y[end], z[end]) = (1.0001877364735474, 1.0008448141309634, 1.0000938682367737)
and:
p1 = [1,1,1]
p2 = [3,10,2]
(x[begin], y[begin], z[begin]) = (0.9999999999999987, 1.0, 1.0)
(x[end], y[end], z[end]) = (2.9998122635264526, 9.999155185869036, 1.9999061317632263)
In 2D, let us assume the pole at the point C, and the spiral from P to Q, corresponding to a variation of the parameter in the interval [0, 1].
We have
X = Cx + cos(at+b).e^(ct+d)
Y = Cy + sin(at+b).e^(ct+d)
Using the known points,
Px - Cx = cos(b).e^d
Py - Cy = sin(b).e^d
Qx - Cx = cos(a+b).e^(c+d)
Qy - Cy = sin(a+b).e^(c+d)
From the first two, by a Cartesian to polar transformation (and logarithm), you can obtain b and d. From the last two, you similarly obtain a+b and c+d, and the spiral is now defined.
For the Z coordinate, I cannot answer precisely as you don't describe how you generalize the spiral to 3D. Anyway, we can assume a certain function Z(t), that you can map to [Pz, Qz] by the linear transformation
(Qz - Pz) . (Z(t) - Z(0)) / (Z(1) - Z(0)) + Pz.

Quadratic surface plotting in Octave

I've been assigned a project that requires me to plot some quadratic surfaces. I tried to be diligent and download some software so that my graphs look better than those done with other free online resources. I decided to try Octave and see if I can make it work but I've ran into a problem. When trying to plot:
I've checked some tutorials but so far I haven't been able to pinpoint my error. This is the code I was using:
clear;
x = [-3:1:3];
y = x;
[xx,yy] = meshgrid(x,y);
zz=sqrt(-9*xx.^2+9*yy.^2);
figure
mesh(xx,yy,zz);
Any suggestions are appreciated.
The error thrown to the command window for your script is:
error: mesh: X, Y, Z, C arguments must be real
error: called from
mesh at line 61 column 5
blah at line 15 column 1
Since you x and y are real, the imaginaries are coming from a square-root of a number less than 0. Looking at your equation, this will happen for any (x, y) pair where x is greater than y.
The easiest fix is to set all complex numbers (values of zz with a non-zero imaginary part) to 0 (which will plot the value) or NaN (which will not plot the value. Consider this script (yours plus filtering):
clear;
x = -3:0.1:3;
y = x;
[xx,yy] = meshgrid(x,y);
zz=sqrt(-9*xx.^2+9*yy.^2);
figure
% Set all zz with nonzero imaginary part to NaN
zz(imag(zz)~=0) = NaN;
% % Set all zz with nonzero imaginary part to 0
% zz(imag(zz)~=0) = 0;
mesh(xx,yy,zz);
I would prefer this:
x = -3:0.1:3;
y = x;
[xx,yy] = meshgrid(x,y);
zz=sqrt(-9*xx.^2+9*yy.^2); % zz will have both + and -
figure
% zz = abs(zz) ;
mesh(xx,yy,abs(zz));
hold on
mesh(xx,yy,-abs(zz));

Is there a code/function that solves an equation for either X or Y?

I have a simple quadratic equation, but I need to find a way for R to solve for X or Y depending on the value I input for either. For example, my equation is
y = 232352x^2+2468776x+381622
I need to find a code that solves for y when x = 8000 and solve for x when y = 4000. Does such a code/function exist in R or do I have to do it manually?
The first part (solving for y when x=8000) is pretty straightforward.
You just type:
232352 * 8000^2 + 2468776 * 8000 + 381622
and R gives:
[1] 1.489028e+13
The second problem involves roots. The polyroot() function is what you're after. It takes in the coefficients of the equation as a vector, and returns the roots. So for your case:
polyroot(c(381622-4000,2468776,232352))
gives:
[1] -0.155227+0i -10.469928-0i
And then it's up to you to figure out which solution you want.
Remember in general if you want to solve y = Ax^2 + Bx + C for a particular value of y, you have to rearrange the equation to Ax^2 + Bx + (C-y) = 0.
Translated to R code this is:
coeff <- c(C-y,B,A)
polyroot(coeff)
Where you substitute A,B,C,y with the relevant numbers.

Plotting function with 3 parameters (4d) in R

I want to see how three variables x, y, and z respond to a function f using R.
I've searched for R solutions (e.g. rgl using 4d plots) but none seem to allow the input of a function as the fourth variable while allowing manipulation of x, y, and z across their full range of values.
# First I create three variables that each have a domain 0 to 4
x
y
z
# Then I create a function from those three variables
f <- sqrt(x^2 + y^2 + z^2)
EDIT: I originally stated that I wanted x, y, and z to be seq(0, 4, 0.01) but in fact I only want them to range from 0 to 4, and do so independently of other variables. In other words, I want to plot the function across a range of values letting x move independently of y and z and so forth, rather than plotting a 3-D line. The result should be a 3-D surface.
I want to:
a) see how the function f responds to all possible combinations of x, y, and z across a range of x, y, and z values 0 to 4, and
b) find what maxima/minima exist especially when holding one variable constant.
This is rather a mathematical questions. Unfortunately, our computer screens are not really made fro 4D, neither our brains. So what you ask wont be possible as if. Indeed, you want to show a dense set of data (a cube between 0 and 4), and we can not display what is "inside" the cube.
To come back to R, you can always display a slice of it, for example fixing z and plot sqrt(x^2 + y^2 + z^2) for x and y. Here you have two examples:
# Points where the function should be evaluated
x <- seq(0, 4, 0.01)
y <- seq(0, 4, 0.01)
z <- seq(0, 4, 0.01)
# Compute the distance from origin
distance <- function(x,y,z) {
sqrt(x^2 + y^2 + z^2)
}
# Matrix to store the results
slice=matrix(0, nrow=length(x),ncol=length(y))
# Fill the matrix with a slice at z=3
i=1
for (y_val in y)
{
slice[,i]=distance(x,y_val,3)
i=i+1
}
# PLot with plot3D library
require(plot3D)
persp3D(z = slice, theta = 100,phi=50)
# PLot with raster library
library(raster)
plot(raster(slice,xmn=min(x), xmx=max(x), ymn=min(y), ymx=max(y)))
If you change your z values, you will not really change the shape (just making it "flatter" for bigger z). Note that the function being symmetric in x, y and z, the same plots are produced if you keep xor y constant.
For your last question about the maximum, you can re-use the slice matrix and do:
max_ind=which(slice==max(slice),arr.ind = TRUE)
x[max_ind[,1]]
y[max_ind[,2]]
(see Get the row and column name of the minimum element of a matrix)
But again with math we can see from your equation that the maximum will always be obtained by maxing x, y and z. Indeed, the function simply measure the distance from the origin.

How to plot Daubechies psi and phi wavelet functions in R?

The analysis with wavelets seems to be carried out as a discrete transform via matrix multiplication. So it is not surprising, I guess, that when plotting, for example, D4, the R package wmtsa returns the plot:
require(wmtsa)
filters <- wavDaubechies("d4")
plot(filters)
The question is how to go from this discretized plot to the plot in the Wikipedia entry:
Please note that I'm not interested in generating these curves precisely with wmtsa. Any other package will do - I don't have Matlab or Mathematica. But I wonder if the way to go is to start with translating this Mathematica chunk of code in this paper into R, rather than using built-in functions:
Wave1etTransform.m
c[k-1 := c[k] = Daubechies[4][[k+l]];
phi[l] = (l+Sqrt[3])/2 // N;
phi[2] = (l-Sqrt[3])/2 // N;
phi[xJ; xc=0 II x>=3] : = 0
phi[x-?NumberQ] := phi[x] =
N[Sqrt[2]] Sum[c[k] phi[2x-k],{k,0,3}];
In order to plot the wavelet and scaling function all you need are the four numbers shown in the first two plots. I'll focus on plotting the scaling function.
Integer shifts of the scaling function, 𝜑, form an orthonormal basis of the subspace V0 of the multiresolution analysis. We also have that V-1 ⊆ V0 and that 𝜑(x/2) ∈ V-1. Using this gives us the identity
𝜑(x/2) = ∑k ∈ ℤ hk𝜑(x-k)
Now we just need the values of hk. For the Daubechies wavelet these are the values show in the discrete plot you gave (and zero for every other value of k). For an exact value of the hk, first let 𝜇 = (1+sqrt(3))/2. Then we have that
h0 = 𝜇/4
h1 = (1+𝜇)/4
h2 = (2-𝜇)/4
h3 = (1-𝜇)/4
and hk = 0 otherwise.
Using these two things we are able to plot the function using what is known as the cascade algorithm. First notice that 𝜑(0) = 𝜑(0/2) = h0𝜑(0) + h1𝜑(0-1) + h2𝜑(0-2) + h3𝜑(0-3). The only way this equation can hold is if 𝜑(0) = 𝜑(-1) = 𝜑(-2) = 𝜑(-3) = 0. Extending this will show that for x ≦ 0 we have that 𝜑(x) = 0. Furthermore, a similar argument can show that 𝜑(x) = 0 for x ≥ 3.
Thus, we only need to worry about x = 1 and x = 2 to find non-zero values of 𝜑 for integer values of x. If we put x = 2 into the identity for 𝜑(x/2) we get that 𝜑(1) = h0𝜑(2) + h1𝜑(1). Putting x = 4 into the identity gives us that 𝜑(2) = h2𝜑(2) + h3𝜑(1).
We can rewrite the above two equations as a matrix multiplied by a vector equals a vector. In fact, it will be in the form v = Av (v is the same vector on both sides). This means that v is an eigenvector of the matrix A with eigenvalue 1. But v = (𝜑(1), 𝜑(2)) and so by finding this eigenvector using the standard methods we will be able to find the values of 𝜑(1) and 𝜑(2).
In fact, this gives us that 𝜑(1) = (1+sqrt(3))/2 and 𝜑(2) = (1-sqrt(3))/2 (this is where those values in the Mathematica code sample come from). Also note that we need to specifically chose the eigenvector of magnitude 2 for this algorithm to work so you must use those values for 𝜑(1) and 𝜑(2) even though you could rescale the eigenvector.
Now we can find the values of 𝜑(1/2), 𝜑(3/2), and 𝜑(5/2). For example, 𝜑(1/2) = h0𝜑(1) and 𝜑(3/2) = h1𝜑(2) + h2𝜑(1).
With these values, you can then find the values of 𝜑(1/4), 𝜑(3/4), and so on. Continuing this process will give you the value of 𝜑 for all dyadic rationals (rational numbers in the form k/2j.
The same process can be used to find the wavelet function. You only need to use the four different values shown in the first plot rather than the four shown in the second plot.
I recently implemented this Python. An R implementation will be fairly similar.
import numpy as np
import matplotlib.pyplot as plt
def cascade_algorithm(j: int):
mu = (1 + np.sqrt(3))/2
h_k = np.array([mu/4, (1+mu)/4, (2-mu)/4, (1-mu)/4])
# Array to store all the value of phi.
phi_vals = np.zeros((2, 3*2**j+1), dtype=np.float64)
for i in range(3*2**j+1):
phi_vals[0][i] = i/(2**j)
calced_vals = np.zeros((3*2**j+1), dtype=np.bool)
# Input values for 1 and 2.
phi_vals[1][1*2**j] = (1+np.sqrt(3))/2
phi_vals[1][2*2**j] = (1-np.sqrt(3))/2
# We now know the values for 0, 1, 2, and 3.
calced_vals[0] = True
calced_vals[1*2**j] = True
calced_vals[2*2**j] = True
calced_vals[3*2**j] = True
# Now calculate for all the dyadic rationals.
for k in range(1, j+1):
for l in range(1, 3*2**k):
x = l/(2**k)
if calced_vals[int(x*2**j)] != True:
calced_vals[int(x*2**j)] = True
two_x = 2*x
which_k = np.array([0, 1, 2, 3], dtype=np.int)
which_k = ((two_x - which_k > 0) & (two_x - which_k < 3))
phi = 0
for n, _ in enumerate(which_k):
if which_k[n] == True:
phi += h_k[n]*phi_vals[1][int((two_x-n)*2**j)]
phi_vals[1][int(x*2**j)] = 2*phi
return phi_vals
phi_vals = cascade_algorithm(10)
plt.plot(phi_vals[0], phi_vals[1])
plt.show()
If you just want to plot the graphs, then you can use the package "wavethresh" to plot for example the D4 with the following commands:
draw.default(filter.number=4, family="DaubExPhase", enhance=FALSE, main="D4 Mother", scaling.function = F) # mother wavelet
draw.default(filter.number=4, family="DaubExPhase", enhance=FALSE, main="D4 Father", scaling.function = T) # father wavelet
Notice that the mother wavelet and the father wavelets will be plotted depending on the variable "scaling.function". If true, then it plots the father wavelet (scaling), else it plots the mother wavelet.
If you want to generate it by yourself, without packages, I'd suggest you follow Daubechies-Lagarias algorithm, in this paper. It is not hard to implement.

Resources