Reducing time complexity of bilinear interpolation - java

I use bilinear interpolation in my android application. It runs perfectly, but takes a lot of time to get the result.
I test it when xi = 259,920, and yi also = 259,920. The time to response was: Galaxy Note 4 takes 3 sec,
and HTC One M8 takes about 8 sec !. So what I can change or use to reduce the time?!
The code I use for bilinear interpolation:
public static double[] BiInterp(Mat z, ArrayList < Double > xi, ArrayList < Double > yi) {
// Declare matrix indeces
int xi_i, yi_i;
// Initialize output vector
double zi[] = new double[xi.size()];
double s00, s01, s10, s11;
for (int i = 0; i < xi.size(); i++) { // Note: xi.length = yi.length !
xi_i = xi.get(i).intValue(); // X index without round
yi_i = yi.get(i).intValue(); // Y index without round
if (xi_i < z.rows() - 1 && yi_i < z.cols() - 1 && xi_i >= 0 && yi_i >= 0) {
// Four neighbors of sample pixel
s00 = z.get(xi_i,yi_i)[0]; s01 = z.get(xi_i,yi_i + 1)[0];
s10 = z.get(xi_i + 1,yi_i)[0];s11 = z.get(xi_i + 1,yi_i + 1)[0];
int neighbor_no = 4; // As bilinear interpolation take 4 neighbors
double A[][] = new double[neighbor_no][neighbor_no];
A[0][0]=xi_i; A[0][1]=yi_i; A[0][2]=xi_i*yi_i; A[0][3]=1;
A[1][0]=xi_i; A[1][1]=yi_i+1; A[1][2]=xi_i*(yi_i+1); A[1][3]=1;
A[2][0]=xi_i+1; A[2][1]=yi_i; A[2][2]=(xi_i+1)*yi_i; A[2][3]=1;
A[3][0]=xi_i+1; A[3][1]=yi_i+1; A[3][2]=(xi_i+1)*(yi_i+1); A[3][3]=1;
GaussianElimination solveE = new GaussianElimination();
double b[] = {s00,s01,s10,s11};
double x[] = solveE.solve(A, b);
zi[i] = xi.get(i)*x[0] + yi.get(i)*x[1] + xi.get(i)*yi.get(i)*x[2] + x[3];
}
}
return zi;
}
and I use Gaussian elimination to solve the equation of 4 unknown
private static final double EPSILON = 1e-10;
// Gaussian elimination with partial pivoting
public static double[] solve(double[][] A, double[] b) {
int N = b.length;
for (int p = 0; p < N; p++) {
// find pivot row and swap
int max = p;
for (int i = p + 1; i < N; i++) {
if (Math.abs(A[i][p]) > Math.abs(A[max][p])) {
max = i;
}
}
double[] temp = A[p];
A[p] = A[max];
A[max] = temp;
double t = b[p];
b[p] = b[max];
b[max] = t;
// singular or nearly singular
if (Math.abs(A[p][p]) <= EPSILON) {
throw new RuntimeException("Matrix is singular or nearly singular");
}
// pivot within A and b
for (int i = p + 1; i < N; i++) {
double alpha = A[i][p] / A[p][p];
b[i] -= alpha * b[p];
for (int j = p; j < N; j++) {
A[i][j] -= alpha * A[p][j];
}
}
}
// back substitution
double[] x = new double[N];
for (int i = N - 1; i >= 0; i--) {
double sum = 0.0;
for (int j = i + 1; j < N; j++) {
sum += A[i][j] * x[j];
}
x[i] = (b[i] - sum) / A[i][i];
}
return x;
}
As you see in the bilinear code, I take the pixels intensities immediately from the Mat object. However, when I used matrix it takes much less time, such as with note 4 takes 1 sec.
But to convert from Mat image to matrix takes 4 sec. So I preferred to use Mat.

Here is a more simple bilinear interpolation algorithm:
Find the fractional part of yi and use it to interpolate between s00 and s01 to find s0, and between s10 and s11 to find s1
Find the fractional part of xi and use it to interpolate between s0 and s1 to find zi
Basically you are decomposing it into three simple linear interpolations. You can visualize it as an H shape. First you interpolate down the left and right posts of the H to get values part way down each. Then you interpolate along the cross-beam to get the final value in the middle.
The code would be something like this:
xi_i = xi.get(i).intValue(); // X index without round
yi_i = yi.get(i).intValue(); // Y index without round
if (xi_i < z.rows() - 1 && yi_i < z.cols() - 1 && xi_i >= 0 && yi_i >= 0) {
// Four neighbors of sample pixel
s00 = z.get(xi_i,yi_i)[0]; s01 = z.get(xi_i,yi_i + 1)[0];
s10 = z.get(xi_i + 1,yi_i)[0];s11 = z.get(xi_i + 1,yi_i + 1)[0];
// find fractional part of yi:
double yi_frac = yi.get(i) - (double)yi_i;
// interpolate between s00 and s01 to find s0:
double s0 = s00 + ((s01 - s00) * yi_frac);
// interpolate between s10 and s11 to find s1:
double s1 = s10 + ((s11 - s10) * yi_frac);
// find fractional part of xi:
double xi_frac = xi.get(i) - (double)xi_i;
// interpolate between s0 and s1 to find zi:
zi[i] = s0 + ((s1 - s0) * xi_frac);
}
You could also speed the whole thing up (at the expense of accuracy) by using fixed point integers instead of doubles.

Related

Finding the smallest distance between origin and coordinates (larger than radius) in Java

Given a radius, find the coordinates (x, y) such that the distance between (x, y) to the origin is greater than the radius. However, I want to find the distance that is the smallest distance that is greater than the radius. Problem is seen here: open.kattis.com/problems/discdistrict. My code works well for radii that are less than or equal to 5000. However, for large radii, my code starts to break and takes exponentially longer to finish!! Are there any ideas?
Examples: 1 yields (1, 1). 5 yields (2, 5). 10 yields (5, 9). (radius | radius >= 10,000) takes an exponentially long period of time.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
public class disc_district {
public static void main(String[] args) {
Scanner new_scanner = new Scanner(System.in);
int radius = new_scanner.nextInt();
new_scanner.close();
//ArrayList<Double> new_distance = new ArrayList<>();
double min_max_dist = Double.MAX_VALUE - 1;
int[] new_min_pair = new int[2];
for (int i = (radius / 2); i <= radius; i++) {
int start = (int)Math.floor(Math.sqrt(Math.pow(radius, 2) - Math.pow(i, 2))) + 1;
for (int j = Math.max(i, start); j <= radius; j++) {
//for (int j = i; j <= radius; j++) {
double new_dist = Math.sqrt(Math.pow(i, 2) + Math.pow(j, 2));
if (new_dist > radius) {
if (min_max_dist > new_dist) {
min_max_dist = new_dist;
new_min_pair[0] = i;
new_min_pair[1] = j;
}
}
}
}
System.out.println(new_min_pair[0] + " " + new_min_pair[1]);
}
}
Thanks again!
It does not takes an exponential time to finish, just a quadratic time, that is O(radius² / 4). This is because you use 2 nested loops. You can speed up the inner-most loop by just solving a basic conic inequation.
Indeed, you are searching for j values where sqrt(i² + j²) > r with r = radius. This means i² + j² > r² since all values are expected to be positives ones. This means j² > r² - i² and so j > sqrt(r² - i²). As a result, you can start the second inner loop to the value Math.sqrt(Math.pow(r, 2) - Math.pow(i, 2)) if it is bigger than i (note that the expression in the square root is always positive since i <= r).
The resulting code is:
for (int i = (radius / 2); i <= radius; i++) {
int start = (int)Math.floor(Math.sqrt(Math.pow(radius, 2) - Math.pow(i, 2))) + 1;
for (int j = Math.max(i, start); j <= radius; j++) {
System.out.println(i + " " + j);
}
}
Note that if you want to get one value, you can just use a break instruction so to avoid many unneeded computations.
Assuming the initial code is correct and you really need all the values to be printed, the complexity of the new code is optimal (each iteration is done in a constant time and is strictly useful since it results in a printed line), but it is still quadratic. A deeper analysis of the code shows its (optimal) complexity is O(radius² / 11.68). Thus the new code is only about ~3 times faster in theory. It can still be slow since there are a lot of values to be printed. It may be interesting to better control when the output is flushed.
Update:
Based on the additional information (about the distance being minimized and only one solution required to be printed), here is the resulting code:
double min_max_dist = Double.MAX_VALUE - 1;
int[] new_min_pair = new int[2];
for (int i = (radius / 2); i <= radius; i++) {
int start = (int)Math.floor(Math.sqrt(Math.pow(radius, 2) - Math.pow(i, 2))) + 1;
int j = Math.max(i, start);
double new_dist = Math.sqrt(Math.pow(i, 2) + Math.pow(j, 2));
if (new_dist > radius) {
if (min_max_dist > new_dist) {
min_max_dist = new_dist;
new_min_pair[0] = i;
new_min_pair[1] = j;
}
}
}
System.out.println(new_min_pair[0] + " " + new_min_pair[1]);
This code find the solution that minimize the distance. It runs in O(n/2) time, that is, a linear time.

modify perceptron to become gradient descent

According to this video the substantive difference between the perceptron and gradient descent algorithms are quite minor. They specified it as essentially:
Perceptron: Δwi = η(y - &ycirc;)xi
Gradient Descent: Δwi = η(y - α)xi
I've implemented a working version of the perceptron algorithm, but I don't understand what sections I need to change to turn it into gradient descent.
Below is the load-bearing portions of my perceptron code, I suppose that these are the components I need to modify. But where? What do I need to change? I don't understand.
This is left for pedagogical reasons, I've sort of figured this out but am still confused about the gradient, please see UPDATE below
iteration = 0;
do
{
iteration++;
globalError = 0;
//loop through all instances (complete one epoch)
for (p = 0; p < number_of_files__train; p++)
{
// calculate predicted class
output = calculateOutput( theta, weights, feature_matrix__train, p, globo_dict_size );
// difference between predicted and actual class values
localError = outputs__train[p] - output;
//update weights and bias
for (int i = 0; i < globo_dict_size; i++)
{
weights[i] += ( LEARNING_RATE * localError * feature_matrix__train[p][i] );
}
weights[ globo_dict_size ] += ( LEARNING_RATE * localError );
//summation of squared error (error value for all instances)
globalError += (localError*localError);
}
/* Root Mean Squared Error */
if (iteration < 10)
System.out.println("Iteration 0" + iteration + " : RMSE = " + Math.sqrt( globalError/number_of_files__train ) );
else
System.out.println("Iteration " + iteration + " : RMSE = " + Math.sqrt( globalError/number_of_files__train ) );
}
while(globalError != 0 && iteration<=MAX_ITER);
This is the crux of my perceptron:
static int calculateOutput( int theta, double weights[], double[][] feature_matrix, int file_index, int globo_dict_size )
{
//double sum = x * weights[0] + y * weights[1] + z * weights[2] + weights[3];
double sum = 0;
for (int i = 0; i < globo_dict_size; i++)
{
sum += ( weights[i] * feature_matrix[file_index][i] );
}
//bias
sum += weights[ globo_dict_size ];
return (sum >= theta) ? 1 : 0;
}
Is it just that I replace that caculateOutput method with something like this:
public static double [] gradientDescent(final double [] theta_in, final double alpha, final int num_iters, double[][] data )
{
final double m = data.length;
double [] theta = theta_in;
double theta0 = 0;
double theta1 = 0;
for (int i = 0; i < num_iters; i++)
{
final double sum0 = gradientDescentSumScalar0(theta, alpha, data );
final double sum1 = gradientDescentSumScalar1(theta, alpha, data);
theta0 = theta[0] - ( (alpha / m) * sum0 );
theta1 = theta[1] - ( (alpha / m) * sum1 );
theta = new double [] { theta0, theta1 };
}
return theta;
}
UPDATE EDIT
At this point I think I'm very close.
I understand how to calculate the hypothesis and I think I've done that correctly, but nevertheless, something remains terribly wrong with this code. I'm pretty sure it has something to do with my calculation of the gradient. When I run it the error fluctuates wildly and then goes to infinity then just NaaN.
double cost, error, hypothesis;
double[] gradient;
int p, iteration;
iteration = 0;
do
{
iteration++;
error = 0.0;
cost = 0.0;
//loop through all instances (complete one epoch)
for (p = 0; p < number_of_files__train; p++)
{
// 1. Calculate the hypothesis h = X * theta
hypothesis = calculateHypothesis( theta, feature_matrix__train, p, globo_dict_size );
// 2. Calculate the loss = h - y and maybe the squared cost (loss^2)/2m
cost = hypothesis - outputs__train[p];
// 3. Calculate the gradient = X' * loss / m
gradient = calculateGradent( theta, feature_matrix__train, p, globo_dict_size, cost, number_of_files__train);
// 4. Update the parameters theta = theta - alpha * gradient
for (int i = 0; i < globo_dict_size; i++)
{
theta[i] = theta[i] - LEARNING_RATE * gradient[i];
}
}
//summation of squared error (error value for all instances)
error += (cost*cost);
/* Root Mean Squared Error */
if (iteration < 10)
System.out.println("Iteration 0" + iteration + " : RMSE = " + Math.sqrt( error/number_of_files__train ) );
else
System.out.println("Iteration " + iteration + " : RMSE = " + Math.sqrt( error/number_of_files__train ) );
//System.out.println( Arrays.toString( weights ) );
}
while(cost != 0 && iteration<=MAX_ITER);
}
static double calculateHypothesis( double[] theta, double[][] feature_matrix, int file_index, int globo_dict_size )
{
double hypothesis = 0.0;
for (int i = 0; i < globo_dict_size; i++)
{
hypothesis += ( theta[i] * feature_matrix[file_index][i] );
}
//bias
hypothesis += theta[ globo_dict_size ];
return hypothesis;
}
static double[] calculateGradent( double theta[], double[][] feature_matrix, int file_index, int globo_dict_size, double cost, int number_of_files__train)
{
double m = number_of_files__train;
double[] gradient = new double[ globo_dict_size];//one for bias?
for (int i = 0; i < gradient.length; i++)
{
gradient[i] = (1.0/m) * cost * feature_matrix[ file_index ][ i ] ;
}
return gradient;
}
The perceptron rule is just an approximation to the gradient descent when you have non-differentiable activation functions like (sum >= theta) ? 1 : 0. As they ask in the end of the video, you cannot use gradients there because this threshold function isn't differentiable (well, its gradient is not defined for x=0 and the gradient is zero everywhere else). If, instead of this thresholding, you had a smooth function like the sigmoid you could calculate the actual gradients.
In that case your weight update would be LEARNING_RATE * localError * feature_matrix__train[p][i] * output_gradient[i]. For the case of sigmoid, the link I sent you also shows how to calculate the output_gradient.
In summary to change from perceptrons to gradient descent you have to
Use an activation function whose derivative (gradient) is not zero
everywhere.
Apply the chain rule to define the new update rule

finding the length given the coordinates for a polygon

I'm working on a question where i need to find the length of the side given the coordinates of a polygon.
N is the number of rows and 2 is number of columns ( x and y coordinates) and i've collected the coordinates in a multi-dimensional array.
what my idea was to collect the x coordinates in a array say x1 and collect y coordinates in a array say y1. now find the difference between the numbers in the array and perform the distance formula operation. but im not able to proceed any further. im not able to find the length using it as the answer is always short of the actual number. kindly help on how can i find the length of the sides of a given polygon. please find my code below:
import java.util.Scanner;
public class Rope {
public static void main(String[] args) {
int N = 1, R=1;
double AoN=1;
float d=0 , e=0, f=0, h=0, s=0, length=0, g=0;;
Scanner in = new Scanner(System.in);
int[] arr = new int[2];
System.out.println("Enter number of Nails (N) and Radius of Nail (R) seperated by space: ");
for (int i=0;i<arr.length;i++) {
arr[i]=in.nextInt();
}
if (arr[0]>=1 && arr[0]<=100) {
N=arr[0]; // N is the number of rows of the multi-dimensional array and rows is fixed to 2 as coordinates are fixed to x and y so 2.
}
R=arr[1]; // kindly ignore R as it is used for other purpose.
float[ ][ ] arr1 = new float[N][2];
System.out.println("Enter Coordinates separated by spaces: ");
for(int i=0; i<N;i++) {
for (int j=0;j<2;j++) {
arr1[i][j]=in.nextFloat();
//System.out.println(arr1[i][j]);
}
}
float[] x = new float[N];
float[] y = new float[N];
for(int i=0; i<N;i++) {
x[i] = arr1[i][0];
}
for (int j=0;j<N;j++) {
y[j] = arr1[j][1];
}
for (int i=0; i<x.length-1;i++) {
d = (float) (d + (Math.pow((x[i+1] - x[i]),2)));
}
for (int i=0; i<y.length-1;i++) {
e = (float) (e + (Math.pow((y[i+1] - y[i]),2)));
}
g = d+e;
s = (float) Math.sqrt(g);
sysout(s);
in.close();
}
}
because you have a logical glitch in your code. Here if you notice in the following section :
for (int i=0; i<x.length-1;i++) {
d = (float) (d + (Math.pow((x[i+1] - x[i]),2)));
}
for (int i=0; i<y.length-1;i++) {
e = (float) (e + (Math.pow((y[i+1] - y[i]),2)));
}
Lets say,
x1-x2 = X1
x2-x3 = X2
and so on
similarly,
y1-y2 = Y1
y2-y3 = Y2
and so on
now what your code does is it calculates
sqrt(X1*X1 + X2*X2.... +Y1*Y1 + Y2*Y2....)
But what actually it is supposed to do is,
sqrt(Math.pow((X1-X2),2) + Math.pow(Y1-Y2),2)) + sqrt (Math.pow((X2-X3),2) + Math.pow((Y2-Y3), 2) + ...
thus your code generates wrong values.
You should try the following :
for (int i=0; i<x.length-1;i++) {
float temp;
temp = (Math.pow((x[i+1] - x[i]),2)) + (Math.pow((y[i+1] - y[i]),2));
d = (float) (d + sqrt(temp));
}
// for first and last values / coordinates w.r.t distance formula
for (int i=x.length-1; i<x.length;i++) {
float temp;
temp = (float) ((Math.pow((x[i] - x[0]),2)) + (Math.pow((y[i] - y[0]),2)));
d = (float) (d + Math.sqrt(temp));
}
Instead of that above mentioned two lines.
Hope this helps !!!

Cut a polygon into 4 parts with equals area. java

I need to cut a convex not simple polygon by two perpendicular lines to divide it into 4 equal(area) parts.
I wrote a program, but it does not pass tests.
I think the reason is rounding errors or my function of calculating area.
Please check it, is it correct?
I use shoelace algorithm and heron's formula
Here is the code:
double calcArea() {
double result = 0;
if (size() > 4) {
int j = size() - 1;
for (int i = 0; i < size() - 1; i++) {
result += (points.get(i).getX() + points.get(j).getX())
*
(points.get(j).getY() - points.get(i).getY());
j = i;
}
result = result / (result >= 0 ? 2. : -2.);
} else if(size() == 3) {
double c,a,b, p;
c = Math.sqrt(Math.pow(points.get(0).getY()-points.get(1).getY(),2)+Math.pow(points.get(0).getX()-points.get(1).getX(),2));
a = Math.sqrt(Math.pow(points.get(1).getY()-points.get(2).getY(),2)+Math.pow(points.get(1).getX()-points.get(2).getX(),2));
b = Math.sqrt(Math.pow(points.get(0).getY()-points.get(2).getY(),2)+Math.pow(points.get(0).getX()-points.get(2).getX(),2));
p = (a + b + c) / 2.;
return Math.sqrt(p*(p-a)*(p-b)*(p-c));
}
return result;
}
What I do in:
finding of point(x, y) of cutting polygon.
I cut it by x = a in [ min(x), max(x)]
and calculate S'(part of polygon from x=min(x) to x=a)
if S' = S/2 , i take a for calculating value(a, *)
then the same with y = b whereb in [min(y), max(y)]
Is there more fast method?

FFT for a single frequency

I need to get the amplitude of a signal at a certain frequency.
I use FFTAnalysis function. But I get all spectrum. How can I modify this for get the amplitude of a signal at a certain frequency?
For example I have:
data = array of 1024 points;
If I use FFTAnalysis I get FFTdata array of 1024 points.
But I need only FFTdata[454] for instance ();
public static float[] FFTAnalysis(short[] AVal, int Nvl, int Nft) {
double TwoPi = 6.283185307179586;
int i, j, n, m, Mmax, Istp;
double Tmpr, Tmpi, Wtmp, Theta;
double Wpr, Wpi, Wr, Wi;
double[] Tmvl;
float[] FTvl;
n = Nvl * 2;
Tmvl = new double[n];
FTvl = new float[Nvl];
for (i = 0; i < Nvl; i++) {
j = i * 2; Tmvl[j] = 0; Tmvl[j+1] = AVal[i];
}
i = 1; j = 1;
while (i < n) {
if (j > i) {
Tmpr = Tmvl[i]; Tmvl[i] = Tmvl[j]; Tmvl[j] = Tmpr;
Tmpr = Tmvl[i+1]; Tmvl[i+1] = Tmvl[j+1]; Tmvl[j+1] = Tmpr;
}
i = i + 2; m = Nvl;
while ((m >= 2) && (j > m)) {
j = j - m; m = m >> 1;
}
j = j + m;
}
Mmax = 2;
while (n > Mmax) {
Theta = -TwoPi / Mmax; Wpi = Math.sin(Theta);
Wtmp = Math.sin(Theta / 2); Wpr = Wtmp * Wtmp * 2;
Istp = Mmax * 2; Wr = 1; Wi = 0; m = 1;
while (m < Mmax) {
i = m; m = m + 2; Tmpr = Wr; Tmpi = Wi;
Wr = Wr - Tmpr * Wpr - Tmpi * Wpi;
Wi = Wi + Tmpr * Wpi - Tmpi * Wpr;
while (i < n) {
j = i + Mmax;
Tmpr = Wr * Tmvl[j] - Wi * Tmvl[j-1];
Tmpi = Wi * Tmvl[j] + Wr * Tmvl[j-1];
Tmvl[j] = Tmvl[i] - Tmpr; Tmvl[j-1] = Tmvl[i-1] - Tmpi;
Tmvl[i] = Tmvl[i] + Tmpr; Tmvl[i-1] = Tmvl[i-1] + Tmpi;
i = i + Istp;
}
}
Mmax = Istp;
}
for (i = 0; i < Nft; i++) {
j = i * 2; FTvl[Nft - i - 1] = (float) Math.sqrt((Tmvl[j]*Tmvl[j]) + (Tmvl[j+1]*Tmvl[j+1]));
}
return FTvl;
}
The Goertzel algorithm (or filter) is similar to computing the magnitude for just 1 bin of an FFT.
The Goertzel algorithm is identical to 1 bin of an FFT, except for numerical artifacts, if the period of the frequency is an exact submultiple of your Goertzel filter's length. Otherwise there are some added scalloping effects from a rectangular window of non-periodic-in-aperture size, and how that window relates to the phase of the input.
Multiplying by a complex sinusoid and taking the magnitude of the complex sum is also computationally similar to a Goertzel, except the Goertzel does not require separately calling (or looking up) a trig library function every point, as it usually includes a trig recursion at part of its algorithm.
You'd multiply a (complex) sine wave on the input data, and integrate the result.
Multiplying with a complex sine is equal to a frequency shift, you want to shift the target frequency down to 0 Hz. The integration is a low pass filtering step, with the bandwidth being the inverse of the sampling length.
You then end up with a complex number, which is the same number you would have found in the FFT bin for this frequency (because in essence this is what the FFT does).
The fast fourier transform (FFT) is a clever way of doing many discrete fourier transforms very quickly. As such, the FFT is designed for when one needs a lot of frequencies from the input. If you want just one frequency, the DFT is the way to go (as otherwise you're wasting resources).
The DFT is defined as:
So, in pseudocode:
samples = [#,#,#,#...]
FREQ = 440; // frequency to detect
PI = 3.14159;
E = 2.718;
DFT = 0i; // this is a complex number
for(int sampleNum=0; sampleNum<N; sampleNum++){
DFT += samples[sampleNum] * E^( (-2*PI*1i*N) / N ); //Note that "i" here means imaginary
}
The resulting variable DFT will be a complex number representing the real and imaginary values of the chosen frequency.

Categories