How to Implementating This EgienVector Code Python Code into Java - java

I have found right result Of Algorithm Can I implementating this code into Java?
import numpy as np
from scipy.linalg import eig
transition_mat = np.matrix([
[0.8, 0.15, 0.05],\
[0.075, 0.85, 0.075],\
[0.05, 0.15,0.8 ]])
S, U = eig(transition_mat.T)
stationary = np.array(U[:, np.where(np.abs(S - 1.) < 1e-8)[0][0]].flat)
print stationary
print np.sum(stationary)
stationary = stationary / np.sum(stationary)
print stationary
I Was Implementated this code in Java but Result is wrong
Matrix A = new Matrix(transition);
A = A.transpose();
Matrix x = new Matrix(N, 1, 1.0 / N); // initial guess for eigenvector
for (int i = 0; i < 50; i++) {
x = A.times(x);
x = x.times(1.0 / x.norm1()); // rescale
}
// compute by finding eigenvector corresponding to eigenvalue = 1
EigenvalueDecomposition eig = new EigenvalueDecomposition(A);
Matrix V = eig.getV();
double[] real = eig.getRealEigenvalues();
for (int i = 0; i < N; i++) {
if (Math.abs(real[i] - 1.0) < 1E-8) {
x = V.getMatrix(0, N-1, i, i);
x = x.times(1.0 / x.norm1());
System.out.println("Stationary distribution using eigenvector:");
x.print(9, 6);
}
}

From a quick look the code seems correct, provided that
your matrix transition is the same as in the python example. From your result I assume
the method Matrix.times does a vector multiplication and not a entry-wise multiplication
the number of 50 iterations should be enough for this example. In cases where your 2nd eigenvalue is also close to one this number will be much larger
the function EigenvalueDecomposition.getV returns the eigenvectors in the orientation you expect (row / column)
Note that a valid transition matrix (the matrix of jumping probabilities) has row or column sum of 1 (a matter of definition) since the chances of staying or switching must be 100%. This implies the existance of an eigenvectors of one. From your use of initial transpose of the matrix, I assume you need row-sum of one.
Since you seem to not have an eigenvalue of 1, the most logical error is a typo in your matrix.

Related

How can you find the max rectangular area in histogram recursively?

I need to come up with a recursive solution for the "Maximum rectangular area in a histogram" problem. For those not familiar with it, here´s an explanation:
A histogram is a display of statistical information that uses rectangles to show the frequency of data items. These rectangles are usually vertical.
In the histogram, all the bars are usually different sizes. In the problem, you have to find the maximum rectangular area in the histogram. For example, if the sizes are [4,1,4,5,6] the maximum area is 12 because we take the last 3 bars [4,5,6], take the shortest bar [4], and apply the rectangular area formula (4x3=12).
The only requirements are:
-It has to be done in java.
-Stacks can´t be used.
-It has to be recursive.
In case it helps, i have a non-recursive solution:
public static int MaxHistograma(int[] histograma) {
if (histograma.length == 1) {
return histograma[0];
}
int res = 0;
for (int i = 0; i < histograma.length - 1; i++) {
int min = histograma[i];
for (int j = i + 1; j < histograma.length; j++) {
min = Math.min(min, histograma[j]);
res = Math.max(histograma[j], Math.max(res, min * (j - i + 1)));
res = Math.max(res, histograma[i]);
}
}
return res;
}
If you start with the base case of a histogram with 1 column then the largest area is simply equal to height of the column.
When you add a include the 2nd column, the area may be either be
1) Equal to the max area from the previous histogram
2) Equal to the height of this 2nd column
3) Equal to the area of the new rectangle which has been formed horizontally
When you look at the third column, it's the same. It's either the max area from the previous histogram (2 cols), the height of the new column (red), or the area of the horizontal rectangle (purple).
Here is a code skeleton to achieve this
private int getLargestArea(int[] histogram)
{
if (histogram.length > 1)
{
int horizontalRectangleArea = 0; //TODO
int lastColumnHeight = 0; //TODO
return Math.max(
Math.max(horizontalRectangleArea, lastColumnHeight),
getLargestArea(Arrays.copyOf(histogram, histogram.length - 1)) //copy the array, subtracting 1 column
);
}
else
{
return histogram[0]; // height of single column
}
}

Matrix multiplication Big O notation

I have a question regarding best case scenario for this piece of code and worst case scenario in Big O notation. From my point of view, it should be O (n^3) for both cases but some people disagree.
public int [][] multiply (int [][] A, int
[][] B, int n) {
int [][] C = new int[n][n]; - 1 ( ignored )
for(int i=0; i<n; i++) { - n
for(int j=0; j<n; j++) { - n
if(A[i][j ]!=0) { - 1 ( ignored )
for (int k=0; k<n; k++) { - n
C[i][k] += A[i][j]*B[j][k]; -
}
}
}
}
return C;
}
It is true that matrix multiplication takes O(n^3) time to run in average and worst cases. For 2 matrices of dimensions m x n and n x p respectively, there is going to be a total of mnp (or n^3 for simplicity) calculations, one for each entry in the resultant matrix. As for the best case, it depends on what your program does when it sees that at least one of the matrices is a zero matrix (all entries in the matrix are 0). If it can spot a zero matrix, then you can short circuit the program. In this case, the running time is going to be O(n^2) (you just scan a couple of n x n matrices at most), which is the best that can be achieved for matrix multiplication. If this optimization is not available, the program will run in O(n^3) in any case. Either way, you can still say that the best case is O(n^3) because of the definition of Big-O notation, but that is not of interest to most people.
The line of code shown above must be corrected.
C[i][k] += A[i][j]*B[j][k];
It should be corrected as follows.
C[i][j] += A[i][k]*B[k][j];

How to check which points are in a circle?

Okay so say there is a grid, which I have stored as a 2 dimensional array, that is 10 by 10.
int[][] grid = new int[10][10];
The origin of the grid is at the bottom left, like a normal x y plane, and there is a circle of radius 5 in the centre of the grid at (5,5), like so:
I want to go through this array and basically check which points are inside the circle, but I do not want to loop through the entire array. By default, every point on a corner is not going to be in the circle, so I would want to ignore those, and similarly the points that are close to the corner, etc.
Just the points that are in the circle. I have a much bigger grid and looping through unnecessary stuff that I already know isn't in the circle would waste time. Is there a way to do this? Because, given that I already know the radius and centre of the circle, there should be a nice easy way to go through those points which are in the circle and change them from 0 to -1, for example.
Otherwise, I would stand to lose 100 - 25π ≈ 21.46% time.
BETTER CLARITY: I already know that I can bound the circle with a square, and loop through the points in that square and check each points distance from the centre of the circle (x^2 + y^2 < r^2), but this is what I am trying to avoid, due to the constant overhead every time of checking the bits that aren't in the circle, when I know they are not in the circle beforehand.
Ok, after a long discussion, here is the solution. You scan across one axis of a quarter slice, compute the extension to which you need to fill that quarter outwards and then fill all 4 quarters at once.
int n = 1000;
// you will need to think yourself about the odd number or elements
int r = n / 2;
int r2 = r * r;
Putting (0,0) at the centre of the matrix in both cases, the optimized solutions can look like this:
int[][] grid0 = new int[n][n];
for (int i = 0; i < r; i++) {
double m = Math.sqrt(r2 - i * i);
for (int j = 0; j < m; j++) {
grid0[r + i][r + j] = 1;
grid0[r + i][r - j] = 1;
grid0[r - i][r + j] = 1;
grid0[r - i][r - j] = 1;
}
}
As commented elsewhere, the extension of filling the circle is computed in O(n).
Here is the straightforward validation:
int[][] grid1 = new int[n][n];
// you will need to think yourself about the even number
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if ((i - r) * (i - r) + (j - r) * (j - r) < r2) {
grid1[i][j] = 1;
}
}
}
Both produce the same number of filled points.
Time measurements over 10000 executions (with array initialization outside of the time loop):
the optimized one 6.0s
the exhaustive one 15.6s
So, I do admit there is a difference, an astonishing one. Although for a fair comparison, the latter snippet should also be using a quarter slice of the circle.
One can speed up the optimized solution even further using some sort of memory copy routine to fill the values from 0 to the computed point rather than a plain loop, but that is beyond the scope.

knapsack 01 with twist

I'm doing a Knapsack in Java where we only use weights no value. The weightlimit is 1000. We get 5 weights scanned from keyboard which we use.
The twist is that you can actually go over 1000 aslong as its the closets to 1000. So in one scenario we have 2 possible weights 990 and 1010 and the program is suposed to pick the higher one.
The scanned numbers can never be higher then 1000.
package kapsackidone;
import java.util.Scanner;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.*;
public class Kapsack {
public static void main(String[] args) throws Exception {
BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
int [] wt=new int[5];
int W = 1000;
System.out.println("Enter Weight 5 weights");
for(int i=0; i<5; i++)
{
wt[i]=Integer.parseInt(reader.readLine());
}
System.out.println(knapsack(wt, W));
}
public static int knapsack(int wt[], int W) {
int N = wt.length;
int[][] V = new int[N + 1][W + 1];
for (int col = 0; col <= W; col++) {
V[0][col] = 0;
}
for (int row = 0; row <= N; row++) {
V[row][0] = 0;
}
for (int item=1;item<=N;item++){
for (int weight=1;weight<=W;weight++){
if(wt[item-1] > weight)
{
V[item][weight] = V[item-1][weight];
}
else if((weight - V[item-1][weight]) < (weight - (V[item-1][weight - wt[item-1]] + wt[item-1])))
{
V[item][weight] = V[item-1][weight];
}
else
{
V[item][weight] = V[item-1][weight - wt[item-1]] + wt[item-1];
}
}
}
return V[N][W];
}
}
I am really struggling with how I can get this done.
Before you ask no its not homework im gonna be a project manager for a new group of people that consist of developers so im just trying to learn some java so that i understand a bit of what they do even tho i doubt i will be able to help with the coding.
I would just run it twice.
In first run find the "classic" solution with best weight less than 1000.
In second run, increase the max value 1000 to the max possible value which is allowed based on previous solution.
Dont worry about "it is two times slower", multiplying complexity by constant does not change the complexity, which is the important thing in knapsack problem.
If your code is working then you can probably count the best solution as this
System.out.println(knapsack(wt,2*W - knapsack(wt, W));
Or you can write it as this to be more clear what is happening (it does exactly the same as that one-line above)
int bestClassicSolution = knapsack(wt, W);
int differenceAgainstMaxWeight = W - bestClassicSolution;
int newMaxWeight = W + differenceAgainstMaxWeight;
int bestSolution = knapsack(wt, newMaxWeight);
System.out.println(bestSolution);
EDIT : The solution above works for this condition select as big solution as possible, but it must not differ from 1000 more than "below 1000" best solution. The OP actually wants little different thing - the "limit" stays, but it should be the closest to the 1000 but as high as possible.
So real solution would to create reversed knapsack method, which will find the solution with minimum value BUT must be bigger than "min" variable.
public static void main(String[] args) throws Exception {
BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
int [] wt=new int[5];
int W = 1000;
System.out.println("Enter Weight 5 weights");
for(int i=0; i<5; i++)
{
wt[i]=Integer.parseInt(reader.readLine());
}
int bestClassicSolution = knapsack(wt, W);
int differenceAgainstMaxWeight = W - bestClassicSolution;
int newMaxWeight = W + differenceAgainstMaxWeight;
int bestMaxSolution = reversedKnapsack(wt, newMaxWeight, W);
int differenceAgainstWeightAboveW = W - bestMaxSolution;
if (differenceAgainstWeightAboveW <= differenceAgainstMaxWeight){
System.out.println(bestMaxSolution);
} else {
System.out.println(bestClassicSolution);
}
}
public static int reversedKnapsack(int wt[], int W, int min) {
//similar to knapsack method, but the solution must be as small as possible and must be bigger than min variable
}
Verbatim from Wikipedia — Subset sum problem.
The problem can be solved in pseudo-polynomial time using dynamic programming. Suppose the sequence is
x1, ..., xN
and we wish to determine if there is a nonempty subset which sums to zero. Define the boolean-valued function Q(i, s) to be the value (true or false) if
"there is a nonempty subset of x1, ..., xi which sums to s".
Thus, the solution to the problem "Given a set of integers, is there a non-empty subset whose sum is zero?" is the value of Q(N, 0).
Let A be the sum of the negative values and B the sum of the positive values. Clearly, Q(i, s) = false, if s < A or s > B. So these values do not need to be stored or computed.
Create an array to hold the values Q(i, s) for 1 ≤ i ≤ N and A ≤ s ≤ B.
The array can now be filled in using a simple recursion. Initially, for A ≤ s ≤ B, set
Q(1, s) := (x1 == s)
where == is a boolean function that returns true if x1 is equal to s, false otherwise.
Then, for i = 2, …, N, set
Q(i, s) := Q(i − 1, s) or (xi == s) or Q(i − 1, s − xi), for A ≤ s ≤ B.
After computing the values of Q, we may loop through them, and take the true value which is closest to the limit.
As for the value of S, we need to take the sum of the weights given to us.
The classical knapsack problem is discussed in a Wikipedia article; the dynamic programming formulation for the classical problem can be adapted to the following problem.
Given weights w_1,...,w_n and a target capacity W, find a subset of the items for which the total weight is minimal, but larger than W.
To avoid pathological cases, we assume that the sum of the weights is largert than W, otherwise there is no solution. Let W_MAX denote the sum of all weights.
For the dynamic programming formulation, let
m[i,j] for each i in 0,...,n and j in 0,...,W_MAX
denote the minimum weight larger than W attainable by discarding weights from 0,...,i with total weight exactly j.
We obtain
m[0,j] = W_MAX for each j in 0,...n
and get the recurrence relation
m[i,j] = min {
m[i-1, i ], // corresponds to keeping weight i
m[i-1, j - w[i]] - w[i] // corresponds to discarding weight i
}
and evaluation can be implemented by iterating i=0,...,n and j=0,...,W_MAX; accedd to m outside of these bounds must be assumed to yield W_MAX. Similar to the classical knapsack problem, the actual set of items to discard can be found by backtracking.
Finally, the given instance can be optimized twice; first with the algorithm above, then with the classical knapsack algorithm.
I would evaluate this problem first as a classical knapsack problem taking value[i] = weight[i] ;, where i is the i'th item and maximum weight to be the given max_wt (1000 kg) and item[] be an array containing the items in ascending order of their weights . Let the answer of this problem be x , say 990 kg , now i would calculate the difference 'd' , d = max_wt - x ; iterate over item[] till item[i] exceeds d : int i = 0 ;
while(item[i] < d )
i++;
,lastly add the first item that exceeds 'd' to the answer you got through the classical knapsack problem :
answer = dp[n-1][w-1] + item[i] \\dp[n-1][w-1] is the answer of the classical
\\knapsack problem

JAVA: Havel-Hakimi algorithm (Algorithm for determing whether the sequence of numbers can represent degrees of vertices in a graph)

I want to write a code in java that helps you determin whether the numbers can represent degrees of vertices in a graph. We were told in the algorithmic graph theory class that there's a simple way to solve that with an algorithm that works like this:
You put the numbers in descending order
3,3,2,1
Then you take the biggest one (in this case it's 3), 'erase it' (set it to zero in an array, I guess) and then from n-following numbers subtract 1 (n equals the value of this biggest number, in this case you subtract one from the following 3 numbers)
0,2,1,0
If needed, put the numbers in descending order once again and repeat the algorithm, erase the biggest number and subtract 1 from n-following numbers.
Do this until you either:
a) come across negative number(s), in which case it means that your sequence of numbers cannot represent degrees of vertices in a graph or
b) you are at the end of your algorithm and all the numbers are zeroes which means that these numbers can represent degrees of vertices in a graph
For these particular numbers it should go like this
3,3,2,1
0,2,1,0
0,0,0,-1
And as there's -1, it means that this sequence of numbers couldn't represent degrees of vertices in a graph.
So far my code for the algorithm and checking whether it is done looks like this (I already have the main method with scanner in it so the user can write down how many vertices and what degrees he wants to find out about, this is just where I don't know what to do next):
public void alg() {
int size = this.vertices.length;
do {
this.check();
for (int i = 0; i < size; i++) {
int biggest = i;
int max = this.vertices[biggest];
this.vertices[biggest] = 0;
for (int j = 0; j <= max + 1; j++) {
this.vertices[j+1]--;
System.out.println(Arrays.toString(this.vertices));
biggest++;
}
}
} while (this.finished != true);
}
public void check() {
Integer[] zeroes = new Integer[this.vertices.length];
Arrays.fill(zeroes, 0); //this probably isn't necessary
int count = 0;
for (int i = 0; i < this.vertices.length; i++) {
if (this.vertices[i] < 0) {
this.finished = true;
System.out.println("not a graph");
}
if(this.vertices[i] == 0) {
count++;
}
}
if (Arrays.equals(this.vertices, zeroes)) {
System.out.println("a graph");
}
}
So if the user's sequence of numbers is 3,3,2,1, the programme will print out only this and won't continue
[3, 3, 2, 1]
[0, 2, 2, 1]
[0, 2, 1, 1]
[0, 2, 1, 0]
I guess I'm missing something in the loops but I can't figure out what. Thanks for the help in advance!
The problem seems to be in your inner for loop. In your example it runs from j = 0 to j = 4.
Inside the loop you try to access this.vertices[j+1] which would be at the end of this loop the 5th entry of this array. You should get an exception by the Java Runtime here.
The second problem is, that you always start at the first index of you array.
Try changing this for loop to
for (int j = i+1; j <= max + i ; j++) {
this.vertices[j]--;
System.out.println(Arrays.toString(this.vertices));
biggest++;
}
You need to consider that even if max is 8 the array size could be 3, so you would get an IndexOutOfBoundsException using just max as a stop condition for the for j loop. What you need to use is min(max,size).

Categories