What is an efficient way of multiplying massive polynomials in Java? - java

I have a function that defines a very long polynomial useful in operations with matrices.
The formula multiplies binomials of the form (1+xi*yj) , where i and j are subscripted and correspond to the rows and columns of the matrix in question, respectively. The polynomial that results is the product of all binomials with every permutation of i and j.
For example, a 3 x 2 matrix will have the polynomial product be:
(1+x1*y1)(1+x1*y2)(1+x2*y1)(1+x2*y2)(1+x3*y1)(1+x3*y2)
For clarification, every number after the variable should be treated as a subscript.
Is it possible for java to compute something of this massive amount, or can the task be delegated to another mathematics engine?
If possible, how would one go about implementing this?

Maybe this idea will help you to solve your problem:
int result = 1;
int x = 2;
int y = 3;
Integer [][] polynomials = new Integer[x][y];
polynomials[0][0] = 1;
polynomials[0][1] = 2;
polynomials[0][2] = 3;
polynomials[1][0] = 4;
polynomials[1][1] = 5;
polynomials[1][2] = 6;
for(int i = 0; i<x; i++) {
for(int j = 0; j<y; j++) {
result *= (1 + polynomials[i][j]);
}
}
System.out.println(result);

Related

Create 2D array with 2 int arrays

I want to build a 2D matrix with sum of 2 input arrays(by adding row & column elements).
For example, if a is {1,3,5} and b is {4,8}, I want to build my matrix as so: [{1,3,5}, {4,7,9}, {8,11,13}].
Some more explanation here: [{1,3,5} (this is a), {4,7,9} (4 from b, 7=3+4) (9= 5+4), {8,11,13}]. (8 from b again, then 11= 3+8) (13=5+8). If you draw the first row with a, then draw b as the column aligned with a[0], you could add row element with column element to get the sum matrix.
Is there a more efficient way to do so? I tried to write 2 for-loops which gives a large time and space complexity.
public void BuildMatrix (int[] a, int[] b) {
int rows = b.length+1;
int columns = a.length;
int[][] matrix = new int[b.length+1][a.length];
for (int i = 0; i < columns-1; i++) {
matrix[0][i] = a[i];
for (int j = 1; j < rows; j++) {
matrix[j][0] = b[j-1];
matrix[j][i+1] = b[j-1] + a[i+1];
}
} }
Are input arrays to be of any possible size? If you know size ahead of time you can optimize that.
You are computing rows and columns twice:
int rows = b.length+1;
int columns = a.length;
int[][] matrix = new int[b.length+1][a.length];
so why not:
int rows = b.length+1;
int columns = a.length;
int[][] matrix = new int[rows][columns];
likewise you can factor out b[j-1] here (but compiler likely does the same anyway):
matrix[j][0] = b[j-1];
matrix[j][i+1] = b[j-1] + a[i+1];
Those are extremely minor bits though.
You should look into the broader picture and try parallelizing BuildMatrix calls if it's called a lot. You would then prepare a set of inputs for multiple BuildMatrix calls, and run them all on multiple processor cores (in parallel).

Simulated Annealing for Sudoku Solving

I'm trying to solve a 9x9 sudoku puzzle using Simulated Annealing, but my implementation doesn't seem to be working correctly. It does not even get closer to a lower-cost solution but instead keeps circling around results that cost between 60 and 80.
My cost function returns the sum of three things: Number of repeating digits in each row, column and block (3x3).
And the successor (neighbour) function i implemented changes two randomly selected digits from the 9x9 grid with random values.
And here is my SA function that doesn't work as expected:
public static void simulatedAnnealing() {
Sudoku neighbour; // candidate successor object
final Double temperature = 2.0; // initial temperature
final Double coolingFactor = 0.999; // cooling constant
final int maxIterations = 1000; // number of iterations
for(Double t = temperature; t>1; t*=coolingFactor) {
for(int i = 0; i < maxIterations; i++) {
neighbour = sudoku.generateSuccessor(); // set random neighbour
int delta = neighbour.cost() - sudoku.cost(); // calculate delta
if (delta <= 0) {
sudoku = neighbour; // always accept good step.
} else {
if (Math.exp(-delta / temperature) > Math.random()) { // Simulated annealing
sudoku = neighbour;
}
}
}
System.out.println(sudoku.cost());
if(sudoku.cost() == 0) { break; } // if puzzle is solved
} }
Function for generating successors:
public Sudoku generateSuccessor() {
int[][] newGrid = new int[9][9];
for(int o = 0; o < 9; o ++) { // cloning current grid array
for(int g = 0; g < 9; g ++) {
newGrid[o][g] = grid[o][g];
}
}
Sudoku rndm = new Sudoku(newGrid); // random Sudoku object.
for (int i = 0; i < 2; i++) { // will randomize 2 cells in 9x9 grid.
int rndmCell = rndmValue(); // random digit for randomizing.
int randomRow = rndm(); // random row that will be randomized
int randomCol = rndm(); // random column that will be randomized
// prevent randomizing given cells in sudoku (in problem definition)
boolean shouldContinue = false;
for (Coordinate c : SudokuSolver.concreteCoordinates) {
if (c.row == randomRow && c.col == randomCol) {
shouldContinue = true;
break;
}
}
if (shouldContinue) {
i--;
continue;
}
// prevention end.
rndm.grid[randomRow][randomCol] = rndmCell;
}
return rndm;
}
Cost function:
public int cost() {
if(hasZeros()) { // if grid is not totally filled with numbers don't calculate its cost.
return -1;
}
int cost = 0;
for(int i = 0; i< 9; i++) { // find total collusions in rows&columns.
cost += findNumberOfCollusions(grid[i]); // find collustions at row 'i'.
cost += findNumberOfCollusions(getColumn(grid,i)); // find collustions at column 'i'.
}
for(int r = 0; r < 9; r += 3) { //find total colusions in blocks (3x3).
for(int c = 0; c < 9; c += 3) {
int[] block = new int[9];
int ctr = 0;
for (int i = r; i < r + 3; i++) {
for (int y = c; y < c+ 3; y++) {
block[ctr] = grid[i][y];
ctr++;
}
}
cost += findNumberOfCollusions(block);
}
}
return cost;
}
When i run the program the output is costs between 60 and 80. After that the temperature goes below the limit and the program outputs a solution that costs around that interval. Can anyone tell me what am i doing wrong? Thanks in advance.
I also had a similar problem to the one you describe, my fitness remained stuck (actually though, my problem was with not copying lists in Python). I can't really assure why your code gets stuck, but if I had to guess: the neighbor generation (int rndmCell = rndmValue(); int randomRow = rndm(); int randomCol = rndm();) may be actually doing more harm than good. Imagine that you have a nearly complete sudoku, but out of the blue two of the correct cells that you had now change their value to a complete opposite one, which is not only wrong on the cell itself but also on the row, column and/or 3x3 square. I'm no mathematician, but logic tells me that the more fitting the sudoku is (i.e. the closer its fitness is to 0), the more chances there are to mess up the sudoku by randomly changing cells. This approach may get you stuck on a local minimum easily.
A more "informed" solution for this problem would be to keep one of the three basic restrictions of the sudoku puzzle fixed by, for instance, generating rows that are permutations of the values [1..9], swapping two cells of a random row (thus still fulfilling the restriction), and calculating the fitness only on the columns and on the 3x3 squares. This choice of neighbor generation is usually more effective. If you are interested, this idea comes from the paper Metaheuristics can solve Sudoku puzzles. I can say that this idea helped me a lot and now the algorithm completes sudokus that I provide :)

Travelling Salesman Brute Force Combinations

I started writing some code today to test some different solutions to the traveling salesman problem. I have run some tests for the random algorithm and the nearest neighbor algorithm, however, I am struggling with the brute force method.
What my program does is ask the user how many cities they will add. It then asks them to input the cities name followed by their longitude and latitude. I have created a method to then generate a 2-dimensional array in which the distances between all cities are stored.
What I want my brute force algorithm to do is calculate the distance between all combinations of cities and at the end output the shortest distance.
For example:
3 cities are entered(New York, Paris, Shanghai)
The distances between them is then stored.
[0.0, 5834.0, 11851.0]
[5834.0, 0.0, 9257.0]
[11851.0, 9257.0, 0.0]
Now I want to work out all the possible combinations and their total distance:
NY-P-S-NY
NY-S-P-NY
P-NY-S-P
P-S-NY-P
S-NY-P-S
S-P-NY-S
My issue is avoiding the 0.0 distances from the array, which will obviously result in shorter routes.
Any help is much appreciated. Please note I am only just learning to code so if possible I prefer less efficient and easier to understand answers :)
The code below is my attempt of getting it to work for 4 cities, however, I wish for the program to be able to complete this task for any amount of cities. I am well aware what I tried is unsuccessful:
int numCities = weights.length();
List<Integer> brute = new ArrayList<Integer>();
for (int i = 0; i< 4; i++){
brute.add(i);
}
System.out.println(brute);
double weight = 0.0;
double tempWeight = 0.0;
int temp1 = 0;
int temp2 = 0;
int temp3 = 0;
int temp4 = 0;
int removing = 0;
int valuetoRemove = 0;
for (int a = 0; a < 4; a++){
for (int b = 0; b < 3; b++){
temp2 = brute.get(b);
//System.out.println(temp2);
List<Integer> brute2 = new ArrayList<Integer>();
brute2.addAll(brute);
brute.remove(b);
System.out.println(brute);
for (int c = 0; c < 2; c++){
temp3 = brute.get(c);
//System.out.println(temp3);
List<Integer> brute2 = new ArrayList<Integer>();
brute2.addAll(brute);
brute.remove(c);
//System.out.println(brute);
temp4 = brute.get(0);
//System.out.println(temp4);
//brute.remove(0);
//System.out.println(brute);
tempWeight = weights[temp1][temp2] + weights[temp2][temp3] + weights[temp3][temp4] + weights[temp4][temp1];
System.out.println(tempWeight);
brute = brute2;
}
}
}

Efficiently get the row.max and row.sum of a Java 2D array

In Java, given a 2D array of double values with dim as 6000*6000, is there an efficient way to query the row max and the row sum?
I am using the data structure double[][] and a two-layer loop to get the row max and sum, but it is not sufficiently efficient, as this function is called frequently.
double MinRowMax = Double.POSITIVE_INFINITY;
int num = 6000;
double[][] array2DDist = new double[num][num];
Random rand = new Random();
// initialising the array2DDist
for(int i=0;i<num;++i)
for(int j=0;j<num;++j)
array2DDist[i][j] = rand.nextDouble();
// get the row.max and row.sum
for(int i=0;i<num;++i) {
double maxDist = Double.NEGATIVE_INFINITY;
double sumDist = 0;
for(int j=0;j<num;++j) {
double dist = array2DDist[i][j];
maxDist = Double.max(maxDist, dist);
sumDist+=dist;
}
if(maxDist < MinRowMax) {
MinRowMax = maxDist;
}
}
Is there any Java library that provides more efficient solutions? Is there any Java library that is similar to Matrix class in Python or R?
Thanks!
To compute the sum of an array, or largest value in an array, you have to visit every element of the array. You cannot speed that up.
However, if the array is not going to change, and you are going to need the sum and max for the array multiple times, then you can compute them once and then look them up. There are two approaches:
Compute the required values for all rows of your 2-D array at the start and store them in a lookup table. This is a form or eager cache.
Use (say) a HashMap<Integer, CacheEntry> (where CacheEntry represents the sum and max), and then use this to lazily cache the required values for each row (indexed by the key).
(Or some variation on the implementation of the above.)
Is there any Java library that provides more efficient solutions? Is there any Java library that is similar to Matrix class in Python or R?
Not to my knowledge. Certainly, not in the standard Java class libraries.
However, if you use eager or lazy caching, you should not need a library ... for this problem.
I don't know if more efficient but way shorter using Stream. Here is a demo using 4x4 array :
double MinRowMax = Double.POSITIVE_INFINITY;
int num = 4;
double[][] array2DDist = new double[num][num];
Random rand = new Random();
// initializing the array2DDist
for(int i=0;i<num;++i) {
for(int j=0;j<num;++j) {
array2DDist[i][j] = rand.nextDouble();
}
}
// get the row.max and row.sum
for(int row=0;row<num;++row) {
double maxDist = Double.NEGATIVE_INFINITY;
double sumDist = 0;
for(int col=0;col<num;++col) {
double dist = array2DDist[row][col];
maxDist = Double.max(maxDist, dist);
sumDist+=dist;
}
//System.out.println(Arrays.toString(array2DDist[row]));
System.out.println("row sum - max " + sumDist +" - " + maxDist);
System.out.println("row sum - max " + Arrays.stream(array2DDist[row]).parallel().sum()
+" - " + Arrays.stream(array2DDist[row]).parallel() .max().getAsDouble());
if(maxDist < MinRowMax) {
MinRowMax = maxDist;
}
}
// Programme to get sum of rows value and column values seprately.
int[] colSum =new int[array[0].length];
for (int i = 0; i < array.length; i++){
for (int j = 0; j < array[i].length; j++){
sum += array[i][j];
colSum[j] += array[i][j];
}
System.out.println("Print the sum of rows =" + sum);
}
for(int k=0;k<colSum.length;k++){
System.out.println("Print the sum of columns =" + colSum[k]);
}
// Programme to get maximum in 2D array.
map<int, int> temp;
int currentMax= -999999,maxCount=0;
for(i=0; i< numberOflines ;i++)
{
for(j=0;j< array[i].length;j++)
{
int newCount = ++temp[array[i][j]];
if (maxCount < newCount) {
maxCount = newCount;
currentMax = array[i][j];
}
}
}

Matrix manipulation: logic not fetching correct answer for higher order NXN matrix data

I came across below problem related to Matrix Manipulation.
problem statement
There is a NxN matrix,divided into N * N cells. Each cell has a predefined value. Which would be given as an input. Iteration has to happen K number of times which is also given in the test input. We have to make sure that we pick the optimum/min value of rows/columns at each iteration. Final output is the cumulative sum of optimum value saved at the end of each iteration.
Steps 1. Sum up the individual row and column and find the min sum of rows and columns, (it could be a row or a column, just need the minimum row or a column)
Step 2. Store the sum found above separately
Step 3.
Increment elements of the min. sum row or column. by 1
Repeat steps 1,2,3 from 1 to Kth value
add the sum at each iteration(specified in step2)
output is the sum obtained on on the Kth iteration.
Sample data
2 4
1 3
2 4
Output data
22
I was able to write a code (in java) and tested the same for some sample test cases. The output worked fine. The code works fine for sample data matrix of lower order, say, 2x2,4x4,even till 44x40 (that has less iteration). However, when the matrix size is increased to 100X100 (complex iteration), I see the expected output output values differ at 10s and hundreds place of the digit from the actual output and its random. Since I am not able to find a correct pattern of output vs input. Now, it is taking a toll on me to really debugging 500th loop to identify the issue. Is there any better way or approach to solve such problem related to huge matrix manipulation. Has anyone come across issues similar to this and solved it.
I am mainly interested in knowing the correct approach to solve given matrix problem. What Data structure to use in java. At present, I am using primitive DS and arrays int[] or long[] to solve this problem. Appreciate any help in this regard.
Which data structure?
What you need here is a data structure which allows you to efficiently query and update the minimum sum line. The most commonly used for this is a heap https://en.wikipedia.org/wiki/Heap_(data_structure).
For your purposes it's probably best to just implement the simplest kind, an array-based binary heap:
See here: https://en.wikipedia.org/wiki/Binary_heap
And here: http://courses.cs.washington.edu/courses/cse373/11wi/homework/5/BinaryHeap.java
..for implementation details.
Procedure:
Initialize your heap to size M + N where M, N are the number of rows and columns.
Before the loop, pre-compute the sum of each row and column, and add them as objects to the heap. Also add two arrays A, B which store the row and columon objects separately.
Now heapify the heap array with respect to the line sum attribute. This ensures the heap follows the criterion of the binary heap structure (parent always > children). Read the sources to find out more about how to implement this (quite easy for a fixed array)
For each iteration, look at the first element in the heap array. This is always the one with the smallest line sum. If this is a row object, then increment the sum attribute by N (no. of columns), and increment each object in B (list of columns) by 1. Do the same if it's a column.
After this, always heapify before the next iteration.
At the end, just return the first element's attribute.
Time complexity:
The original naive solution (looping through all columns and rows every time) is .
Using a heap, the heapify operation at each step is (for a binary heap).
This means the total complexity is , FAR smaller. The max term is to compensate for the fact that at each iteration it may be either rows or columns which are incremented.
As a side note, there are other heap structure types which have even better time complexity than the binary heap, e.g. binomial trees, Fibonacci heaps etc. These however are far more complicated, and have higher constant-factor overheads as a result. Thus for your project I feel they are not necessary, as many of them need phenomenal data set sizes to justify for the constant factor overhead.
Besides, they all support the same external operations as the binary heap, as defined by the Abstract Data Structure of Heap.
(heapify is an internal operation specific to the binary heap structure. Quite a few of the other ones are theoretically superior as they do this operation implicitly and "lazily")
O(KN + N*N) Solution:
You can just work with sum of columns and rows, and not store or manipulate them directly.
First sum all the columns and rows, in a 2*N array, first row being sum of columns, a[0][0] is sum of first column, a[0][1] is sum of second column, and second row is sum of rows, a[1][0] sum of first row, etc...
Then do the following for iterating:
Find min in array a .
Add it to the answer.
Add N to the min of row or column selected.
If the min is row add one to all cols and if it is a column add one to all rows.
If needed any further explanation, don't hesitate to comment.
I am doing like this for solving the above problem...
void matrixManipulation() throws IOException {
int N = Reader.nextInt();
int[][] matrix = new int[N][N];
int K = Reader.nextInt();
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
matrix[i][j] = Reader.nextInt();
}
}
// System.out.println("********Inital position**********");
// for (int i = 0; i < N; i++) {
// for (int j = 0; j < N; j++) {
// System.out.print(matrix[i][j]);
// }
// System.out.println();
// }
// System.out.println("********Inital position**********");
CalculateSum calculateSum = new CalculateSum();
int[] row = new int[N];
int[] row_clone = new int[N];
int[] col = new int[N];
int[] col_clone = new int[N];
int test =0;
for (int kk = 0; kk < K; kk++) {
row = calculateSum.calculateRowSum(matrix, N);
row_clone = row.clone();
/* just sort it either Arrarys sort or any other ---starts here*/
// for (int i = 1; i < row.length; i++) {
// row_orignial[i] = row[i];
// }
// Arrays.sort(row);
Node root1 = insert(null, row[0], 0, row.length);
for (int i = 1; i < row.length; i++) {
insert(root1, row[i], 0, row.length);
}
sortArrayInOrderTrvsl(root1, row, 0);
/* just sort it either Arrarys sort or any other ---ends here*/
col = calculateSum.calculateColumnSum(matrix, N);
col_clone = col.clone();
/* just sort it either Arrarys sort or any other ---starts here*/
// for (int i = 1; i < col.length; i++) {
// col_orignial[i] = col[i];
// }
// Arrays.sort(col);
Node root2 = insert(null, col[0], 0, col.length);
for (int i = 1; i < row.length; i++) {
insert(root2, col[i], 0, col.length);
}
sortArrayInOrderTrvsl(root2, col, 0);
/* just sort it either Arrary.sort or any other---ends here */
int pick = 0;
boolean rowflag = false;
int rowNumber = 0;
int colNumber = 0;
if (row[0] < col[0]) {
pick = row[0];// value
rowflag = true;
for (int i = 0; i < N; i++) {
if (pick == row_clone[i])
rowNumber = i;
}
} else if (row[0] > col[0]) {
pick = col[0];// value
rowflag = false;
for (int i = 0; i < N; i++) {
if (pick == col_clone[i])
colNumber = i;
}
} else if(row[0] == col[0]){
pick = col[0];
rowflag = false;
for (int i = 0; i < N; i++) {
if (pick == col_clone[i])
colNumber = i;
}
}
test= test + pick;
if (rowflag) {
matrix = rowUpdate(matrix, N, rowNumber);
} else {
matrix = columnUpdate(matrix, N, colNumber);
}
System.out.println(test);
// System.out.println("********Update Count"+kk+" position**********");
// for (int i = 0; i < N; i++) {
// for (int j = 0; j < N; j++) {
// System.out.print(matrix[i][j]);
// }System.out.println();
// }
// System.out.println("********Update Count"+kk+" position**********");
}
// System.out.println("********Final position**********");
// for (int i = 0; i < N; i++) {
// for (int j = 0; j < N; j++) {
// System.out.print(matrix[i][j]);
// }System.out.println();
// }
// System.out.println("********Final position**********");
// System.out.println(test);
}

Categories