memoized matrix chain multiplication in Java - java

I feel like I'm really close with this implementation of a memoized matrix chain algorithm in Java, but I'm getting an array out of bounds error on line 45 and 53. These, for some reason, really seem to mess me up. Maybe there's something I'm continually messing up with, but I dunno, obviously. Can anyone help me out?
public class Lab2 {
//fields
static int p[];
static int m[][];
final static int INFINITY = 999999999;
public Lab2() {
//
}
public static void main(String[] args) {
Lab2 lab2 = new Lab2();
Lab2.m = new int[7][7];
Lab2.p = new int[7];
Lab2.p[0] = 20;
Lab2.p[1] = 8;
Lab2.p[2] = 4;
Lab2.p[3] = 25;
Lab2.p[4] = 30;
Lab2.p[5] = 5;
Lab2.p[6] = 10;
int n = Lab2.p.length-1;
//initialize m array to infinity
for (int i = 1; i <= n; i++){
for (int j = i; j <= n; j++){
Lab2.m[i][j]= INFINITY;
}
}
lab2.lookUpChain(m, p, 1, n);
for (int i = 0; i < 8; i++){
for (int j = 0; j < 8; j++){
System.out.println(m[i][j]);
}
}
}
//
public int lookUpChain(int m[][], int p[], int i, int j ){
if (m[i][j]<INFINITY){
return m[i][j];
}
if (i == j){
m[i][j] = 0;
}
else{
for (int k = i; k <= j; i++){
int q = (lookUpChain(m,p,i,k)) + (lookUpChain(m,p,k+1,j)) + (p[i]*p[k]*p[j]);
if (q < m[i][j]){
m[i][j] = q;
}
}
}
return m[i][j];
}
}

else{
for (int k = i; k <= j; i++)
Change to:
else{
for (int k = i; k <= j; k++) // change i to k

Related

java.lang.StackOverflowError on factorial function being called by another recursive function

I have a factorial function on my program that works fine until i try to execute the function deleteRepeated(), the console is telling me that the error is in the return of the factorial function, maybe it's being called by a single function too many times in a short period of time? I've been stuck for hours.
import java.util.Scanner;
public class ex9 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
int[] newArr = new int[n - repeated(arr)];
int[] finalArr = deleteRepeated(arr, newArr);
for (int a : finalArr) {
System.out.println(a);
}
}
public static long factorial(int n) {
if (n == 0)
return 1;
return (n * factorial(n - 1));
}
public static int repeated(int arr[]) {
int n = arr.length;
int mix = (int) (factorial(n) / (2 * factorial(n - 2)));
int i = 0;
int k = 0;
int rep = 0;
int a = -100;
while (i < mix) {
for (int j = k + 1; j < n; j++) {
if (arr[k] == arr[j] && a != j) {
a = j;
rep += 1;
}
i++;
}
k++;
}
return rep;
}
public static int[] deleteRepeated(int arr[], int newArr[]) {
int n = arr.length;
int rep = repeated(arr);
int i = 0;
int k = 0;
int a = -100;
while (i < newArr.length) {
for (int j = k + 1; j < n; j++) {
if (arr[k] == arr[j] && a != arr[k]) {
a = arr[j];
newArr[k] = arr[k];
}
i++;
}
k++;
}
rep = repeated(newArr);
if (rep > 0) {
int[] newArr2 = new int[newArr.length - rep];
deleteRepeated(newArr, newArr2);
}
return newArr;
}
}
Only thing i could do to avoid the error was stopping the function from executing :/, maybe it has to do with how i'm re-calling it at the end of each execution...? is what i did allowed?
So, deleteRepeated is all messed up. The issue is deleteRepeated does not actually remove duplicate elements, so the check for the base case of recursion always fails. I'm not sure why you're using recursion here anyway; if the while loop worked properly, it could remove all duplicates without need for recursion.
It appears that you copy-pasted the implementation of repeated into deleteRepeated, and you replaced the logic for handling repeated elements with logic that handles non-repeated elements.
Here is how I would implement the method:
public static int deleteRepeated(int arr[], int newArr[]) {
int n = 0;
for(int i = 0; i < arr.length; i++) {
boolean unique = true;
for(int j = 0; j < n; j++)
unique = unique && newArr[j] != arr[i];
if(unique)
newArr[n++] = arr[i];
if(n >= newArr.length) break;
}
return n;
}

Floyd Warshall algorithm implementation

I've written code for a 100 x 100 adjacency matrix that represents the following directed graph:
I'm attempting to use a Floyd-Warshall algorithm to find the shortest path for all pairs of blue nodes in the graph. How do you only find the all pairs shortest path for the selected nodes? Here's the code I've written thus far:
public class AdjacencyMatrix
{
public static final int NUM_NODES = 100;
public static final int INF = Integer.MAX_VALUE;
public static boolean even(int num)
{
return num%2==0;
}
public static boolean odd(int num)
{
return num%2==1;
}
public static void initialize(int [][] adjMat, int N)
{
for(int i = 0; i < N; i++)
for(int j = 0; j <N; j++)
adjMat[i][j]=INF;
for(int x = 0; x<N; x++)
{
int row = x/10;
int column = x%10;
if (even(row)) {
if (column!=9)
adjMat[x][x+1]=1;
}
if (odd(row)) {
if (column!=0)
adjMat[x][x-1]=1;
}
if (even(column)){
if (row!=9)
adjMat[x][x+10]=1;
}
if (odd(column)) {
if (row!=0)
adjMat[x][x-10]=1;
}
}
}
public void floydWarshall(int[][] adjMat, int N)
{
adjMat = new int[N][N];
initialize(adjMat, NUM_NODES);
for(int k = 0; k < N; ++k) {
for(int i = 0; i < N; ++i) {
for(int j = 0; j < N; ++j) {
adjMat[i][j] = Math.min(adjMat[i][j], adjMat[i][k] + adjMat[k][j]);
}
}
}
}
public static void main(String[] args)
{
int adjMat[][] = new int[NUM_NODES][NUM_NODES];
initialize(adjMat, NUM_NODES);
int A,B,C,D,E,F,G,H,I,W;
A = 20;
B = 18;
C = 47;
D = 44;
E = 53;
F = 67;
G = 95;
H = 93;
I = 88;
W = 66;
System.out.println(adjMat[A][B]);
System.out.println();
}
}
First of all, you should not assign new value to adjMat parameter in floydWarshall(), because the value will not be saved after exiting the method.
The next step is to check adjMat[i][k] and adjMat[k][j] for equality to INF and continue the loop if so:
for(int k = 0; k < N; ++k) {
for(int i = 0; i < N; ++i) {
for(int j = 0; j < N; ++j) {
if (adjMat[i][k] != INF && adjMat[k][j] != INF) {
adjMat[i][j] = Math.min(adjMat[i][j], adjMat[i][k] + adjMat[k][j]);
}
Shortest Floyd-Warshall algo implemenation:
for(int k = 0; k < N; ++k) {
for(int i = 0; i < N; ++i) {
for(int j = 0; j < N; ++j) {
adjMat[i][j] = Math.min(adjMat[i][j], adjMat[i][k] + adjMat[k][j]);
}
}
}
After running this piece of cade adjMat will contain shortest distances between every pair of nodes.
Update: to avoid integer overflow, fill the matrix with Integer.MAX_VALUE / 2. In general case, it's dangerous to set the maximum possible value to variable as infinity, because you can't perform addition operation with it.

ArrayIndexOutOfBounds in binomial cofficient dynamic programming

I am trying to create a method that calculates (N choose R) using dynamic programming but I get an array out of bounds exception:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 7
at BinomialCoefficients.method5(BinomialCoefficients.java:127)
at BinomialCoefficients.main(BinomialCoefficients.java:50)
I am using a 2 dimensional array. Here is my code,
protected static long method5(long lN, long lR)
{
long lArray[][] = new long[(int) (lN+1)][(int) (lR+1)];
for(int i = 0; i <= lN; i++)
{
lArray[i][0] = 1;
}
for(int i = 0; i <= lN; i++)
{
lArray[i][i] = 1;
}
for(int i = 0; i <= lN; i++)
{
for(int j = i; j <= i; j++)
{
lArray[i][j] = lArray[i-1][j-1] + lArray[i-1][j];
}
}
/*for(int i = 0; i <= lN; i++)
{
for(int j = 0; j <= i; j++)
{
System.out.print(String.format("%5d", lArray[i][j]));
}
System.out.println();
}*/
return lArray[(int) lN][(int) lR];
}
Can somebody tell me what is wrong with it?
This code looks suspicious
for(int i = 0; i <= lN; i++)
{
lArray[i][i] = 1;
}
considering lArray was initialized using two potentially different values:
long lArray[][] = new long[(int) (lN+1)][(int) (lR+1)];
I think you should have an inner loop here, such as:
for(int i = 0; i <= lN; i++) {
for (int j=0; j<=lR; j++) {
lArray[i][j] = 1;
}
}
I see the indexing error has already been corrected. But will point out that you're allocating a square array when you only need one row. You're also not taking advantage of symmetry. Consider something like this:
public class Binomial {
public static long n_choose_r(int n, int r) {
r = Math.min(r, n - r);
long [] a = new long[r + 1];
a[0] = 1;
for (int i = 1; i <= n; ++i) {
if (i <= r) {
a[i] = 1;
}
for (int j = Math.min(r, i - 1); j > 0; --j) {
a[j] += a[j - 1];
}
}
return a[r];
}
public static void main(String [] args) {
System.out.println(n_choose_r(6, 4));
}
}

Inverse 2D FFT is outputting correct values in wrong order

My 2D FFT algorithm is outputting the correct values, but they are in the wrong order. For example, for input:
1050.0 1147.0 1061.0 1143.0
1046.0 1148.0 1118.0 1073.0
1072.0 1111.0 1154.0 1101.0
1078.0 1101.0 1106.0 1062.0
Taking the FFT, and then inverse FFT results in:
1050.0 1143.0 1061.0 1147.0
1078.0 1062.0 1106.0 1101.0
1072.0 1101.0 1154.0 1111.0
1046.0 1073.0 1118.0 1148.0
You can see that if you flip the last 3 columns horizontally, then the last 3 rows vertically, the data will be correct. As far as I can tell this is true for all input sizes so it's an easy (albeit hacky) fix. I am however worried about about computational time of the fix because I may have to perform this on 1024x1024 or even 2048x2048 images in the future.
I am fairly confident that my 1D FFT algorithm doFFT() is correct, and I am getting the expected values for the forward 2D FFT. It is just the inverse 2D FFT that is causing me trouble.
Does anyone see where my error is?
Code
private static double[] cose;
private static double[] sin;
public static void main(String[] args) {
float[][] img = new float[][]{
{ 1050.0f, 1147.0f, 1061.0f, 1143.0f},
{ 1046.0f, 1148.0f, 1118.0f, 1073.0f},
{ 1072.0f, 1111.0f, 1154.0f, 1101.0f},
{ 1078.0f, 1101.0f, 1106.0f, 1062.0f}
};
int size = img.length;
System.out.println("Image");
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
System.out.print(img[i][j] + "\t");
}
System.out.println();
}
Complex[][] fft = fft2D(toComplex(img), false);
Complex[][] inverse = fft2D(fft, true);
System.out.println("\nInverse");
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
System.out.print(inverse[i][j].getReal() + "\t");
}
System.out.println();
}
}
public static Complex[][] fft2D(Complex[][] pixels, boolean inverse){
int size = pixels.length;
computeCosSin(size);
Complex[][] data = transpose(pixels.clone());
Complex[] temp;
// FFT of rows
for (int i = 0; i < size; i++)
{
temp = doFFT(data[i], size);
data[i] = temp;
}
// FFT of columns
for (int i = 0; i < size; i++)
{
temp = new Complex[size];
for (int j = 0; j < size; j++)
{
temp[j] = data[j][i];
}
Complex[] temp2 = doFFT(temp, size);
for (int j = 0; j < size; j++)
{
data[j][i] = temp2[j];
}
}
if (!inverse)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
data[i][j] = data[i][j].divide(size*size);
}
}
}
return data;
}
public static Complex[] doFFT(Complex[] data, int size){
Complex[] temp = new Complex[size];
int j = 0;
for (int i = 0; i < size; i++) {
temp[i] = data[j];
int k = size / 2;
while ((j >= k) && (k > 0)) {
j -= k;
k /= 2;
}
j += k;
}
Complex n,m,h,f;
for(int i=0; i<size;i+=4){
n = temp[i].add(temp[i+1]);
m = temp[i+2].add(temp[i+3]);
h = temp[i].subtract(temp[i+1]);
f = temp[i+2].subtract(temp[i+3]);
Complex mult = h.add(f.multiply(Complex.I));
Complex sub = h.subtract(f.multiply(Complex.I));
temp[i] = n.add(m);
temp[i+2] = n.subtract(m);
temp[i+1] = sub;
temp[i+3] = mult;
}
int u;
for(int i=4; i< size;i<<=1){
int v = size/(i <<1);
for(int c=0; c< size;c +=i<<1){
for(int x=0; x < i; x++){
u = v*x;
double calc = temp[i+c+x].getReal()*cose[u] - temp[i+c+x].getImaginary()*sin[u];
double calc2 = temp[i+c+x].getReal()*sin[u] + temp[i+c+x].getImaginary()*cose[u];
Complex fftArray = new Complex(calc,calc2);
temp[(i+c+x)] =temp[(c+x)].subtract(fftArray);
temp[(c+x)] = temp[(c+x)].add(fftArray);
}
}
}
return temp;
}
public static Complex[][] toComplex(float[][] arr)
{
Complex[][] newArr = new Complex[arr.length][arr.length];
for (int i = 0; i < arr.length; i++)
{
for (int j = 0; j < arr.length; j++)
{
newArr[i][j] = new Complex(arr[i][j], 0.0);
}
}
return newArr;
}
public static Complex[][] transpose(Complex[][] array)
{
for (int i = 0; i < array.length; i++)
{
for (int j = i+1; j < array[i].length; j++)
{
Complex temp = array[i][j];
array[i][j] = array[j][i];
array[j][i] = temp;
}
}
return array;
}
public static void computeCosSin(int size){
double num = (2.0*Math.PI)/size;
double cos = Math.cos(num);
double sine = Math.sin(num);
cose = new double[size];
sin = new double[size];
cose[0] =1.0;
for(int i=1; i<size;i++){
cose[i] = cos*cose[i-1] + sine*sin[i-1];
sin[i] = cos*sin[i-1] - sine*cose[i-1];
}
}
}
This doesn't solve the root problem, but it does change the data I'm getting to the data I expect so it will serve my purpose for now. I do worry it will be incredibly slow on large arrays.
This function swaps row i with row N-i and then swaps every column i with column N-i, for 0 < i < N, (Assuming a square, power of 2 input array)
public Complex[][] inverseFix(Complex[][] array)
{
int size = array.length;
// Swap rows
Complex[] temp;
for (int i = 1; i < size/2; i++)
{
temp = array[i];
array[i] = array[size-i];
array[size-i] = temp;
}
// Swap columns
Complex temp2;
for (int i = 0; i < size; i++)
{
for (int j = 1; j < size/2; j++)
{
temp2 = array[i][j];
array[i][j] = array[i][size-j];
array[i][size-j] = temp2;
}
}
return array;
}

Multiplying 2d arrays(matrices) in java

My goal is to print out the Matrix when the two arrays are multiplied together. What am I doing wrong with this code? How do I get it so that it prints out the matrix? (Sorry I do not know what other details i should provide and I cannot submit this post unless I add more detail).
public class Matrices {
static int mRows = 0;
static int mCol = 0;
static int nRows = 0;
static int nCol = 0;
public static int[][] multiplyMatrices(int[][] m, int[][] n){
mRows = m.length;
mCol = m[0].length;
nRows = n.length;
nCol = n[0].length;
if(canBeMultiplied(m,n) == false){
throw new IllegalArgumentException("Cannot multiply arrays");
}
int[][] answer = new int[mRows][nCol];
for(int i = 0; i < mRows; i++){
for(int j = 0; j < nCol; j++){
for(int k = 0; k < mCol; k++){
answer[i][j] += m[i][k] * n[k][j];
}
}
}
return answer;
}
public static boolean canBeMultiplied(int[][] m, int[][]n){
mRows = m.length;
mCol = m[0].length;
nRows = n.length;
nCol = n[0].length;
if(nRows == mCol){
return true;
}
return false;
}
public static void main(String[] args) {
int[][] temp1 = {{1,2,3},{4,5,6}};
int[][] temp2 ={{1},{2},{3}};
for(int i = 0; i < mRows; i++){
for(int j = 0; j < nCol; j++){
System.out.print(multiplyMatrices(temp1,temp2)[i][j]);
}
System.out.print("\n");
}
}
}
Thanks for your help.
This could will loop through the the 2D array and print each element.
static final int ROWS = 2;
static final int COLS = 4;
int[][] a2 = new int[ROWS][COLS];
//... Print array in rectangular form
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
System.out.print(" " + a2[i][j]);
}
System.out.println("");
}

Categories

Resources