In my attempts to practice Julia, I've made a program which draws a bifurcation diagram. My code is as follows:
function bifur(x0,y0,a=1.3,b=0.4,n=1000,m=10000)
i,x,y=1,x0,y0
while i < n && abs(x) < m
x,y = a - x^2 + y, b * x
i += 1
end
if abs(x) < m
return x
else
return 1000
end
end
la = Float64[];
lx = Float64[];
for a=0:400
for j = 1:1000
x0 = rand()
y0 = rand()
x = bifur(x0,y0,a/100)
if x != 1000
push!(la,a/100)
push!(lx,x)
end
end
end
using Gadfly
myplot = Gadfly.plot( x=la, y=lx , Scale.x_discrete, Scale.y_continuous, Geom.point)
draw(PNG("myplot.png",10inch,8inch),myplot)
The output I get is this image:
In order to make my plot look more like this:
I need to be able to set point sizes to as small as one pixel. Then by increasing the iteration length I should be able to get a better bifurcation diagram. Does anyone know how to set the point sizes in Gadfly diagrams in Julia?
[Just to encapsulate the comments as an answer...]
Gadfly's Theme defaults can be changed. In particular, point_size is probably what you are looking for.
For changing the automatic plot scale/range settings, have a look at Gadfly's Scale params.
Related
I am trying to write some codes to find the global maximum of an equation, e.g. f = -x**4.
Here is what I have got at the moment.
import sympy
x = sympy.symbols('x')
f = -x**4
df = sympy.diff(f,x)
ans = sympy.solve(df,x)
Then I am stuck. How should I substitute ans back into f, and how would I know if that would be the maximum, but not the minimum or a saddle point?
If you are just looking for the global maximum and nothing else, then there is already a function for that. See the following:
from sympy import *
x = symbols('x')
f = -x**4
print(maximum(f, x)) # 0
If you want more information such as the x value that gives that max or maybe local maxima, you'll have to do more manual work. In the following, I find the critical values as you have done above and then I show the values as those critical points.
diff_f = diff(f, x)
critical_points = solve(diff_f, x)
print(critical_points) # x values
for point in critical_points:
print(f.subs(x, point)) # f(x) values
This can be extended to include the second derivative test as follows:
d_f = diff(f, x)
dd_f = diff(f, x, 2)
critical_points = solve(d_f, x)
for point in critical_points:
if dd_f.subs(x, point) < 0:
print(f"Local maximum at x={point} with f({point})={f.subs(x, point)}")
elif dd_f.subs(x, point) > 0:
print(f"Local minimum at x={point} with f({point})={f.subs(x, point)}")
else:
print(f"Inconclusive at x={point} with f({point})={f.subs(x, point)}")
To find the global max, you would need to take all your critical points and evaluate the function at those points. Then pick the max from those.
outputs = [f.subs(x, point) for point in critical_points]
optimal_x = [point for point in critical_points if f.subs(x, point) == max(outputs)]
print(f"The values x={optimal_x} all produce a global max at f(x)={max(outputs)}")
The above should work for most elementary functions. Apologies for the inconsistent naming of variables.
If you are struggling with simple things like substitution, I suggest going through the docs for an hour or two.
I'm new to Julia and I am trying to implement Julia's multithreading but I believe I am running into the "race condition problem". Here I am plotting the mandelbrot but I believe because of the race condition the array index [n] is messing with the color mapping. I tried using the atomic feature to the index n but apparently i cant use that type as an index. Here are pictures to compare as well as the code block.
Thanks!
module MandelBrot
using Plots
#make some functions for mandelbrot stuff
#find out if a number is part of the set
#remember the mandelbrot is symmetrical about the real number plane
function mandel(c)
#determine if a number is in the set or not in the set -
max_iter = 1000;
bound = 2
z = 0
n = 0
#if the magnitude of z exceeds two we know we are done.
while abs(z)<bound && n<max_iter
z = z^2+c
n+=1
end
return n #if n is 1000 assume c is good, else not of the set
end
#map n to a color
function brot(n)
rgb = 250
m = (n%rgb) /rgb#divide 250
if 0< n <= 250
c = RGB(1,m,0)
elseif 250<n<=500
c = RGB(1-m,1,0)
elseif 500<n<=750
c = RGB(0,1,m)
elseif 750<n<=999
c = RGB(0,1-m,1)
else
c=RGB(0,0,0)
end
return c
#TODO: append this c to an array of color values
end
#mrandom
function mandelbrot(reals,imags)
#generate #real amount of points between -2 and 1
#and #imag amount of points between 0 and i
#determine if any of those combinations are in the mandelbrot set
r = LinRange(-2,1,reals)
i = LinRange(-1,1,imags)
master_list = zeros(Complex{Float64},reals*imags,1)
color_assign = Array{RGB{Float64}}(undef,reals*imags,1)
#n = Threads.Atomic{Int64}(1)
n = 1
Threads.#threads for real_num in r
for imaginary_num in i
#z = complex(real_num, imaginary_num) #create the number
#master_list[n] = z #add it to the list
#color_assign[n,1] = (brot ∘ mandel)(z) #function of function! \circ + tab
#or would this be faster? since we dont change z all the time?
master_list[n] = complex(real_num, imaginary_num)
color_assign[n,1] = (brot ∘ mandel)(complex(real_num, imaginary_num))
n+=1
#Threads.atomic_add!(n,1)
end
end
gr(markerstrokewidth=0,markerstrokealpha=0,markersize=.5,legend=false)
scatter(master_list,markerstrokecolor=color_assign,color=color_assign,aspect_ratio=:equal)
end
#end statement for the module
end
julia> #time m.mandelbrot(1000,1000)
2.260481 seconds (6.01 M allocations: 477.081 MiB, 9.56% gc time)
Here is what should help:
function mandelbrot(reals,imags)
r = LinRange(-2,1,reals)
i = LinRange(0,1,imags)
master_list = zeros(Complex{Float64},reals*imags,1)
color_assign = Array{RGB{Float64}}(undef,reals*imags,1)
Threads.#threads for a in 1:reals
real_num = r[a]
for (b, imaginary_num) in enumerate(i)
n = (a-1)*imags + b
master_list[n] = complex(real_num, imaginary_num)
color_assign[n, 1] = (brot ∘ mandel)(complex(real_num, imaginary_num))
end
end
gr(markerstrokewidth=0,markerstrokealpha=0,markersize=1,legend=false)
scatter(master_list,markerstrokecolor=color_assign,color=color_assign,aspect_ratio=:equal)
end
The approach is to compute n as a function of indices along r and i.
Also note that I use 1:reals and not just enumerate(r) as Threads.#threads does not accept arbitrary iterators.
Note though that your code could probably be cleaned up in other but it is hard to do this without a fully reproducible example.
I have a data cube with 2 dimensions of coordinates and a third dimension for wavelength. My goal is to write a mask for coordinates outside a circle of given radius to the central coordinates (x0 and y0 in my code). For this, I'm trying to use a dictionary, but I'm having throuble because it seems that I'll have to make a double loop inside the dictionary to iterate over the two dimensions, and as a beginner with dictionaries, I don't know yet how to do that.
I wrote the following code
x0 = 38
y0 = 45
radius = 9
xcoords = np.arange(1,flux.shape[1]+1,1)
ycoords = np.arange(1,flux.shape[2]+1,1)
mask = {'xmask': [xcoords[np.sqrt((xcoords[:]-x0)**2 + (y-y0)**2) < radius] for y in ycoords], 'ymask': [ycoords[np.sqrt((x-x0)**2 + (ycoords[:]-y0)**2) < radius] for x in xcoords]}
And it returned several arrays, one for each value of y (for xmasks), and one for each value of x (for ymasks), although I want just one array for each one. Could anyone say what I made wrong and how to achieve my goal?
Note: I also made it without using a dictionary, as
xmask = []
for x in xcoords:
for y in ycoords:
if np.sqrt((x-x0)**2 + (y-y0)**2) < radius:
xmask.append(x)
break
ymask = []
for y in xcoords:
for x in ycoords:
if np.sqrt((x-x0)**2 + (y-y0)**2) < radius:
ymask.append(y)
break
but I hope it's possible to make it more efficiently.
Thanks for any help!
Edit: I realized that no loop was needed. If I select y = y0 and x = x0, I get the values of x and y that are inside the circle, respectively. So I stayed with
mask = {'xmask': [xcoords[abs(xcoords[:]-x0) < radius]], 'ymask': [ycoords[abs(ycoords[:]-y0) < radius]]}
The OP explains that assigning
mask = {'xmask': [xcoords[abs(xcoords[:] - x0) < radius]],
'ymask': [ycoords[abs(ycoords[:] - y0) < radius]]}
solves the problem.
Some background...
I am currently building a macro that will estimate the cost of an injection molding tool. These tools have cavities which are filled with plastic. The number of cavities a tool has is the number of parts that will be formed.
So far my program will determine the minimum number of cavities a tool can have based on customer demand. This number is always even. The tool should have an even number of cavities. Given the bounding length and width of a cavity, and setting a limit to how much space the cavities can occupy within the tool, I need my program to calculate the combination of number of cavities along the length and width whose difference is minimized and whose product is equal to the total number of minimum cavities the tool should have.
I am programming my macro is SolidWorks VBA. I first constructed this problem in Excel and used the solver tool. But, I am unable to find a way to reference the Excel Solver Tool in SolidWorks to automate this optimization problem. I am hoping to find a clever set of equations that can solve this specific problem for me. But if someone else has a better idea of what to use, that would be awesome.
Rephrasing in an optimization format...
Variables
x = number of cavities along width of tool
y = number of cavities along length of tool
z = suggested number of total cavities
Objective Function
Minimize x - y
Such that
x * y = z
x >= 1
y >= 1
x <= y
x is an integer
y is an integer
Example
My macro says that in order to meet demand, our tool needs to have at least 48 cavities. Find the number of cavities along the length and width of the tool such that the difference is minimized and the product is equal to 48. Ideally in this case the macro would return x = 6 and y = 8.
Thanks!
Just to clarify, in the question did you actually mean to Min y-x rather than Min x-y? Otherwise there is a naïve solution taking x = 1 and y = z. Min x - y = 1-z.
I don't program in VBA but here is the idea.
Since x and y are positive integers and there product is z, with x <= y. You can essentially start with x = floor(sqrt(z)) and decrement until x = 1.
For each x, check if there exists an integer y such that x * y = z. If there is, break the loop and that's the pair you are looking for. Otherwise continue until x = 1
If you need any pseudo code so you can translate it into VBA. Here it is
int x, y;
for (x = floor(sqrt(z)); x >= 1; --x)
{
y = z / x;
if (x * y == z)
break;
}
I think you can just test out a few examples. No fancy algorithm is needed.
If you relax the condition to be 2 numbers, x and y, whose product is z and with a minimum difference, then the answer is SQRT(z).
That is not an integer that meets your needs (in general). However, you can then try integers around the square root to see if they divide z. The first one you hit (i.e. minimum difference from SQRT(z)) should have the minimum difference.
If you relax the condition to be |z - x * y| is minimized, then I would recommend testing the numbers around sqrt(z). You need to check two cases -- the floor and ceiling of the square root (and the appropriate other number).
Just in case someone is needs something similar to this in the future, but can't figure out the pseudo-code I went ahead wrote it up. I wasn't sure how to output it as two values so I just threw them together as a string for the user to see.
Option Explicit
Function Factors(ByVal Test As Long) As String
Dim Val As Long
Dim i As Long
Val = Test
i = Int(Sqr(Val))
While Val / i >= 2
If Int(Val / i) * i = Val Then
Factors = i & " & " & Val / i
Exit Function
End If
i = i - 1
Wend
End Function
Part 2 - Determination of Number Density of Particles
If we say that q is the production rate of particles of a specific size, then in an interval dt the total number of particles produced is just q dt. To make things concrete in what follows, please adopt the case:
a = 0.9amax
q = 100000
Consider this number of particles at some distance r from the nucleus. The number density of particles will be number divided by volume, so to find number density we must compute the volume of a shell of radius r with a thickness that corresponds to how far the particles will travel in our time interval dt. Obviously that’s just the velocity of the particle at radius r times the time interval v(r) dt, so the volume of our shell is:
Volume = Shell Surface Area×Shell Thickness = 4πr2v(r)dt
Therefore, the number density, n, at radius r is:
n(r) = q dt /4πr2v(r)dt = q /4πr2v(r) (equation5)
You will note that our expression above will have a singularity for the number density of particles right at the surface of the nucleus, since at that position the outward velocity, v(R), is 0. Obviously this is an indication that we expect the particle density n to drop very rapidly as the dust is accelerated away from the surface. For now, let’s not worry about this point — we don’t need it later — and just graph how the number density varies with distance from the nucleus, starting with the 1st point after the surface value
• Evaluate Eqaution 5 for all calculated points using the parameters for q and a given above.
• Make a log-log graph of the number density versus radius. You should find that, after terminal velocity is achieved, the number density decreases as r−2, corresponding to a slope of -2 on a log-log plot
Current code:
% matplotlib inline
import numpy as np
import matplotlib.pyplot as pl
R = 2000 #Nucleus Radius (m)
GM_n = 667 #Nucleus Mass (m^3 s^-2)
Q = 7*10**27 #Gas Production Rate (molecules s^-1)
V_g = 1000 #Gas Velocity (m s^-1)
C_D = 4 #Drag Coefficient Dimensionless
p_d = 500 #Grain Density (kg m^-3)
M_h2o = .01801528/(6.022*10**23) #Mass of a water molecule (g/mol)
pi = np.pi
p_g_R = M_h2o*Q/(4*np.pi*R**2*V_g)
print ('Gas Density at the comets nucleus: ', p_g_R)
a_max = (3/8)*C_D*(V_g**2)*p_g_R*(1/p_d)*((R**2)/GM_n)
print ('Radius of Maximum Size Particle: ', a_max)
def drag_force(C_D,V_g,p_g_R,pi,a,v):
drag = .5*C_D*((V_g - v)**2)*p_g_R*pi*a**2
return drag
def grav_force(GM_n,M_d,r):
grav = -(GM_n*M_d)/(r**2)
return grav
def p_g_r(p_g_R,R,r):
p_g_r = p_g_R*(R**2/r**2)
return p_g_r
dt = 1
tfinal = 100000
v0 = 0
t = np.arange(0.,tfinal+dt,dt)
npoints = len(t)
r = np.zeros(npoints)
v = np.zeros(npoints)
r[0]= R
v[0]= v0
a = np.array([0.9,0.5,0.1,0.01,0.001])*a_max
for j in range(len(a)):
M_d = 4/3*pi*a[j]**3*p_d
for i in range(len(t)-1):
rmid = r[i] + v[i]*dt/2.
vmid = v[i] + (grav_force(GM_n,M_d,r[i])+drag_force(C_D,V_g,p_g_r(p_g_R,R,r[i]),pi,a[j],v[i]))*dt/2.
r[i+1] = r[i] + vmid*dt
v[i+1] = v[i] + (grav_force(GM_n,M_d,rmid)+drag_force(C_D,V_g,p_g_r(p_g_R,R,rmid),pi,a[j],vmid))*dt
pl.plot(r,v)
pl.show()
a_2= 0.9*a_max
q = 100000
I have never programmed anything like this before, my class is very difficult for me and I don't understand it. I have developed the above code with the help of the professor, and I am nearly out of time to finish this project. I just want help understanding the problem.
How do I find v(r) when I only have v(t), r(t)?
What do I do to calculate the r values and what r values do I even use?
You have v as a known function of time and also r as another known function of time. You can invert these to get t vs. v and t vs. r. To get v as a function of r, eliminate t.