I'm attempting to generate a breed-owned variable which draws it's values from a random beta distribution in Netlogo.
I've found the "bc" code example online but am struggling to adapt it to what I need. Right now, for convenience, I've generate my distribution from a random-normal distribution using
create-breed 500
[
set target_factor random-normal 0.9 0.05
if target_factor > 1 [set target_factor 0.9999999999]
if target_Factor < 0.5 [set target_factor 0.5000000001]
]
So basically I'd like to get a reporter that can replace the "random-normal 0.9 0.05" part with a random beta distribution
I got so far as:
to-report random_beta
set asocial_alpha 2
set asocial_beta 2
set asocial_min_eps 0
set asocial_max_eps 0.25
let x random-gamma asocial_alpha 1
let asocial_eps (x / (x + random-gamma asocial_beta 1))
set asocial_eps asocial_min_eps + (asocial_eps * (asocial_max_eps - asocial_min_eps))
foreach ( n-values 99 [ (? + 1) / 100 * (asocial_max_eps - asocial_min_eps) + asocial_min_eps] )
[report ? ( ((? - asocial_min_eps) ^ (asocial_alpha - 1) * (asocial_max_eps - ?) ^ (asocial_beta - 1)) / ( asocial_max_eps - asocial_min_eps ) ^ (asocial_alpha + asocial_beta - 1) )]
end
all of the 'set' variables here are global factors
I'm honestly out of my depth with this one mathematically. If anyone can help me fix this reporter (or if a procedure would work that's fine too). so my final code for breed creation is:
create-breed 500
[
set target_factor random-beta
if target_factor > 1 [set target_factor 0.9999999999]
if target_Factor < 0.5 [set target_factor 0.5000000001]
]
I was asked this offsite as apparently the rngs extension hasn't been updated for awhile and thought I should post here too. Here is the code to draw beta using the built-in gamma distribution generators.
to-report random-beta [ #alpha #beta ]
let XX random-gamma #alpha 1
let YY random-gamma #beta 1
report XX / (XX + YY)
end
Related
I am trying to numerically solve the Klein-Gordon equation that can be found here. To make sure I solved it correctly, I am comparing it with an analytical solution that can be found on the same link. I am using the finite difference method and Matlab. The initial spatial conditions are known, not the initial time conditions.
I start off by initializing the constants and the space-time coordinate system:
close all
clear
clc
%% Constant parameters
A = 2;
B = 3;
lambda = 2;
mu = 3;
a = 4;
b = - (lambda^2 / a^2) + mu^2;
%% Coordinate system
number_of_discrete_time_steps = 300;
t = linspace(0, 2, number_of_discrete_time_steps);
dt = t(2) - t(1);
number_of_discrete_space_steps = 100;
x = transpose( linspace(0, 1, number_of_discrete_space_steps) );
dx = x(2) - x(1);
Next, I define and plot the analitical solution:
%% Analitical solution
Wa = cos(lambda * x) * ( A * cos(mu * t) + B * sin(mu * t) );
figure('Name', 'Analitical solution');
surface(t, x, Wa, 'edgecolor', 'none');
colormap(jet(256));
colorbar;
xlabel('t');
ylabel('x');
title('Wa(x, t) - analitical solution');
The plot of the analytical solution is shown here.
In the end, I define the initial spatial conditions, execute the finite difference method algorithm and plot the solution:
%% Numerical solution
Wn = zeros(number_of_discrete_space_steps, number_of_discrete_time_steps);
Wn(1, :) = Wa(1, :);
Wn(2, :) = Wa(2, :);
for j = 2 : (number_of_discrete_time_steps - 1)
for i = 2 : (number_of_discrete_space_steps - 1)
Wn(i + 1, j) = dx^2 / a^2 ...
* ( ( Wn(i, j + 1) - 2 * Wn(i, j) + Wn(i, j - 1) ) / dt^2 + b * Wn(i - 1, j - 1) ) ...
+ 2 * Wn(i, j) - Wn(i - 1, j);
end
end
figure('Name', 'Numerical solution');
surface(t, x, Wn, 'edgecolor', 'none');
colormap(jet(256));
colorbar;
xlabel('t');
ylabel('x');
title('Wn(x, t) - numerical solution');
The plot of the numerical solution is shown here.
The two plotted graphs are not the same, which is proof that I did something wrong in the algorithm. The problem is, I can't find the errors. Please help me find them.
To summarize, please help me change the code so that the two plotted graphs become approximately the same. Thank you for your time.
The finite difference discretization of w_tt = a^2 * w_xx - b*w is
( w(i,j+1) - 2*w(i,j) + w(i,j-1) ) / dt^2
= a^2 * ( w(i+1,j) - 2*w(i,j) + w(i-1,j) ) / dx^2 - b*w(i,j)
In your order this gives the recursion equation
w(i,j+1) = dt^2 * ( (a/dx)^2 * ( w(i+1,j) - 2*w(i,j) + w(i-1,j) ) - b*w(i,j) )
+2*w(i,j) - w(i,j-1)
The stability condition is that at least a*dt/dx < 1. For the present parameters this is not satisfied, they give this ratio as 2.6. Increasing the time discretization to 1000 points is sufficient.
Next up is the boundary conditions. Besides the two leading columns for times 0 and dt one also needs to set the values at the boundaries for x=0 and x=1. Copy also them from the exact solution.
Wn(:,1:2) = Wa(:,1:2);
Wn(1,:)=Wa(1,:);
Wn(end,:)=Wa(end,:);
Then also correct the definition (and use) of b to that in the source
b = - (lambda^2 * a^2) + mu^2;
and the resulting numerical image looks identical to the analytical image in the color plot. The difference plot confirms the closeness
I got stuck with below task and spent about 3 hours trying to figure it out.
Task description: A man has a rather old car being worth $2000. He saw a secondhand car being worth $8000. He wants to keep his old car until he can buy the secondhand one.
He thinks he can save $1000 each month but the prices of his old car and of the new one decrease of 1.5 percent per month. Furthermore this percent of loss increases by 0.5 percent at the end of every two months. Our man finds it difficult to make all these calculations.
How many months will it take him to save up enough money to buy the car he wants, and how much money will he have left over?
My code so far:
def nbMonths(startPriceOld, startPriceNew, savingperMonth, percentLossByMonth)
dep_value_old = startPriceOld
mth_count = 0
total_savings = 0
dep_value_new = startPriceNew
mth_count_new = 0
while startPriceOld != startPriceNew do
if startPriceOld >= startPriceNew
return mth_count = 0, startPriceOld - startPriceNew
end
dep_value_new = dep_value_new - (dep_value_new * percentLossByMonth / 100)
mth_count_new += 1
if mth_count_new % 2 == 0
dep_value_new = dep_value_new - (dep_value_new * 0.5) / 100
end
dep_value_old = dep_value_old - (dep_value_old * percentLossByMonth / 100)
mth_count += 1
total_savings += savingperMonth
if mth_count % 2 == 0
dep_value_old = dep_value_old - (dep_value_old * 0.5) / 100
end
affordability = total_savings + dep_value_old
if affordability >= dep_value_new
return mth_count, affordability - dep_value_new
end
end
end
print nbMonths(2000, 8000, 1000, 1.5) # Expected result[6, 766])
The data are as follows.
op = 2000.0 # current old car value
np = 8000.0 # current new car price
sv = 1000.0 # annual savings
dr = 0.015 # annual depreciation, both cars (1.5%)
cr = 0.005. # additional depreciation every two years, both cars (0.5%)
After n >= 0 months the man's (let's call him "Rufus") savings plus the value of his car equal
sv*n + op*(1 - n*dr - (cr + 2*cr + 3*cr +...+ (n/2)*cr))
where n/2 is integer division. As
cr + 2*cr + 3*cr +...+ (n/2)*cr = cr*((1+2+..+n)/2) = cr*(1+n/2)*(n/2)
the expression becomes
sv*n + op*(1 - n*dr - cr*(1+(n/2))*(n/2))
Similarly, after n years the cost of the car he wants to purchase will fall to
np * (1 - n*dr - cr*(1+(n/2))*(n/2))
If we set these two expressions equal we obtain the following.
sv*n + op - op*dr*n - op*cr*(n/2) - op*cr*(n/2)**2 =
np - np*dr*n - np*cr*(n/2) - np*cr*(n/2)**2
which reduces to
cr*(np-op)*(n/2)**2 + (sv + dr*(np-op))*n + cr*(np-op)*(n/2) - (np-op) = 0
or
cr*(n/2)**2 + (sv/(np-op) + dr)*n + cr*(n/2) - 1 = 0
If we momentarily treat (n/2) as a float division, this expression reduces to a quadratic.
(cr/4)*n**2 + (sv/(np-op) + dr + cr/2)*n - 1 = 0
= a*n**2 + b*n + c = 0
where
a = cr/4 = 0.005/4 = 0.00125
b = sv/(np-op) + dr + cr/(2*a) = 1000.0/(8000-2000) + 0.015 + 0.005/2 = 0.18417
c = -1
Incidentally, Rufus doesn't have a computer, but he does have an HP 12c calculator his grandfather gave him when he was a kid, which is perfectly adequate for these simple calculations.
The roots are computed as follows.
(-b + Math.sqrt(b**2 - 4*a*c))/(2*a) #=> 5.24
(-b - Math.sqrt(b**2 - 4*a*c))/(2*a) #=> -152.58
It appears that Rufus can purchase the new vehicle (if it's still for sale) in six years. Had we been able able to solve the above equation for n/2 using integer division it might have turned out that Rufus would have had to wait longer. That’s because for a given n both cars would have depreciated less (or at least not not more), and because the car to be purchased is more expensive than the current car, the difference in values would be greater than that obtained with the float approximation for 1/n. We need to check that, however. After n years, Rufus' savings and the value of his beater will equal
sv*n + op*(1 - dr*n - cr*(1+(n/2))*(n/2))
= 1000*n + 2000*(1 - 0.015*n - 0.005*(1+(n/2))*(n/2))
For n = 6 this equals
1000*6 + 2000*(1 - 0.015*6 - 0.005*(1+(6/2))*(6/2))
= 1000*6 + 2000*(1 - 0.015*6 - 0.005*(1+3)*3)
= 1000*6 + 2000*0.85
= 7700
The cost of Rufus' dream car after n years will be
np * (1 - dr*n - cr*(1+(n/2))*(n/2))
= 8000 * (1 - 0.015*n - 0.005*(1+(n/2))*(n/2))
For n=6 this becomes
8000 * (1 - 0.015*6 - 0.005*(1+(6/2))*(6/2))
= 8000*0.85
= 6800
(Notice that the factor 0.85 is the same in both calculations.)
Yes, Rufus will be able to buy the car in 6 years.
def nbMonths(old, new, savings, percent)
percent = percent.fdiv(100)
current_savings = 0
months = 0
loop do
break if current_savings + old >= new
current_savings += savings
old -= old * percent
new -= new * percent
months += 1
percent += 0.005 if months.odd?
end
[months, (current_savings + old - new).round]
end
So I'm trying to write a converter for HSL to RGB (and eventually into hex)
I'm following this colorspace conversion theory and I seem to be stuck on step 6
Now we need to do up to 3 tests to select the correct formula for each
color channel. Let’s start with Red.
test 1 – If 6 x temporary_R is smaller then 1, Red = temporary_2 +
(temporary_1 – temporary_2) x 6 x temporary_R In the case the first
test is larger then 1 check the following
test 2 – If 2 x temporary_R is smaller then 1, Red = temporary_1 In
the case the second test also is larger then 1 do the following
test 3 – If 3 x temporary_R is smaller then 2, Red = temporary_2 +
(temporary_1 – temporary_2) x (0.666 – temporary_R) x 6 In the case
the third test also is larger then 2 you do the following
Red = temporary_2
Ok lets do it for our Red value
6 x temporary_R = 6 x 0.869 = 5.214, so it’s larger then 1, we need to
do test 2 2 x temporary_R = 2 x 0.869 = 1.738, it’s also larger then
1, we need to do test 3 3 x temporary_R = 3 x 0.869 = 2.607, it’s
larger then 2, so we go for the last formula Red = temporary_2 =
0.0924 which rounded down is 0.09, which is a number we recognize from the RGB to HSL conversion
So far I've monkey patched a function to take my HSL colours
def toRGB(hue, sat, lum)
temp_1 =
case lum
when lum < 0.0
lum x (1.0 * sat)
when lum > 0.0
(lum + sat) - lum
end
temp_2 = (2 * lum) - temp_1.to_f
h = (hue/360.0).round(4)
temp_r = (h + 0.333).round(4)
temp_r = temp_r + 1 if temp_r < 0
temp_r = temp_r - 1 if temp_r > 1
temp_g = h
temp_b = (h - 0.333).round(4)
temp_b = temp_b + 1 if temp_b < 0
temp_b = temp_b - 1 if temp_b > 1
red =
#test 1
#test 2
#test 3
"#{red}"
end
I was trying to use a case statement
red =
case temp_r
when 6 * temp_r < 1
temp_2 + (temp_1 - temp_2) * 6 * temp_r
when 2 * temp_r < 1
temp_1
when 3 * temp_r < 2
temp_2 + (temp_1 - temp_2) * (0.666 - temp_r * 6)
end
but then I started re-reading the instructions and now I can't really see a way to do what I need in ruby. Maybe I'm over-thinking it.
If you want to see the rest of my code in context you can see it here
There are two things I noticed in your code snippet:
You are mixing two types of switch case statement in ruby.
case a
when 1..5
"It's between 1 and 5"
when 6
"It's 6"
end
case
when a > 1 && a < 5
"It's between 1 and 5"
when a == 6
"It's 6"
end
See a difference, in first case when you directly compare cases, you've to mention the variable name you're comparing with, while in second case you're comparing with true & false condition by explicitly putting a condition on your variable so you don't need to put it next to case.
The second thing is as per your condition statement, you'll need an else case in your case statement.
red =
case
when 6 * temp_r < 1
temp_2 + (temp_1 - temp_2) * 6 * temp_r
when 2 * temp_r < 1
temp_1
when 3 * temp_r < 2
temp_2 + (temp_1 - temp_2) * (0.666 - temp_r * 6)
else
temp_2
end
I am building my first large-scale MATLAB program, and I've managed to write original vectorized code for everything so for until I came to trying to create an image representing vector density in stereographic projection. After a couple failed attempts I went to the Mathworks file exchange site and found an open source program which fits my needs courtesy of Malcolm Mclean. With a test matrix his function produces something like this:
And while this is almost exactly what I wanted, his code relies on a triply nested for-loop. On my workstation a test data matrix of size 25000x2 took 65 seconds in this section of code. This is unacceptable since I will be scaling up to a data matrices of size 500000x2 in my project.
So far I've been able to vectorize the innermost loop (which was the longest/worst loop), but I would like to continue and be rid of the loops entirely if possible. Here is Malcolm's original code that I need to vectorize:
dmap = zeros(height, width); % height, width: scalar with default value = 32
for ii = 0: height - 1 % 32 iterations of this loop
yi = limits(3) + ii * deltay + deltay/2; % limits(3) & deltay: scalars
for jj = 0 : width - 1 % 32 iterations of this loop
xi = limits(1) + jj * deltax + deltax/2; % limits(1) & deltax: scalars
dd = 0;
for kk = 1: length(x) % up to 500,000 iterations in this loop
dist2 = (x(kk) - xi)^2 + (y(kk) - yi)^2;
dd = dd + 1 / ( dist2 + fudge); % fudge is a scalar
end
dmap(ii+1,jj+1) = dd;
end
end
And here it is with the changes I've already made to the innermost loop (which was the biggest drain on efficiency). This cuts the time from 65 seconds down to 12 seconds on my machine for the same test matrix, which is better but still far slower than I would like.
dmap = zeros(height, width);
for ii = 0: height - 1
yi = limits(3) + ii * deltay + deltay/2;
for jj = 0 : width - 1
xi = limits(1) + jj * deltax + deltax/2;
dist2 = (x - xi) .^ 2 + (y - yi) .^ 2;
dmap(ii + 1, jj + 1) = sum(1 ./ (dist2 + fudge));
end
end
So my main question, are there any further changes I can make to optimize this code? Or even an alternative method to approach the problem? I've considered using C++ or F# instead of MATLAB for this section of the program, and I may do so if I cannot get to a reasonable efficiency level with the MATLAB code.
Please also note that at this point I don't have ANY additional toolboxes, if I did then I know this would be trivial (using hist3 from the statistics toolbox for example).
Mem consuming solution
yi = limits(3) + deltay * ( 1:height ) - .5 * deltay;
xi = limits(1) + deltax * ( 1:width ) - .5 * deltax;
dx = bsxfun( #minus, x(:), xi ) .^ 2;
dy = bsxfun( #minus, y(:), yi ) .^ 2;
dist2 = bsxfun( #plus, permute( dy, [2 3 1] ), permute( dx, [3 2 1] ) );
dmap = sum( 1./(dist2 + fudge ) , 3 );
EDIT
handling extremely large x and y by breaking the operation into blocks:
blockSize = 50000; % process up to XX elements at once
dmap = 0;
yi = limits(3) + deltay * ( 1:height ) - .5 * deltay;
xi = limits(1) + deltax * ( 1:width ) - .5 * deltax;
bi = 1;
while bi <= numel(x)
% take a block of x and y
bx = x( bi:min(end, bi + blockSize - 1) );
by = y( bi:min(end, bi + blockSize - 1) );
dx = bsxfun( #minus, bx(:), xi ) .^ 2;
dy = bsxfun( #minus, by(:), yi ) .^ 2;
dist2 = bsxfun( #plus, permute( dy, [2 3 1] ), permute( dx, [3 2 1] ) );
dmap = dmap + sum( 1./(dist2 + fudge ) , 3 );
bi = bi + blockSize;
end
This is a good example of why starting a loop from 1 matters. The only reason that ii and jj are initiated at 0 is to kill the ii * deltay and jj * deltax terms which however introduces sequentiality in the dmap indexing, preventing parallelization.
Now, by rewriting the loops you could use parfor() after opening a matlabpool:
dmap = zeros(height, width);
yi = limits(3) + deltay*(1:height) - .5*deltay;
matlabpool 8
parfor ii = 1: height
for jj = 1: width
xi = limits(1) + (jj-1) * deltax + deltax/2;
dist2 = (x - xi) .^ 2 + (y - yi(ii)) .^ 2;
dmap(ii, jj) = sum(1 ./ (dist2 + fudge));
end
end
matlabpool close
Keep in mind that opening and closing the pool has significant overhead (10 seconds on my Intel Core Duo T9300, vista 32 Matlab 2013a).
PS. I am not sure whether the inner loop instead of the outer one can be meaningfully parallelized. You can try to switch the parfor to the inner one and compare speeds (I would recommend going for the big matrix immediately since you are already running in 12 seconds and the overhead is almost as big).
Alternatively, this problem can be solved in using kernel density estimation techniques. This is part of the Statistics Toolbox, or there's this KDE implementation by Zdravko Botev (no toolboxes required).
For the example code below, I get 0.3 seconds for N = 500000, or 0.7 seconds for N = 1000000.
N = 500000;
data = [randn(N,2); rand(N,1)+3.5, randn(N,1);]; % 2 overlaid distrib
tic; [bandwidth,density,X,Y] = kde2d(data); toc;
imagesc(density);
I determine limits as limit(0)=0; limit(y)=2*1.08^(y-1), y∈{1,2,3,...,50} or if you prefeer iterative functions:
limit(0)=0
limit(1)=2
limit(y)=limit(y-1)*1.08, x∈{2,3,4,...,50}
Exmples:
limit(1) = 2*1.08^0 = 2
limit(2) = 2*1.08^1 = 2.16
limit(3) = 2*1.08^2 = 2.3328
...
for a given x∈[0,infinity) I want an efficient formula to calculate y so that limit(y)>x and limit(y-1)≤x or 50 if there is none.
Any ideas?
or is pre-calculating the 50 limits and using a couple of ifs the best solution?
I am using erlang as language, but I think it will not make much of a difference.
limit(y) = 2 * 1.08^(y-1)
limit(y) > x >= limit(y - 1)
Now if I haven't made a mistake,
2 * 1.08^(y - 1) > x >= 2 * 1.08^(y - 2)
1.08^(y - 1) > x / 2 >= 1.08^(y - 2)
y - 1 > log[1.08](x / 2) >= y - 2
y + 1 > 2 + ln(x / 2) / ln(1.08) >= y
y <= 2 + ln(x / 2) / ln(1.08) < y + 1
Which gives you
y = floor(2 + ln(x / 2) / ln(1.08))