Help in optimizing a for loop in matlab - optimization

I have a 1 by N double array consisting of 1 and 0. I would like to map all the 1 to symbol '-3' and '3' and all the 0 to symbol '-1' and '1' equally. Below is my code. As my array is approx 1 by 8 million, it is taking a very long time. How to speed things up?
[row,ll] = size(Data);
sym_zero = -1;
sym_one = -3;
for loop = 1 : row
if Data(loop,1) == 0
Data2(loop,1) = sym_zero;
if sym_zero == -1
sym_zero = 1;
else
sym_zero = -1;
end
else
Data2(loop,1) = sym_one;
if sym_one == -3
sym_zero = 3;
else
sym_zero = -3;
end
end
end

Here's a very important MATLAB optimization tip.
Preallocate!
Your code is much faster with a simple preallocation. Just add
Data2 = zeros(size(Data));
for loop = 1: row
...
before your for loop.
On my computer your code with preallocation terminated in 0.322s, and your original code is still running. I removed my original solution since yours is pretty fast with this optimization :).
Also since we're talking about MATLAB, it's faster to work on column vectors.

Hope you can follow this and I hope that I have understood your code correctly:
nOnes = sum(Data);
nZeroes = size(Data,2) - nOnes;
Data2(find(Data)) = repmat([-3 3],1,nOnes/2)
Data2(find(Data==0)) = repmat([-1 1],1,nZeroes/2)
I'll leave it to you to deal with the odd 1s and 0s.

So, disregarding negative signs, the equation for the output item Data2[loop,1] = Data[loop,1]*2 + 1. So why not first do that using a simple multiply-- that should be fast since it can be vectorized. Then create an array of half the original array length of 1s, half the original array length of -1s, call randperm on that. Then multiply by that. Everything's vectorized and should be much faster.

[row,ll] = size(Data);
sym_zero = -1;
sym_one = -3;
for loop = 1 : row
if ( Data(loop,1) ) // is 1
Data2(loop,1) = sym_one;
sym_one = sym_one * -1; // flip the sign
else
Data2(loop,1) = sym_zero;
sym_zero = sym_zero * -1; // flip the sign
end
end

Related

Check if two lines are intersecting? (if so, not where so)

I saw this asked but I couldn't understand the answers!
I got 4 vector2s, P1 & P2 for line 1, P3 & P4 for line 2.
Code for intersection position works, but how do I check if that intersection is happening?
More specifically, I want to check what side of a polygon an imaginary line is passing through/colliding with
...
...Had something like it working in an old test-script, however I made no annotations and I can't adapt it. I don't know if there's anything here that could be used but thought I'd share:
if rotation_angle > PI/2 && rotation_angle < 3*PI/2:
if rad_overflow(($Position2D.position-position).angle()-PI/2) < rad_overflow(rotation_angle-PI/2) or rad_overflow(($Position2D.position-position).angle()-PI/2) > rad_overflow(rotation_angle+PI/2):
actives.x = 1
else:
actives.x = 0
if rad_overflow(($Position2D2.position-position).angle()-PI/2) < rad_overflow(rotation_angle-PI/2) or rad_overflow(($Position2D2.position-position).angle()-PI/2) > rad_overflow(rotation_angle+PI/2):
actives.y = 1
else:
actives.y = 0
else:
if rad_overflow(($Position2D.position-position).angle()-PI/2) < rad_overflow(rotation_angle-PI/2) && rad_overflow(($Position2D.position-position).angle()-PI/2) > rad_overflow(rotation_angle+PI/2):
actives.x = 1
else:
actives.x = 0
if rad_overflow(($Position2D2.position-position).angle()-PI/2) < rad_overflow(rotation_angle-PI/2) && rad_overflow(($Position2D2.position-position).angle()-PI/2) > rad_overflow(rotation_angle+PI/2):
actives.y = 1
else:
actives.y = 0
var point1 = $Position2D.position
var point2 = $Position2D2.position
var limit3 = Vector2(0,1).rotated(rotation_angle+PI/2)
var limit4 = Vector2(0,1).rotated(rotation_angle-PI/2)
var det = (point1.x - point2.x)*(limit3.y - limit4.y) - (point1.y - point2.y)*(limit3.x - limit4.x)
var new_position = Vector2(
((point1.x*point2.y - point1.y*point2.x) * (limit3.x-limit4.x) - (point1.x-point2.x) * (limit3.x*limit4.y - limit3.y*limit4.x))/det,
((point1.x*point2.y - point1.y*point2.x) * (limit3.y-limit4.y) - (point1.y-point2.y) * (limit3.x*limit4.y - limit3.y*limit4.x))/det)
if actives.x != actives.y:
print("hit")
else:
print("miss")
You ask:
I got 4 vector2s, P1 & P2 for line 1, P3 & P4 for line 2. Code for intersection position works, but how do I check if that intersection is happening?
If you are using Godot, you can use the Geometry class for this, in particular the line_intersects_line_2d method. I quote from the documentation:
Variant line_intersects_line_2d ( Vector2 from_a, Vector2 dir_a, Vector2 from_b, Vector2 dir_b )
Checks if the two lines (from_a, dir_a) and (from_b, dir_b) intersect. If yes, return the point of intersection as Vector2. If no intersection takes place, returns null.
Note: The lines are specified using direction vectors, not end points.
So that gives you both if they intersect (if it returns null they don't intersect) and where (if it does not return null it returns a Vector2 with the position of the intersection).

Struggling with using iteration and println in Julia

I am new to Julia and trying to understand how things work.
Below is the sample code I just wrote.
(This is the baseline code and I am planning to add other lines one by one.)
I expected to see something like 1 2 3 4 5 6 7... from test = check(m)
However, I don't see any result.
Any help will be very much appreciated.
using Pkg
using Optim
using Printf
using LinearAlgebra, Statistics
using BenchmarkTools, Optim, Parameters, QuantEcon, Random
using Optim: converged, maximum, maximizer, minimizer, iterations
using Interpolations
using Distributions
using SparseArrays
using Roots
# ================ 1. Parameters and Constants ============================
mutable struct Model
# Model Parameters and utility function
δ::Float64
function Model(;
δ = 0.018,
)
new(
δ
)
end
end
function check(m)
it = 0
tol=1e-8
itmax = 1000
dif = 0
# Iteration
while it < itmax && dif >=tol
it = it + 1;
V = Vnew;
println(it)
end
return itmax
end
m=Model()
test = check(m)
dif = 0
tol = 1e-8
while it < itmax && dif >= tol
Now explain to me how
dif >= tol

Pandas .loc[] method is too slow, how can I speed it up

I have a dataframe with 40 million rows,and I want to change some colums by
age = data[data['device_name'] == 12]['age'].apply(lambda x : x if x != -1 else max_age)
data.loc[data['device_name'] == 12,'age'] = age
but this method is too slow, how can I speed it up.
Thanks for all reply!
you might wanna change the first part to :
age = data[data['device_name'] == 12]['age']
age[age == -1] = max_age
data.loc[data['device_name'] == 12,'age'] = age
you could use, to me more concise(this could gain you a little speed)
cond = data['device_name'] == 12
age = data.loc[cond, age]
data.loc[cond,'age'] = age.where(age != -1, max_age)

Non-uniform random numbers in Objective-C

I'd like to calculate a non-uniformly distributed random number in the range [0, n - 1]. So the min possible value is zero. The maximum possible value is n-1. I'd like the min-value to occur the most often and the max to occur relatively infrequently with an approximately linear curve between (Gaussian is fine too). How can I do this in Objective-C? (possibly using C-based APIs)
A very rough sketch of my current idea is:
// min value w/ p = 0.7
// some intermediate value w/ p = 0.2
// max value w/ p = 0.1
NSUInteger r = arc4random_uniform(10);
if (r <= 6)
result = 0;
else if (r <= 8)
result = (n - 1) / 2;
else
result = n - 1;
I think you're on basically the right track. There are possible precision or range issues but in general if you wanted to randomly pick, say, 3, 2, 1 or 0 and you wanted the probability of picking 3 to be four times as large as the probability of picking 0 then if it were a paper exercise you might right down a grid filled with:
3 3 3 3
2 2 2
1 1
0
Toss something onto it and read the number it lands on.
The number of options there are for your desired linear scale is:
- 1 if number of options, n, = 1
- 1 + 2 if n = 2
- 1 + 2 + 3 if n = 3
- ... etc ...
It's a simple sum of an arithmetic progression. You end up with n(n+1)/2 possible outcomes. E.g. for n = 1 that's 1 * 2 / 2 = 1. For n = 2 that's 2 * 3 /2 = 3. For n = 3 that's 3 * 4 / 2 = 6.
So you would immediately write something like:
NSUInteger random_linear(NSUInteger range)
{
NSUInteger numberOfOptions = (range * (range + 1)) / 2;
NSUInteger uniformRandom = arc4random_uniform(numberOfOptions);
... something ...
}
At that point you just have to decide which bin uniformRandom falls into. The simplest way is with the most obvious loop:
NSUInteger random_linear(NSUInteger range)
{
NSUInteger numberOfOptions = (range * (range + 1)) / 2;
NSUInteger uniformRandom = arc4random_uniform(numberOfOptions);
NSUInteger index = 0;
NSUInteger optionsToDate = 0;
while(1)
{
if(optionsToDate >= uniformRandom) return index;
index++;
optionsToDate += index;
}
}
Given that you can work out optionsToDate without iterating, an immediately obvious faster solution is a binary search.
An even smarter way to look at it is that uniformRandom is the sum of the boxes underneath a line from (0, 0) to (n, n). So it's the area underneath the graph, and the graph is a simple right-angled triangle. So you can work backwards from the area formula.
Specifically, the area underneath the graph from (0, 0) to (n, n) at position x is (x*x)/2. So you're looking for x, where:
(x-1)*(x-1)/2 <= uniformRandom < x*x/2
=> (x-1)*(x-1) <= uniformRandom*2 < x*x
=> x-1 <= sqrt(uniformRandom*2) < x
In that case you want to take x-1 as the result hadn't progressed to the next discrete column of the number grid. So you can get there with a square root operation simple integer truncation.
So, assuming I haven't muddled my exact inequalities along the way, and assuming all precisions fit:
NSUInteger random_linear(NSUInteger range)
{
NSUInteger numberOfOptions = (range * (range + 1)) / 2;
NSUInteger uniformRandom = arc4random_uniform(numberOfOptions);
return (NSUInteger)sqrtf((float)uniformRandom * 2.0f);
}
What if you try squaring the return value of arc4random_uniform() (or multiplying two of them)?
int rand_nonuniform(int max)
{
int r = arc4random_uniform(max) * arc4random_uniform(max + 1);
return r / max;
}
I've quickly written a sample program for testing it and it looks promising:
int main(int argc, char *argv[])
{
int arr[10] = { 0 };
int i;
for (i = 0; i < 10000; i++) {
arr[rand_nonuniform(10)]++;
}
for (i = 0; i < 10; i++) {
printf("%2d. = %2d\n", i, arr[i]);
}
return 0;
}
Result:
0. = 3656
1. = 1925
2. = 1273
3. = 909
4. = 728
5. = 574
6. = 359
7. = 276
8. = 187
9. = 113

What is the most efficient way to get a random odd or even number?

So off the top of my head, I can think of a few solutions (focusing on getting random odd numbers for example):
int n;
while (n == 0 || n % 2 == 0) {
n = (arc4random() % 100);
}
eww.. right? Not efficient at all..
int n = arc4random() % 100);
if (n % 2 == 0) n += 1;
But I don't like that it's always going to increase the number if it's not odd.. Maybe that shouldn't matter? Another approach could be to randomize that:
int n = arc4random() % 100);
if (n % 2 == 0) {
if (arc4random() % 2 == 0) {
n += 1;
else {
n -= 1;
}
}
But this feels a little bleah to me.. So I am wondering if there is a better way to do this sort of thing?
Generate a random number and then multiply it by two for even, multiply by two plus 1 for odd.
In general, you want to keep these simple or you run the risk of messing up the distribution of numbers. Take the output of the typical [0...1) random number generator and then use a function to map it to the desired range.
FWIW - It doesn't look like you're skewing the distributions above, except for the third one. Notice that getting 99 is less probable than all the others unless you do your adjustments with a modulus incl. negative numbers. Since..
P(99) = P(first roll = 99) + P(first roll = 100 & second roll = -1) + P(first roll = 98 & second roll = +1)
and P(first roll = 100) = 0
If you want a random set of binary digits followed by a fixed digit, then I'd go with bitwise operations:
odd = arc4random() | 1;
even = arc4random() & ~ 1;