currently i am trying to perform an FFT on AudioData collected with AudioRecord. My Problem is that every Value is 0 after the FFT. I have no idea why.
I am using the Following code for the FFT (from FFT library in android Sdk). The number of samples is even! (8192)
public class FFT {
int n, m;
// Lookup tables. Only need to recompute when size of FFT changes.
double[] cos;
double[] sin;
public FFT(int n) {
this.n = n;
this.m = (int) (Math.log(n) / Math.log(2));
// Make sure n is a power of 2
if (n != (1 << m))
throw new RuntimeException("FFT length must be power of 2");
// precompute tables
cos = new double[n / 2];
sin = new double[n / 2];
for (int i = 0; i < n / 2; i++) {
cos[i] = Math.cos(-2 * Math.PI * i / n);
sin[i] = Math.sin(-2 * Math.PI * i / n);
}
}
public void fft(double[] x, double[] y) {
int i, j, k, n1, n2, a;
double c, s, t1, t2;
// Bit-reverse
j = 0;
n2 = n / 2;
for (i = 1; i < n - 1; i++) {
n1 = n2;
while (j >= n1) {
j = j - n1;
n1 = n1 / 2;
}
j = j + n1;
if (i < j) {
t1 = x[i];
x[i] = x[j];
x[j] = t1;
t1 = y[i];
y[i] = y[j];
y[j] = t1;
}
}
// FFT
n1 = 0;
n2 = 1;
for (i = 0; i < m; i++) {
n1 = n2;
n2 = n2 + n2;
a = 0;
for (j = 0; j < n1; j++) {
c = cos[a];
s = sin[a];
a += 1 << (m - i - 1);
for (k = j; k < n; k = k + n2) {
t1 = c * x[k + n1] - s * y[k + n1];
t2 = s * x[k + n1] + c * y[k + n1];
x[k + n1] = x[k] - t1;
y[k + n1] = y[k] - t2;
x[k] = x[k] + t1;
y[k] = y[k] + t2;
}
}
}
}
}
This is the code to calculate the Frequency:
private void writeToScreen()
{
while(isRecording)
{
double[] y = new double[bufferSize];
for (int i = 0; i < y.length; i++) {
y[i]=0;
}
double[] x = new double[bufferSize];
//short[] to double[]
for (int i = 0; i < x.length; i++)
{
x[i]= audioBuffer[i]/32768;
}
//perform fft
fft meinfft = new fft(bufferSize);
meinfft.FFT(x, y);
System.out.println("Alle Werte x und y nach FFT:");
for (int i = 0; i < x.length; i++) { //Every Value is 0.0
if(x[i] != 0 || y[i] != 0)
System.out.println("x["+i+"]: "+ x[i] +" y["+i+"]: "+y[i]);
}
System.out.println("Ende Aller Werte");
// calculate index of max Value
int maxIndex =0;
for (int i = 1; i < x.length; i++) {
if(Math.sqrt(x[i]*x[i]+y[i]*y[i]) > Math.sqrt(x[maxIndex]*x[maxIndex]+y[maxIndex]*y[maxIndex]) )
{
maxIndex = i;
}
}
System.out.println("Index des Maximums: "+maxIndex);
double freq = ((1.0 * sampleRate) / (1.0 * bufferSize)) * maxIndex; //Frequency is always 0
System.out.println("wahrscheinliche Frequenz: "+freq);
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{}
}
System.out.println("Writethread beendet");
}
Unfortunately i dosn't know very much about FFT. I could imagine that the Transformation from short[] to double[] is wrong or the complete FFT itself. I hope someone can help me.
If you want to try you'll find the complete code below:
import java.io.IOException;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.LinearLayout;
import android.widget.TextView;
//import android.os.Bundle;
import android.os.Environment;
import android.view.ViewGroup;
import android.widget.Button;
import android.view.View;
import android.view.View.OnClickListener;
import android.content.Context;
import android.util.Log;
import android.media.MediaRecorder;
import android.media.MediaPlayer;
import de.benediktbock.fft.fft;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder.AudioSource;
import java.io.IOException;
public class MainActivity extends Activity {
private static final String LOG_TAG = "FFTTEST";
private PlayButton mPlayButton = null;
private TextView realTeil = null;
private TextView imgTeil = null;
private fft mFFT = null;
private int channel_config = AudioFormat.CHANNEL_IN_MONO;
private int format = AudioFormat.ENCODING_PCM_16BIT;
private int sampleRate = 8000;
private int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channel_config, format);
private AudioRecord audioInput = null; //new AudioRecord(AudioSource.MIC, sampleSize, channel_config, format, bufferSize);
private short[] audioBuffer = new short[bufferSize];
private Thread readingThread = null,writingThread=null;
private boolean isRecording = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout ll = new LinearLayout(this);
mPlayButton = new PlayButton(this);
ll.addView(mPlayButton,new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
realTeil = new TextView(this);
ll.addView(realTeil,new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
imgTeil = new TextView(this);
ll.addView(imgTeil,new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
setContentView(ll);
realTeil.setText("Realteil");
imgTeil.setText("Imaginärteil");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
class PlayButton extends Button {
boolean mStartPlaying = true;
OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {
onPlay(mStartPlaying);
if (mStartPlaying) {
setText("Stop");
} else {
setText("Start");
}
mStartPlaying = !mStartPlaying;
}
};
public PlayButton(Context ctx) {
super(ctx);
setText("Start");
setOnClickListener(clicker);
}
}
private void onPlay(boolean start) {
if (start) {
startRecording();
} else {
stopRecording();
}
}
private void startRecording()
{
audioInput = new AudioRecord(AudioSource.MIC, sampleRate, channel_config, format, bufferSize);
audioInput.startRecording();
isRecording = true;
readingThread = new Thread(new Runnable()
{
#Override
public void run()
{
readAudioToBuffer();
}
},"readAudio Thread");
readingThread.start();
writingThread = new Thread(new Runnable()
{
#Override
public void run()
{
writeToScreen();
}
},"write Thread");
writingThread.start();
}
private void writeToScreen()
{
while(isRecording)
{
double[] y = new double[bufferSize];
for (int i = 0; i < y.length; i++) {
y[i]=0;
}
double[] x = new double[bufferSize];
//short[] to double[]
for (int i = 0; i < x.length; i++)
{
x[i]= audioBuffer[i]/32768;
}
//perform fft
fft meinfft = new fft(bufferSize);
meinfft.FFT(x, y);
System.out.println("Alle Werte x und y nach FFT:");
for (int i = 0; i < x.length; i++) { //Every Value is 0.0
if(x[i] != 0 || y[i] != 0)
System.out.println("x["+i+"]: "+ x[i] +" y["+i+"]: "+y[i]);
}
System.out.println("Ende Aller Werte");
// calculate index of max Value
int maxIndex =0;
for (int i = 1; i < x.length; i++) {
if(Math.sqrt(x[i]*x[i]+y[i]*y[i]) > Math.sqrt(x[maxIndex]*x[maxIndex]+y[maxIndex]*y[maxIndex]) )
{
maxIndex = i;
}
}
System.out.println("Index des Maximums: "+maxIndex);
double freq = ((1.0 * sampleRate) / (1.0 * bufferSize)) * maxIndex; //Frequency is always 0
System.out.println("wahrscheinliche Frequenz: "+freq);
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{}
}
System.out.println("Writethread beendet");
}
private void readAudioToBuffer()
{
while(isRecording)
{
audioInput.read(audioBuffer, 0,bufferSize);
}
System.out.println("Thread wurde beendet");
}
private void stopRecording()
{
isRecording = false;
audioInput.stop();
audioInput.release();
audioInput= null;
readingThread = null;
}
}
Your inputs are all 0.
short s = 32767;
double d = s/32768;
System.out.println("dividing a short yields a truncated result " + d);
d = (double) s / 32768;
System.out.println("casting to a double and then dividing yields " + d);
Related
So i'm trying to implement a parallell version of the Sieve in Java. I'm pretty sure my algorithm is very close to working, it works well for finding all primes up to a small number, (n < 1000 ish) but when the number gets bigger, the sieve finds a small amount of non prime numbers.
An example run with n = 10000000, and the sieve finds 664627 supposed primes numbers, while the actual correct number of primes is 664579. So it marked 48 non-primes as primes. If anyone would be able to take a look at the code below and provide some pointers, that would be greatly appreciated. The code can be compiled and run with Javac Oblig3.java - > java Oblig3 where n is a positive integer and is the max value for n and i is a positive integer and the number of threads to be used.
import java.util.Arrays;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.locks.ReentrantLock;
class Worker implements Runnable {
int n;
int id;
int numOfThreads;
int elementsPerThread;
Oblig3 parent;
int[] primesLessThanRoot;
byte[] oddNumbers;
CyclicBarrier barrier;
ReentrantLock lock;
Worker(int n, int id, int numOfThreads, int[] primesLessThanRoot, Oblig3 parent,
CyclicBarrier barrier,ReentrantLock lock) {
this.n = n;
this.id = id;
this.numOfThreads = numOfThreads;
this.primesLessThanRoot = primesLessThanRoot;
this.elementsPerThread = (int) (primesLessThanRoot.length / numOfThreads);
this.parent = parent;
this.barrier = barrier;
this.lock = lock;
}
private void mark(int num) {
int bitIndex = (num % 16) / 2;
int byteIndex = num / 16;
parent.oddNumbers[byteIndex] |= (1 << bitIndex);
}
#Override
public void run() {
if(id==1){
System.out.println(primesLessThanRoot.length + " " + numOfThreads);
}
int index = id;
while(index < primesLessThanRoot.length){
int count = 3;
int currentNum = primesLessThanRoot[index] * count;
while(currentNum <= n){
if(currentNum % 2 == 1){
mark(currentNum);
// System.out.println("ID: " + id + " marking:" + currentNum + "( " +
primesLessThanRoot[index] + " * " + count + " )");
}
count += 2;
currentNum = primesLessThanRoot[index] * count;
}
index += numOfThreads;
}
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Oblig3 {
int root, n, threads, numOfPrimes;
byte[] oddNumbers;
Long startTime;
Long endTime;
Long totalTime;
Oblig3(int n, int threads) {
this.n = n;
this.threads = threads;
root = (int) Math.sqrt(n);
oddNumbers = new byte[(n / 16) + 1];
}
public static void main(String[] args) {
int n;
int threads;
try {
n = Integer.parseInt(args[0]);
threads = Integer.parseInt(args[1]);
if (threads > Runtime.getRuntime().availableProcessors()) {
System.out.println("More threads than available cores, setting threads to
max available cores");
threads = Runtime.getRuntime().availableProcessors();
}
Oblig3 oblig3 = new Oblig3(n, threads);
oblig3.sieveParallell();
int[] primes = oblig3.getPrimes();
SieveOfEratosthenes soe = new SieveOfEratosthenes(n);
Long soeStart = System.nanoTime();
int[] soePrimes = soe.getPrimes();
Long soeTotal = (System.nanoTime() - soeStart);
System.out.println("Parallell time: " + oblig3.totalTime);
System.out.println("Sequential time: " + soeTotal);
System.out.println(primes.length);
System.out.println(soePrimes.length);
System.out.println(Arrays.equals(primes, soePrimes));
} catch (Exception e) {
e.printStackTrace();
System.out.println("Invalid input");
}
}
void sieveParallell() {
CyclicBarrier barrier;
ReentrantLock lock = new ReentrantLock();
byte[] oddNumbers = new byte[(n / 16) + 1];
startTime = System.nanoTime();
SieveOfEratosthenes soe = new SieveOfEratosthenes((int) Math.sqrt(n));
int[] primesLessThanRoot = soe.getPrimes();
if (primesLessThanRoot.length > threads) {
barrier = new CyclicBarrier(threads + 1);
for (int i = 0; i < threads; i++) {
Worker worker = new Worker(n, i + 1, threads, primesLessThanRoot, this,
barrier, lock);
Thread t = new Thread(worker);
t.start();
}
} else {
barrier = new CyclicBarrier(primesLessThanRoot.length);
for (int i = 0; i < primesLessThanRoot.length - 1; i++) {
Worker worker = new Worker(n, i + 1, threads, primesLessThanRoot, this,
barrier, lock);
Thread t = new Thread(worker);
t.start();
}
}
try {
barrier.await();
endTime = System.nanoTime();
totalTime = endTime - startTime;
} catch (InterruptedException | BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
boolean isPrime(int num) {
int bitIndex = (num % 16) / 2;
int byteIndex = num / 16;
return (oddNumbers[byteIndex] & (1 << bitIndex)) == 0;
}
int[] getPrimes() {
if (n <= 1)
return new int[0];
return collectPrimes();
}
private int[] collectPrimes() {
int start = (root % 2 == 0) ? root + 1 : root + 2;
for (int i = start; i <= n; i += 2)
if (isPrime(i))
numOfPrimes++;
int[] primesWith0 = new int[(int) (numOfPrimes * 1.2)];
primesWith0[0] = 2;
int j = 1;
for (int i = 3; i <= n; i += 2)
if (isPrime(i))
primesWith0[j++] = i;
int count = 0;
for(int num : primesWith0){
if(num != 0){
count ++;
}
}
int [] primes = new int[count];
for(int i = 0; i < count; i++){
primes[i] = primesWith0[i];
}
return primes;
}
static void printPrimes(int[] primes) {
for (int prime : primes)
System.out.println(prime);
}
static boolean isEqual(int[] a, int[] b) {
boolean status = true;
if(a.length == b.length){
for(int i = 0; i < a.length; i++){
if(a[i] != b[i]){
System.out.println(String.format("A[%d]: %d B[%d]: %d", i, a[i], i,
b[i]));
status = false;
}
}
}
else{
if(a.length > b.length){
for (int i = 0; i < b.length; i++) {
if (a[i] != b[i]) {
System.out.println(String.format("A[%d]: %d B[%d]: %d", i, a[i], i,
b[i]));
status = false;
}
}
}
else{
for (int i = 0; i < a.length; i++) {
if (a[i] != b[i]) {
System.out.println(String.format("A[%d]: %d B[%d]: %d", i, a[i], i,
b[i]));
status = false;
}
}
}
}
return status;
}
}
I have been trying to code a sinc low pass filter to be used on sound waves in java.
I have been following this code here https://tomroelandts.com/articles/how-to-create-a-simple-low-pass-filter
I then got to the part on convulving the waveform with the filter output and thought convulving had to happen with arrays, but since the sight's code is in python, I cannot tell the arrays from the other variables. Most of what I came up with on convulving needed arrays to function properly and since it seemed to multiply one value with another, that was how I coded it.
What should I be doing and are there other mistakes with my code?
Also, would I be able to apply resonance to this filter?
The method lowPass(double point) is meant to take a sample, low pass filter it and return it.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package effects;
/**
*
* #author Edward Jenkins
*/
public class SincLowPassFilter {
public static final double DEF_BAND = 0;
// instance variables
private double cutoffFrequency;
private double resonance;
private double sampleRate;
private double value;
private double sumnatedValue;
private double cutoffAmount;
private double resonanceAmount;
private double transitionBand;
private double window;
private int n;
private int index;
// constructor
public SincLowPassFilter(double cutoffFrequency, double resonance,
double sampleRate, double band) {
this.cutoffFrequency = cutoffFrequency;
cutoffAmount = cutoffFrequency / sampleRate;
transitionBand = band / sampleRate;
n = (int)Math.ceil(4 / transitionBand);
if (!(n % 2 == 2)) {
n += 1;
}
sumnatedValue = 0;
for(int i = 0; i < n; i++) {
value = sinc(2 * cutoffAmount * (i - (n - 1) / 2));
window = 0.42 - 0.5 * Math.cos(2 * Math.PI * i / (n - 1)
/ 0.08 * Math.cos(4 * Math.PI * i / (n - 1)));
value = value * window;
sumnatedValue += value;
value = value / sumnatedValue;
}
}
// low pass filter
public double lowPass(double point) {
return point * value;
}
// sinc
private double sinc(double value) {
return Math.sin(Math.PI * value) / Math.PI * value;
}
}
Thanks to the folks on stack exchange, I ended up with this. But this uses a sub class to implement
Super class:
package filters;
import sound.generator.waveforms.SamplePlayer;
import sound.generator.waveforms.ISamplePlayer;
/**
*
* #author Edward Jenkins
* #version 1.2
*/
public abstract class SincSpecs implements ISimpleFilter{
// instance variables
private double cutoffFrequency;
private double sampleRate;
private double resonance;
private boolean highPass;
private double value;
private double sumnatedValue;
private double cutoffAmount;
private double transitionBand;
private double window;
private double[] impulseResponce;
private double[] sampleCache;
private int sampleCacheLength;
private int n;
private int order;
private int midPoint;
//private int index;
// constructor for audio sample
public SincSpecs(double cutoffFrequency, double sampleRate, byte resonance,
boolean highPass, int band, SamplePlayer sample) {
this.cutoffFrequency = cutoffFrequency;
this.resonance = (double)resonance / 127;
this.highPass = highPass;
this.sampleRate = sampleRate;
if (highPass) {
this.cutoffFrequency += band / 2;
} else {
this.cutoffFrequency -= band / 2;
}
cutoffAmount = this.cutoffFrequency / this.sampleRate;
transitionBand = band / sampleRate;
//index = 0;
n = (int)(Math.ceil(4 / transitionBand));
// make sure length is odd
if (n % 2 == 0) {
n += 1;
}
order = n;
midPoint = order / 2 + 1;
impulseResponce = new double[n];
sumnatedValue = 0;
updateImpulseResponce();
sampleCache = new double[n];
sampleCacheLength = 0;
double inputPoint;
while (!canOutput()) {
inputPoint = sample.getNextPoint(); // get next sample point
inputFilterPoint(inputPoint);
}
}
// constructor for interface
public SincSpecs(double cutoffFrequency, double sampleRate, byte resonance,
boolean highPass, int band, ISamplePlayer sample) {
this.cutoffFrequency = cutoffFrequency;
this.resonance = (double)resonance / 127;
this.highPass = highPass;
this.sampleRate = sampleRate;
if (highPass) {
this.cutoffFrequency -= band / 2;
} else {
this.cutoffFrequency += band / 2;
}
cutoffAmount = cutoffFrequency / this.sampleRate;
transitionBand = band / sampleRate;
//index = 0;
n = (int)(Math.ceil(4 / transitionBand));
// make sure length is odd
if (n % 2 == 0) {
n += 1;
}
order = n;
midPoint = order / 2 + 1;
impulseResponce = new double[n];
sumnatedValue = 0;
updateImpulseResponce();
sampleCache = new double[n];
sampleCacheLength = 0;
double inputPoint;
while (!canOutput()) {
inputPoint = sample.generateWaveformPoint(); // get next waveform point
inputFilterPoint(inputPoint);
}
}
public double getTransitionBand() {
return transitionBand;
}
#Override
public void setCutoff(double cutoffFrequency) {
this.cutoffFrequency = cutoffFrequency;
cutoffAmount = this.cutoffFrequency / sampleRate;
updateImpulseResponce();
}
public void updateImpulseResponce() {
// get window of filtering
for (int i = 0; i < n; i++) {
impulseResponce[i] = cutoffAmount
* sinc(2 * cutoffAmount * Math.PI * (i - midPoint));
impulseResponce[midPoint] = cutoffAmount;
window = 0.54 - 0.46 * Math.cos(2 * Math.PI * i / order);
impulseResponce[i] *= window;
}
// sumnate all filter kernal values
double sum = 0;
for (int i = 0; i < n; i++) {
sum += impulseResponce[i];
}
for (int i = 0; i < n; i++) {
impulseResponce[i] /= sum;
}
// invert the impulse responce if high pass is true
if (this.highPass) {
invertImpulseForHighPass();
}
}
// input points
protected void inputFilterPoint(double point) {
sampleCache[sampleCacheLength] = point;
sampleCacheLength++;
for (int i = 0, j = n - 1; i < n; i++, j--) {
value += sampleCache[j] * impulseResponce[i];
}
}
protected void incrementCache(double value) {
for (int i = 0; i < sampleCacheLength - 1; i++) {
sampleCache[i] = sampleCache[i + 1];
}
sampleCache[sampleCacheLength - 1] = value;
}
// can output
protected boolean canOutput() {
boolean result = false;
if (sampleCacheLength == n) {
result = true;
}
return result;
}
// sinc
protected double sinc(double value) {
if (value == 0) {
value = 1;
} else {
value = Math.sin(value) / (value) + resonance * Math.sin(value);
}
return value;
}
protected void invertImpulseForHighPass() {
for (int i = 0; i < impulseResponce.length; i++) {
impulseResponce[i] *= -1;
}
impulseResponce[midPoint] += 1;
}
#Override
public double filter(double point) {
//index++;
value = 0;
for (int i = 0, j = n - 1; i < n; i++, j--) {
value += sampleCache[j] * impulseResponce[i];
}
incrementCache(point);
/*if (index == n) {
index = 0;
}*/
return value;
}
}
sub class:
package filters;
import sound.generator.waveforms.ISamplePlayer;
/**
*
* #author Edward Jenkins
*/
public class SincFilter extends SincSpecs {
// constants
public static final byte DEF_RESONANCE = 0;
public static final int DEF_BAND = 400;
// constructor
public SincFilter(double cutoffFrequency, double sampleRate, byte resonance,
boolean highPass, int band, ISamplePlayer sample) {
super(cutoffFrequency, sampleRate, (byte)resonance, highPass,
band, sample);
}
// three args constructor
public SincFilter(double cutoffFrequency, double sampleRate, byte resonance,
boolean highPass, ISamplePlayer sample) {
this(cutoffFrequency, sampleRate, resonance, highPass, DEF_BAND, sample);
}
// two args constructor
public SincFilter(double cutoffFrequency, double sampleRate,
ISamplePlayer sample) {
this(cutoffFrequency, sampleRate, DEF_RESONANCE, false, sample);
}
#Override
public void setCutoff(double cutoffFrequency) {
super.setCutoff(cutoffFrequency + getTransitionBand() / 2);
}
}
I have implemented the algorithm according to this paper it's working well, but for certain tests, it doesn't get the shortest path,
here's the pseudo-code
Initialize
For t=1 to iteration number do
For k=1 to l do
Repeat until ant k has completed a tour
Select the city j to be visited next
With probability pij given by Eq. (1)
Calculate Lk
Update the trail levels according to Eqs. (2-4).
End
here's the code
import java.io.*;
import java.util.*;
import static java.lang.Math.*;
public class test2 {
private InputReader cin;
private PrintWriter cout;
double pheromones[][];
double distances[][];
double visibility[][];
static int n;
City[] city;
Ant[] ant;
int m;
int T;
double alpha = 1; // pheromone importance
double beta = 2; // visibility importance
double evaporation = 0.1;
double Q = 100.0;
static class City {
double x, y;
int id;
public City(double x, double y, int id) {
this.x = x;
this.y = y;
this.id = id;
}
}
static class Ant {
int whereAmI;
boolean[] visited;
double tourDistance;
LinkedList<Integer> citiesVisitedInOrder;
int cityEdges[][];
Ant(int whereAmI) {
this.whereAmI = whereAmI;
visited = new boolean[n + 1];
cityEdges = new int[n + 1][n + 1];
reset();
}
void reset() {
Arrays.fill(visited, false);
visited[whereAmI] = true;
for (int i = 1; i <= n; i++)
Arrays.fill(cityEdges[i], 0);
tourDistance = 0;
citiesVisitedInOrder = new LinkedList<>();
citiesVisitedInOrder.addLast(whereAmI);
}
}
//the actual algorithm iteration
/*
Initialize
For t=1 to iteration number do
For k=1 to l do
Repeat until ant k has completed a tour
Select the city j to be visited next
With probability pij given by Eq. (1)
Calculate Lk
Update the trail levels according to Eqs. (2-4).
End
*/
private void solve() {
n = cin.readInt();
initializeParameter();
//the main loop
for (int t = 0; t < T; t++) {
for (int i = 0; i < m; i++) {//for each ant
Ant current = ant[i];
for (int j = 0; j < n; j++) {//for each city
int currentAntsCity = current.whereAmI;
double highestProbability = 0;
int cityId = 1;
double sumNotiation = calculateSum(current.visited, currentAntsCity);
//traverse all non-visited cities and choose the best
boolean good = false;
for (int c = 1; c <= n; c++) {//remove the equal
if (!current.visited[c]) {
double prop = (pow(pheromones[currentAntsCity][c], alpha) * pow(visibility[currentAntsCity][c], beta))
/ sumNotiation;
if (prop >= highestProbability) {
highestProbability = prop;
cityId = c;
good = true;
}
}
}
if (good) {
current.tourDistance += distances[currentAntsCity][cityId];
current.cityEdges[currentAntsCity][cityId] = current.cityEdges[cityId][currentAntsCity] = 1;
current.citiesVisitedInOrder.addLast(cityId);
current.whereAmI = cityId;
current.visited[cityId] = true;
}
}//after n iteration i ant completes a tour
current.tourDistance += distances[current.citiesVisitedInOrder.getFirst()][current.citiesVisitedInOrder.getLast()];
}//update
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
double deltaPhermons = 0;
for (int a = 0; a < m; a++) {
if (ant[a].cityEdges[i][j] != 0) {
deltaPhermons += Q / ant[a].tourDistance;
}
}
pheromones[i][j] = pheromones[j][i] = pheromones[i][j] * evaporation + deltaPhermons;
pheromones[i][i] = 0;
}
}
if (t == T - 1)
break;
//reset everything
for (int i = 0; i < m; i++) {
ant[i].reset();
}
}
//get the best ant route
double minDistance = Double.MAX_VALUE;
LinkedList<Integer> minRout = new LinkedList<>();
for (Ant ant : ant) {
if (ant.tourDistance < minDistance) {
minDistance = ant.tourDistance;
minRout = ant.citiesVisitedInOrder;
}
}
cout.println(minDistance);
for (int element : minRout)
cout.print(element + " ");
}
private double calculateSum(boolean[] visited, int currentAntsCity) {
//traverse all non-visited cities
double ans = 0.0;
for (int c = 1; c <= n; c++) {
if (!visited[c]) {
ans +=
pow(pheromones[currentAntsCity][c], alpha) *
pow(visibility[currentAntsCity][c], beta);
}
}
return ans;
}
private void initializeParameter() {
m = 2 * n;
T = 4 * m;
city = new City[n + 1];
pheromones = new double[n + 1][n + 1];
distances = new double[n + 1][n + 1];
visibility = new double[n + 1][n + 1];
//read cities coordinates
for (int i = 1; i <= n; i++) {
city[i] = new City(cin.readDouble(), cin.readDouble(), i);
}
//initialize distances
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
distances[i][j] = distances[j][i] = sqrt(pow(city[i].x -
city[j].x, 2.0) + pow(city[i].y -
city[j].y, 2.0));
}
}
//initialize the pheromones
double pheromones0 = 1.0 / (double) n;
for (int i = 1; i <= n; i++) {
Arrays.fill(pheromones[i], pheromones0);
pheromones[i][i] = 0;
}
//initialize the visibility
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
visibility[i][j] = visibility[j][i] = 1.0 / distances[i][j];
}
}
//initialize the ants
ant = new Ant[m];
Random rand = new Random(); //instance of random class for
for (int i = 0; i < m; i++) {
int random_int = rand.nextInt(n) + 1;
ant[i] = new Ant(random_int);
}
}
public static void main(String args[]) {
new test2().run();
}
private void run() {
// cin = new InputReader(System.in);
// cout = new PrintWriter(System.out);
try {
cin = new InputReader(new FileInputStream("input.txt"));
cout = new PrintWriter(new FileOutputStream("output.txt"));
} catch (FileNotFoundException e) {
//System.out.println(e.toString());
}
solve();
cout.close();
}
//just for faster reading from a file
public static class InputReader {
private InputStream stream;
private byte[] buf = new byte[1024];
private int curChar, numChars;
public InputReader(InputStream stream) {
this.stream = stream;
}
public int read() {
if (numChars == -1)
throw new InputMismatchException();
if (curChar >= numChars) {
curChar = 0;
try {
numChars = stream.read(buf);
} catch (IOException e) {
throw new InputMismatchException();
}
if (numChars <= 0)
return -1;
}
return buf[curChar++];
}
public int readInt() {
int c = read();
while (isSpaceChar(c))
c = read();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = read();
}
int res = 0;
do {
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = read();
} while (!isSpaceChar(c));
return res * sgn;
}
public double readDouble() {
int c = read();
while (isSpaceChar(c))
c = read();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = read();
}
double res = 0;
while (!isSpaceChar(c) && c != '.') {
if (c == 'e' || c == 'E')
return res * pow(10, readInt());
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = read();
}
if (c == '.') {
c = read();
double m = 1;
while (!isSpaceChar(c)) {
if (c == 'e' || c == 'E')
return res * pow(10, readInt());
if (c < '0' || c > '9')
throw new InputMismatchException();
m /= 10;
res += (c - '0') * m;
c = read();
}
}
return res * sgn;
}
private boolean isSpaceChar(int c) {
return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
}
}
}
the test case
10
-15 89
-5 -49
-35 -18
7 49
-95 -68
85 -39
53 -1
69 -99
-74 8
-52 -35
the right answer:
615.11811789868988853
1 9 5 10 3 2 8 6 7 4
my coes's output:
685.2134200307595
5 9 10 3 2 8 6 7 4 1
as you can notice I am not getting the shortest path, I believe that the mistake is somewhere in the constant, and the probability comparing!
the formula I have implemented
and the update formulas
how can I improve the algorithm accuracy? or maybe there's something wrong in my implementation!
I found the solution, Changing the Update functions after each complete tour for all ants, fixed the problem:
#part 1
//the elaboration presses after a complete tour for all ants
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
pheromones[i][j] *= evaporation;
if (pheromones[i][j] < 1.0 / (double) n)//notice it the phermones can't be less than the starting value`
pheromones[i][j] = 1.0 / (double) n;
pheromones[i][i] = 0;
}
}
#part 2
//update the phermonses
for (int i = 0; i < m; i++) {
for (int j = i + 1; j <= n; j++) {
int from = ant[i].rout[0];
int to = ant[i].rout[n - 1];
pheromones[from][to] += Q / ant[i].tourDistance;
pheromones[to][from] = pheromones[from][to];
}
}
source HERE
strangely enough the algorithm can work without the elaboration presses i.e. #part1.
Anyway here's the complete code with little changes
import java.io.*;
import java.util.*;
import static java.lang.Math.*;
public class test2 {
private InputReader cin;
private PrintWriter cout;
double[][] arr;
double[][] pheromones;
double[][] distances;
double[][] visibility;
static int n;
Ant[] ant;
int m;
int T;
double alpha = 1; // pheromone importance
double beta = 3; // visibility importance
double evaporation = 0.9;
double Q = 40.0;
double pheromones0;
static class Ant {
int whereAmI;
boolean[] visited;
double tourDistance;
private int ctr; //counter for the cites thought which the ant pass
private int[] route;
Ant(int whereAmI) {
this.whereAmI = whereAmI;
reset();
}
void reset() {
ctr = 0;
route = new int[n];
visited = new boolean[n + 1];
visited[whereAmI] = true;
tourDistance = 0;
addCityToTheRoute(whereAmI);
}
void addCityToTheRoute(int cityId) {
route[ctr++] = cityId;
}
}
private void solve() {
n = cin.readInt();
initializeParameter();
double mi = Double.MAX_VALUE;
int[] cityRoute = new int[n];
//the main loop
for (int t = 0; t < T; t++) {
for (int i = 0; i < m; i++) {//for each ant
for (int j = 0; j < n; j++) {//for each city
double highestProbability = 0;
int cityId = 1;
double sumNotiation = calculateSum(ant[i].visited, ant[i].whereAmI);
//traverse all non-visited cities and choose the best
boolean good = false;
for (int c = 1; c <= n; c++) {//remove the equal
if (!ant[i].visited[c]) {
double prop = (pow(pheromones[ant[i].whereAmI][c], alpha) * pow(visibility[ant[i].whereAmI][c], beta))
/ sumNotiation;
if (prop >= highestProbability) {
highestProbability = prop;
cityId = c;
good = true;
}
}
}
if (good) {
ant[i].tourDistance += distances[ant[i].whereAmI][cityId];
ant[i].addCityToTheRoute(cityId);
ant[i].whereAmI = cityId;
ant[i].visited[cityId] = true;
}
}//after n iteration i ant completes a tour
ant[i].tourDistance += distances[ant[i].route[0]][ant[i].route[n - 1]];//add the distance from the last city to the first city
//while k ant finishes its tour take the best ant's route so far
if (ant[i].tourDistance < mi) {
mi = ant[i].tourDistance;
cityRoute = ant[i].route;
}
}
//update
//evaporatePheromones
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
pheromones[i][j] *= evaporation;
if (pheromones[i][j] < pheromones0)
pheromones[i][j] = pheromones0;
pheromones[i][i] = 0;
}
}
//updatePheromones
for (int i = 0; i < m; i++) {
for (int j = i + 1; j <= n; j++) {
int from = ant[i].route[0];
int to = ant[i].route[n - 1];
pheromones[from][to] += Q / ant[i].tourDistance;
pheromones[to][from] = pheromones[from][to];
}
}
if (t == T - 1)
break;
//reset everything
for (int i = 0; i < m; i++) {
ant[i].reset();
}
}
//print the route with the distance
cout.println(mi);
for (int element : cityRoute)
cout.print(element + " ");
}
private double calculateSum(boolean[] visited, int currentAntsCity) {
//traverse all non-visited cities
double ans = 0.0;
for (int c = 1; c <= n; c++) {
if (!visited[c]) {
ans +=
pow(pheromones[currentAntsCity][c], alpha) *
pow(visibility[currentAntsCity][c], beta);
}
}
return ans;
}
private void initializeParameter() {
m = 20 * n;
T = 20;
pheromones = new double[n + 1][n + 1];
distances = new double[n + 1][n + 1];
visibility = new double[n + 1][n + 1];
//read cities coordinates
arr = new double[n + 1][2];
for (int i = 1; i <= n; i++) {
double x = cin.readDouble();
double y = cin.readDouble();
arr[i][0] = x;
arr[i][1] = y;
}
//initialize distances
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
distances[i][j] = distances[j][i] = sqrt(pow(arr[i][0] -
arr[j][0], 2.0) + pow(arr[i][1] -
arr[j][1], 2.0));
}
}
//initialize the pheromones
pheromones0 = 1.0 / (double) n;
for (int i = 1; i <= n; i++) {
Arrays.fill(pheromones[i], pheromones0);
pheromones[i][i] = 0;
}
//initialize the visibility
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
visibility[i][j] = visibility[j][i] = 1.0 / distances[i][j];
}
}
//initialize the ants
ant = new Ant[m];
Random rand = new Random(); //instance of random class for
for (int i = 0; i < m; i++) {
int random_int = rand.nextInt(n) + 1;
ant[i] = new Ant(random_int);
}
}
public static void main(String args[]) {
new test2().run();
}
private void run() {
// cin = new InputReader(System.in);
// cout = new PrintWriter(System.out);
try {
cin = new InputReader(new FileInputStream("input.txt"));
cout = new PrintWriter(new FileOutputStream("output.txt"));
} catch (FileNotFoundException e) {
//System.out.println(e.toString());
}
solve();
cout.close();
}
//just for faster reading from a file
public static class InputReader {
private InputStream stream;
private byte[] buf = new byte[1024];
private int curChar, numChars;
public InputReader(InputStream stream) {
this.stream = stream;
}
public int read() {
if (numChars == -1)
throw new InputMismatchException();
if (curChar >= numChars) {
curChar = 0;
try {
numChars = stream.read(buf);
} catch (IOException e) {
throw new InputMismatchException();
}
if (numChars <= 0)
return -1;
}
return buf[curChar++];
}
public int readInt() {
int c = read();
while (isSpaceChar(c))
c = read();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = read();
}
int res = 0;
do {
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = read();
} while (!isSpaceChar(c));
return res * sgn;
}
public double readDouble() {
int c = read();
while (isSpaceChar(c))
c = read();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = read();
}
double res = 0;
while (!isSpaceChar(c) && c != '.') {
if (c == 'e' || c == 'E')
return res * pow(10, readInt());
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = read();
}
if (c == '.') {
c = read();
double m = 1;
while (!isSpaceChar(c)) {
if (c == 'e' || c == 'E')
return res * pow(10, readInt());
if (c < '0' || c > '9')
throw new InputMismatchException();
m /= 10;
res += (c - '0') * m;
c = read();
}
}
return res * sgn;
}
private boolean isSpaceChar(int c) {
return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
}
}
}
I am trying to perform hamming followed by FFT of a wav file. I have implemented the same in python. How to do this in Java. I have applied hamming on the given wave file which returns a bytearrayOutputStream. Now how to perform FFT over this byteArrayOutputStream?
I am new to audio processing. My current code is:
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
public class AudioFFT {
public static void main(String[] args) throws UnsupportedAudioFileException, IOException {
String wavFilePath="C:\\abc.wav";
ByteArrayOutputStream byteArrayOutputStream=applyHamming(wavFilePath);
byte[] bytesOut=byteArrayOutputStream.toByteArray();
System.out.println(Arrays.toString(bytesOut));
}
public static ByteArrayOutputStream applyHamming(String filePath)
{
// TODO Auto-generated method stub
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
File fileIn = new File(filePath);
AudioInputStream audioInputStream;
try {
audioInputStream = AudioSystem.getAudioInputStream(fileIn);
int bytesPerFrame = audioInputStream.getFormat().getFrameSize();
if (bytesPerFrame == AudioSystem.NOT_SPECIFIED) {
bytesPerFrame = 1;
}
int numBytes = 1024 * bytesPerFrame;
byte[] audioBytes = new byte[numBytes];
int numBytesRead = 0;
while ((numBytesRead = audioInputStream.read(audioBytes, 0, audioBytes.length)) != -1) {
outputStream.write(audioBytes, 0, numBytesRead);
}
} catch (UnsupportedAudioFileException | IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return outputStream;
}
private static int BITS_IN_BYTE = 8;
private static AudioInputStream audioInputStream;
private static AudioFormat format;
final static int W = 1024;
public static void getFFT() {
String wavFilePath="C:\\abc.wav";;
File AudioFile = new File(wavFilePath);
ByteArrayOutputStream out = new ByteArrayOutputStream();
BufferedInputStream in;
try {
audioInputStream = AudioSystem.getAudioInputStream(AudioFile);
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
format = audioInputStream.getFormat();
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
if (!AudioSystem.isLineSupported(info)) {
System.out.println("Error");
}
TargetDataLine line = null;
try {
line = (TargetDataLine) AudioSystem.getLine(info);
line.open(format);
} catch (LineUnavailableException ex) {
System.out.println("Error");
}
line.start();
byte[] data = new byte[W * format.getSampleSizeInBits() / BITS_IN_BYTE];
double[] inbuf = new double[W];
double[] fftbuf = new double[W];
try {
in = new BufferedInputStream(new FileInputStream(AudioFile));
int read;
while ((read = in.read(data)) > 0) {
out.write(data, 0, read);
}
out.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
data = out.toByteArray();
decode(data, inbuf);
fft(inbuf, fftbuf);
}
public static void decode(byte[] input, double[] output) {
assert input.length == 2 * output.length;
for (int i = 0; i < output.length; i++) {
output[i] = (short) (((0xFF & input[2 * i + 1]) << 8) | (0xFF & input[2 * i]));
output[i] /= Short.MAX_VALUE;
}
}
public static void fft(final double[] inputReal, double[] inputImag) {
assert inputReal.length == 2 * inputImag.length;
int n = inputReal.length;
double ld = Math.log(n) / Math.log(2.0);
if (((int) ld) - ld != 0) {
System.out.println("The number of elements is not a power of 2.");
}
int nu = (int) ld;
int n2 = n / 2;
int nu1 = nu - 1;
double[] xReal = new double[n];
double[] xImag = new double[n];
double tReal, tImag, p, arg, c, s;
double constant;
if (true){
constant = -2 * Math.PI;
}
for (int i = 0; i < n; i++) {
xReal[i] = inputReal[i];
xImag[i] = inputImag[i];
}
int k = 0;
for (int l = 1; l <= nu; l++) {
while (k < n) {
for (int i = 1; i <= n2; i++) {
p = bitreverseReference(k >> nu1, nu);
arg = constant * p / n;
c = Math.cos(arg);
s = Math.sin(arg);
tReal = xReal[k + n2] * c + xImag[k + n2] * s;
tImag = xImag[k + n2] * c - xReal[k + n2] * s;
xReal[k + n2] = xReal[k] - tReal;
xImag[k + n2] = xImag[k] - tImag;
xReal[k] += tReal;
xImag[k] += tImag;
k++;
}
k += n2;
}
k = 0;
nu1--;
n2 /= 2;
}
k = 0;
int r;
while (k < n) {
r = bitreverseReference(k, nu);
if (r > k) {
tReal = xReal[k];
tImag = xImag[k];
xReal[k] = xReal[r];
xImag[k] = xImag[r];
xReal[r] = tReal;
xImag[r] = tImag;
}
k++;
}
double[] newArray = new double[xReal.length * 2];
double radice = 1 / Math.sqrt(n);
for (int i = 0; i < newArray.length; i += 2) {
int i2 = i / 2;
newArray[i] = xReal[i2] * radice;
newArray[i + 1] = xImag[i2] * radice;
}
for (int i = 0; i < newArray.length; i++) {
System.out.println("Array: " + newArray[i]);
}
}
private static int bitreverseReference(int j, int nu) {
int j2;
int j1 = j;
int k = 0;
for (int i = 1; i <= nu; i++) {
j2 = j1 / 2;
k = 2 * k + j1 - 2 * j2;
j1 = j2;
}
return k;
}
}
bytesOut contain your wav file data (after being modified by a Hamming window function). These data
represent the real part that you should send to your fft method (inputReal). For the imaginary part,
create an array of the same size as inputReal and fill it with zeros
//create an array for the imaginary part ( I assume 1024 in length)
double[] imgBytesOut = new double[1024]; //imgBytesOut is not a good name for this
for(int i=0; i<1024;i++)
imgBytesOut[i] = 0;
Now you have everything you need to call fft
fft(bytesOut, imgBytesOut);
Your fft method populates xReal and xImg arrays but since you declared them locally, you won't be
able to use them after fft has finsihed (declare them as static global variables).
Also, if your file contains, say, 10000 samples and your fft size is 1024 samples long(outBytes and imgBytesOut are 1024 samples long)
you will have to call fft repeatedly to process the whole file. To get the best results, you would still need to apply overlapping (e.g. for a 50% overlap and fft size of 1024, you'd process samples 1-1024, then 512-1536, then 1024-2048 and so on).
I'm trying to do the Algorithm programming assignment of Princeton , and I met a problem about the memory test. The assignment requires us run the percolation program N times and find the medium of the result, and I write a percolationtest.java and for each time, I create an instance variable, it worked, but use too much memory, and the instructor suggests me to use local variable, but I don't know how. Can some one help me and give me some advice, I really appreciate it.
public class PercolationStats {
private int N, T, totalSum;
private double []fraction;
private int []count;
public PercolationStats(int N, int T) {
if (N <= 0 || T <= 0)
throw new IllegalArgumentException();
else {
this.N = N;
this.T = T;
count = new int [T];
totalSum = N*N;
fraction = new double[T];
int randomX, randomY;
for (int i = 0; i < T; i++) {
Percolation perc = new Percolation(N);
while (true) {
if (perc.percolates()) {
fraction[i] = (double) count[i]/totalSum;
break;
}
randomX = StdRandom.uniform(1, N+1);
randomY = StdRandom.uniform(1, N+1);
if (perc.isOpen(randomX, randomY)) continue;
else {
perc.open(randomX, randomY);
count[i]++;
}
}
}
}
} // perform T independent experiments on an N-by-N grid
public double mean() {
double totalFraction = 0;
for (int i = 0; i < T; i++) {
totalFraction += fraction[i];
}
return totalFraction/T;
} // sample mean of percolation threshold
public double stddev() {
double u = this.mean();
double sum = 0;
for (int i = 0; i < T; i++) {
sum += (fraction[i] - u) * (fraction[i] - u);
}
return Math.sqrt(sum/(T-1));
} // sample standard deviation of percolation threshold
public double confidenceLo() {
double u = this.mean();
double theta = this.stddev();
double sqrtT = Math.sqrt(T);
return u-1.96*theta/sqrtT;
} // low endpoint of 95% confidence interval
public double confidenceHi() {
double u = this.mean();
double theta = this.stddev();
double sqrtT = Math.sqrt(T);
return u+1.96*theta/sqrtT;
} // high endpoint of 95% confidence interval
public static void main(String[] args) {
int N = 200;
int T = 100;
if (args.length == 1) N = Integer.parseInt(args[0]);
else if (args.length == 2) {
N = Integer.parseInt(args[0]);
T = Integer.parseInt(args[1]); }
PercolationStats a = new PercolationStats(N, T);
System.out.print("mean = ");
System.out.println(a.mean());
System.out.print("stddev = ");
System.out.println(a.stddev());
System.out.print("95% confidence interval = ");
System.out.print(a.confidenceLo());
System.out.print(", ");
System.out.println(a.confidenceHi());
}
}
public class Percolation {
private boolean[][] site;
private WeightedQuickUnionUF uf;
private int N;
public Percolation(int N) {
if (N < 1)
throw new IllegalArgumentException();
else {
site = new boolean[N + 2][N + 2];
for (int j = 1; j <= N; j++) {
site[0][j] = true;
site[N + 1][j] = true;
}
uf = new WeightedQuickUnionUF((N + 2) * (N + 2));
for (int i = 1; i <= N; i++) {
uf.union(0, i);
}
this.N = N;
}
}
public void open(int i, int j) {
if (i > N || i < 1 || j > N || j < 1)
throw new IndexOutOfBoundsException();
else {
if (!site[i][j]) {
site[i][j] = true;
if (site[i - 1][j]) {
uf.union((N + 2) * (i - 1) + j, (N + 2) * i + j);
}
if (site[i + 1][j]) {
uf.union((N + 2) * i + j, (N + 2) * (i + 1) + j);
}
if (site[i][j + 1]) {
uf.union((N + 2) * i + (j + 1), (N + 2) * i + j);
}
if (site[i][j - 1]) {
uf.union((N + 2) * i + (j - 1), (N + 2) * i + j);
}
}
}
}
public boolean isOpen(int i, int j) {
if (i > N || i < 1 || j > N || j < 1)
throw new IndexOutOfBoundsException();
else
return site[i][j];
}
public boolean isFull(int i, int j) {
if (i > N || i < 1 || j > N || j < 1)
throw new IndexOutOfBoundsException();
else
return site[i][j] && (i == 1 || uf.connected((N + 2) * i + j, 0));
}
public boolean percolates() {
for (int i = 1; i <= N; i++) {
if (this.isFull(N, i)) {
return true;
}
}
return false;
}
public static void main(String[] args) {
}
}
Added meanValue instance variable to keep mean value and replaced it in multiple places where you used to call mean() method which was over head to calculate again and again. Also modified "int[] count" as local variable which you were not using outside the constructor. post your "Percolation" and "StdRandom" classes for more optimization of code. you can run this code and test, it should reduce the runtime than yours.
public class PercolationStats {
private int N, T, totalSum;
private double []fraction;
private double meanValue;
public PercolationStats(int N, int T) {
if (N <= 0 || T <= 0)
throw new IllegalArgumentException();
else {
this.N = N;
this.T = T;
int [] count = new int [T];
totalSum = N*N;
fraction = new double[T];
int randomX, randomY;
for (int i = 0; i < T; i++) {
Percolation perc = new Percolation(N);
while (true) {
if (perc.percolates()) {
fraction[i] = (double) count[i]/totalSum;
break;
}
randomX = StdRandom.uniform(1, N+1);
randomY = StdRandom.uniform(1, N+1);
if (perc.isOpen(randomX, randomY)) continue;
else {
perc.open(randomX, randomY);
count[i]++;
}
}
}
}
}
// perform T independent experiments on an N-by-N grid
public double mean() {
double totalFraction = 0;
for (int i = 0; i < T; i++) {
totalFraction += fraction[i];
}
meanValue = totalFraction/T;
return meanValue;
} // sample mean of percolation threshold
public double stddev() {
double u = meanValue;
double sum = 0;
for (int i = 0; i < T; i++) {
sum += (fraction[i] - u) * (fraction[i] - u);
}
return Math.sqrt(sum/(T-1));
} // sample standard deviation of percolation threshold
public double confidenceLo() {
double u = meanValue;
double theta = this.stddev();
double sqrtT = Math.sqrt(T);
return u-1.96*theta/sqrtT;
} // low endpoint of 95% confidence interval
public double confidenceHi() {
double u = meanValue;
double theta = this.stddev();
double sqrtT = Math.sqrt(T);
return u+1.96*theta/sqrtT;
} // high endpoint of 95% confidence interval
public static void main(String[] args) {
int N = 200;
int T = 100;
if (args.length == 1) N = Integer.parseInt(args[0]);
else if (args.length == 2) {
N = Integer.parseInt(args[0]);
T = Integer.parseInt(args[1]); }
PercolationStats a = new PercolationStats(N, T);
System.out.print("mean = ");
System.out.println(a.mean());
System.out.print("stddev = ");
System.out.println(a.stddev());
System.out.print("95% confidence interval = ");
System.out.print(a.confidenceLo());
System.out.print(", ");
System.out.println(a.confidenceHi());
}
}