public class Structure <E extends Comparable<? super E>>{
private E[] d;
public Structure() { d = getArray(1); }
public void show() { show(0); }
private void show(int p){
if( p < d.length && d[p] != null) {
show(r(p));
show(l(p));
System.out.print(d[p] + " ");
}
}
public void add(E obj) {
int p = getPos(obj);
if(p >= d.length)
resize();
d[p] = obj;
}
public boolean present(E obj){
int p = getPos(obj);
return p < d.length && d[p] != null;
}
private int getPos(E obj){
int p = 0;
while(p < d.length && d[p] != null){
int dir = <*1>;
if(dir < 0)
p = l(p);
else if(dir >0)
p = r(p);
else
return p;
}
return p;
}
private E[] getArray(int size) {
return (E[]) new Comparable[size];
}
private void resize(){
E[] temp = getArray(d.length*2 + 1);
for( int i = 0; i < d.length; i++)
temp[i] = d[i];
d = temp;
}
private int l(int i) { return 2 * i + 1;}
private int r(int i) { return 2 * i + 2;}
}
Take that data structure. What is it? I think it's a binary search tree, but I'm pretty sure it's that or a max heap. I'm largely leaning BST, though.
public void fillCol (int n, Collection<Integer> col){
for(int i = 0; i < n; i++)
col.add (i);
}
What is the big O for that method if col is a linked list? I think it's O (N).
And is col a tree set? I think it's O (N log N).
public void sort (List<Double> data){
int lim = data.size();
for(int i = 0; i < lim; i++){
int m = i;
for(int j = i + 1; j < lim; j++)
if(data.get(j) < data.get(m) )
m = j;
data.set( i, data.set(m, data.get(i)));
}
}
and big o for each type of list. I think it's O (N²) for ArrayList and O (N³) for Linked list.
A class that represents a graph uses an adjacency matrix to represent the connections between verticies. What are the space requirements for a graph that contains N nodes with an average of M connections per node?
I think it's O (N²)
Please help! Confirm if I'm right, or correct me if I'm wrong.
It looks like a (not-necessarily-balanced) binary tree, implemented in a manner similar to how a binary heap is often done - in an array where the children of i are 2i and 2i+1.
Someone should've documented what they were doing better.
I agree with your assessment of fillCol.
That sort callable seems like an unrelated question, and yes it does look O(n^2) with a normal data structure.
Related
I'm currently enrolled in the Princeton Algorithms course (Part 1) and it talks about an improvement to the quick-union algorithm by maintaining an extra array sz[i] to count the number of objects in the tree rooted i, but it doesn't show how to do that.
Where and how is that counter supposed to be implemented? I've tried doing it in the root method, but I realized it wouldn't count the children of a given object.
This is the unaltered code given in the course:
public class QuickUnionUF {
private int[] id;
public QuickUnionUF(int N) {
id = new int[N];
for (int i = 0; i < N; i++) id[i] = i;
}
private int root(int i) {
while (i != id[i]) i = id[i];
return i;
}
public boolean connected(int p, int q) {
return root(p) == root(q);
}
public void union(int p, int q) {
int i = root(p);
int j = root(q);
id[i] = j;
}
}
To perform weighted union, you need to know weight of every tree, so make parallel array wt[], where wt[k] contains size of tree with root k. Initial weigths are 1.
Glue smaller tree to the root of larger tree and update weight
public void union(int p, int q) {
int i = root(p);
int j = root(q);
if wt[i] < wt[j] {
id[i] = j;
wt[j] += wt[i]
}
else {similar for j->i}
}
Initialization
public class QuickUnionUF {
private int[] id;
private int[] wt;
public QuickUnionUF(int N) {
id = new int[N];
wt = new int[N];
for (int i = 0; i < N; i++) {
id[i] = i;
wt[i] = 1;
}
}
In an effort to learn and use hidden markov models, I am writing my own code to implement them. I am using this wiki article to help with my work. I do not wish to resort to pre-written libraries, because I have found I can achieve a better understanding if I write it myself. And no, this isn't a school assignment! :)
Unfortunately, my highest level of education consists of high school computer science and statistics. I have no background in Machine Learning besides the casual poking around with ANN libraries and TensorFlow. I am therefore having a bit of trouble translating mathematical equations into code. Specifically, I'm worried my implementations of the alpha and beta functions aren't functionally correct. If anyone can assist in describing where I messed up and how to correct my mistakes to have a functioning HMM implementation, it'd be greatly appreciated.
Here are my class-wide globals:
public int n; //number of states
public int t; //number of observations
public int time; //iteration holder
public double[][] emitprob; //Emission parameter
public double[][] stprob; //State transition parameter
public ArrayList<String> states, observations, x, y;
My constructor:
public Model(ArrayList<String> sts, ArrayList<String> obs)
{
//the most important algorithm we need right now is
//unsupervised learning through BM. Supervised is
//pretty easy.
//need hashtable of count objects... Aya...
//perhaps a learner...?
states = sts;
observations = obs;
n = states.size();
t = observations.size();
x = new ArrayList();
y = new ArrayList();
time = 0;
stprob = new double[n][n];
emitprob = new double[n][t];
stprob = newDistro(n,n);
emitprob = newDistro(n,t);
}
The newDistro method is for creating a new, uniform, normal distribution:
public double[][] newDistro(int x, int y)
{
Random r = new Random(System.currentTimeMillis());
double[][] returnme = new double[x][y];
double sum = 0;
for(int i = 0; i < x; i++)
{
for(int j = 0; j < y; j++)
{
returnme[i][j] = Math.abs(r.nextInt());
sum += returnme[i][j];
}
}
for(int i = 0; i < x; i++)
{
for(int j = 0; j < y; j++)
{
returnme[i][j] /= sum;
}
}
return returnme;
}
My viterbi algorithm implementation:
public ArrayList<String> viterbi(ArrayList<String> obs)
{
//K means states
//T means observations
//T arrays should be constructed as K * T (N * T)
ArrayList<String> path = new ArrayList();
String firstObservation = obs.get(0);
int firstObsIndex = observations.indexOf(firstObservation);
double[] pi = new double[n]; //initial probs of first obs for each st
int ts = obs.size();
double[][] t1 = new double[n][ts];
double[][] t2 = new double[n][ts];
int[] y = new int[obs.size()];
for(int i = 0; i < obs.size(); i++)
{
y[i] = observations.indexOf(obs.get(i));
}
for(int i = 0; i < n; i++)
{
pi[i] = emitprob[i][firstObsIndex];
}
for(int i = 0; i < n; i++)
{
t1[i][0] = pi[i] * emitprob[i][y[0]];
t2[i][0] = 0;
}
for(int i = 1; i < ts; i++)
{
for(int j = 0; j < n; j++)
{
double maxValue = 0;
int maxIndex = 0;
//first we compute the max value
for(int q = 0; q < n; q++)
{
double value = t1[q][i-1] * stprob[q][j];
if(value > maxValue)
{
maxValue = value; //the max
maxIndex = q; //the argmax
}
}
t1[j][i] = emitprob[j][y[i]] * maxValue;
t2[j][i] = maxIndex;
}
}
int[] z = new int[ts];
int maxIndex = 0;
double maxValue = 0.0d;
for(int k = 0; k < n; k++)
{
double myValue = t1[k][ts-1];
if(myValue > maxValue)
{
myValue = maxValue;
maxIndex = k;
}
}
path.add(states.get(maxIndex));
for(int i = ts-1; i >= 2; i--)
{
z[i-1] = (int)t2[z[i]][i];
path.add(states.get(z[i-1]));
}
System.out.println(path.size());
for(String s: path)
{
System.out.println(s);
}
return path;
}
My forward algorithm, which takes place of the alpha function as described later:
public double forward(ArrayList<String> obs)
{
double result = 0;
int length = obs.size()-1;
for(int i = 0; i < n; i++)
{
result += alpha(i, length, obs);
}
return result;
}
The remaining functions are for implementing the Baum-Welch Algorithm.
The alpha function is what I'm afraid I'm doing wrong of the most on here. I had trouble understanding which "direction" it needs to iterate over the sequence - Do I start from the last element (size-1) or the first (at index zero) ?
public double alpha(int j, int t, ArrayList<String> obs)
{
double sum = 0;
if(t == 0)
{
return stprob[0][j];
}
else
{
String lastObs = obs.get(t);
int obsIndex = observations.indexOf(lastObs);
for(int i = 0; i < n; i++)
{
sum += alpha(i, t-1, obs) * stprob[i][j] * emitprob[j][obsIndex];
}
}
return sum;
}
I'm having similar "correctness" issues with my beta function:
public double beta(int i, int t, ArrayList<String> obs)
{
double result = 0;
int obsSize = obs.size()-1;
if(t == obsSize)
{
return 1;
}
else
{
String lastObs = obs.get(t+1);
int obsIndex = observations.indexOf(lastObs);
for(int j = 0; j < n; j++)
{
result += beta(j, t+1, obs) * stprob[i][j] * emitprob[j][obsIndex];
}
}
return result;
}
I'm more confident in my gamma function; However, since it explicitly requires use of alpha and beta, obviously I'm worried it'll be "off" somehow.
public double gamma(int i, int t, ArrayList<String> obs)
{
double top = alpha(i, t, obs) * beta(i, t, obs);
double bottom = 0;
for(int j = 0; j < n; j++)
{
bottom += alpha(j, t, obs) * beta(j, t, obs);
}
return top / bottom;
}
Same for my "squiggle" function - I do apologize for naming; Not sure of the actual name for the symbol.
public double squiggle(int i, int j, int t, ArrayList<String> obs)
{
String lastObs = obs.get(t+1);
int obsIndex = observations.indexOf(lastObs);
double top = alpha(i, t, obs) * stprob[i][j] * beta(j, t+1, obs) * emitprob[j][obsIndex];
double bottom = 0;
double innerSum = 0;
double outterSum = 0;
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
{
innerSum += alpha(i, t, obs) * stprob[i][j] * beta(j, t+1, obs) * emitprob[j][obsIndex];
}
outterSum += innerSum;
}
return top / bottom;
}
Lastly, to update my state transition and emission probability arrays, I have implemented these functions as aStar and bStar.
public double aStar(int i, int j, ArrayList<String> obs)
{
double squiggleSum = 0;
double gammaSum = 0;
int T = obs.size()-1;
for(int t = 0; t < T; t++)
{
squiggleSum += squiggle(i, j, t, obs);
gammaSum += gamma(i, t, obs);
}
return squiggleSum / gammaSum;
}
public double bStar(int i, String v, ArrayList<String> obs)
{
double top = 0;
double bottom = 0;
for(int t = 0; t < obs.size()-1; t++)
{
if(obs.get(t).equals(v))
{
top += gamma(i, t, obs);
}
bottom += gamma(i, t, obs);
}
return top / bottom;
}
In my understanding, since the b* function includes a piecewise function that returns either 1 or 0, I think implementing it in an "if" statement and only adding the result if the string is equal to the observation history is the same as what is described, since the function would render the call to gamma 0, thus saving a little computation time. Is this correct?
In summation, I want to get my math right, to ensure a successful (albeit simple) HMM implementation. As for the Baum-Welch algorithm, I am having trouble understanding how to implment the complete function - would it be as simple as running aStar over all states (as an n * n FOR loop) and bStar for all observations, inside a loop with a convergence function? Also, what would be a best-practice function for checking for convergence without overfitting?
Please let me know of everything I need to do in order to get this right.
Thank you heavily for any help you can give me!
To avoid underflow, one should use a scaling factor in the forward and backward algorithms. To get the correct result, one uses nested for loops and the steps are forward in the forward method.
The backward method is similar to the forward function.
You invoke them from the method of the Baum-Welch algorithm.
The puzzle:
Follow up for N-Queens problem.
Now, instead outputting board configurations, return the total number of distinct solutions.
Here's the code:
public class Solution {
public int totalNQueens(int n) {
boolean[][] board = new boolean[n][n];
return totalNQueens(board, 0, n);
}
private int totalNQueens(boolean[][] board, int cur, int n) {
int res = 0;
if(cur == n) {
return 1;
}
for(int i = 0; i < n; i++) {
if(!board[cur][i]) {
boolean[][] subboard = board.clone();
for(int r = cur + 1; r < n; r++) {
subboard[r][i] = true;
}
for(int r = cur + 1, c = i - 1; r < n && c >= 0; r++, c--) {
subboard[r][c] = true;
}
for(int r = cur + 1, c = i + 1; r < n && c < n; r++, c++) {
subboard[r][c] = true;
}
res += totalNQueens(subboard, cur+1, n);
}
}
return res;
}
}
The result:
Input:
4
Output:
0
Expected:
2
I can't figure out what's wrong with this code, so please help me, thx in advance.
The problem is with this line:
boolean[][] subboard = board.clone();
Java does not have multi-dimensional arrays. So board is actually a one dimensional array of arrays of booleans. The clone only clones the top level array but not the subarrays. So board[0] is actually the same object as subboard[0] and changes made there are never undone.
I am trying to deep copy a 4d int array as the solution of my algorithm. Unfortunately, when I call that solution at the end of my program, it is not the one that was supposed to be deepcopied. It is also neither the first nor the last created solution. I figure the problem must lie in deepCopy as cloning the same solution in a 1d array works fine.
I am trying to deepcopy w[][][][]:
public Object clone()
{
MySolution copy = (MySolution)super.clone();
copy.w = deepCopyOf(w);
copy.wtour = (int[])this.wtour.clone();
return copy;
} // end clone
#SuppressWarnings("unchecked")
public static <T> T[] deepCopyOf(T[] array) {
if (0 >= array.length) return array;
return (T[]) deepCopyOf(
array,
Array.newInstance(array[0].getClass(), array.length),
0);
}
private static Object deepCopyOf(Object array, Object copiedArray, int index) {
if (index >= Array.getLength(array)) return copiedArray;
Object element = Array.get(array, index);
if (element.getClass().isArray()) {
Array.set(copiedArray, index, deepCopyOf(
element,
Array.newInstance(
element.getClass().getComponentType(),
Array.getLength(element)),
0));
}
else {
Array.set(copiedArray, index, element);
}
return deepCopyOf(array, copiedArray, ++index);
}
I am using the openTS Tabu Search framework by Harder and the fact that the wtour array gets copied just fine shows me that there must be something wrong with the deepcopy method for w[][][][]
EDIT: novic3 assumed that I have to iterate over the different array levels. I tried doing the following which is a little bit different in its approach. Unfortunately, it still doesn't work.
public static int[][][][] deepCopy2(int[][][][] original) {
if (original == null) {
return null;
}
final int[][][][] result = new int[original.length][original[0].length][original.length+1][];
for (int i = 0; i < original.length; i++) {
for (int j = 0; j < original.length; j++) {
for (int q= 0; q <= original.length; q++) {
result[i][j][q] = Arrays.copyOf(original[i][j][q], original[i][j][q].length);
// For Java versions prior to Java 6 use the next:
//System.arraycopy(original[i], 0, result[i], 0, original[i].length);
}
}
}
return result;
}
This should work:
public int[] deepCopy(int[] w) {
int[] ans = new int[w.length];
for (int i = 0; i < w.length; i++) {
ans[i] = w[i];
}
return ans;
}
public int[][] deepCopy2(int[][] w) {
int[][] ans = new int[w.length][];
for (int i = 0; i < w.length; i++) {
ans[i] = deepCopy(w[i]);
}
return ans;
}
public int[][][] deepCopy3(int[][][] w) {
int[][][] ans = new int[w.length][][];
for (int i = 0; i < w.length; i++) {
ans[i] = deepCopy2(w[i]);
}
return ans;
}
public int[][][][] deepCopy4(int[][][][] w) {
int[][][][] ans = new int[w.length][][][];
for (int i = 0; i < w.length; i++) {
ans[i] = deepCopy3(w[i]);
}
return ans;
}
To use, call deepCopy4(w)
My merge sort doesn't seem to be working correctly. When I display the sorted list, it is not sorted and elements are added, where there is supposed to be 9 there is 49.
Anyone see where Im going wrong?
public static <E extends Comparable<E>> void mergeSort(List<E> A) {
int n = A.size();
if (n > 1) {
int half = n / 2;
List<E> B = copyPartialArray(A, 0, half);
List<E> C = copyPartialArray(A, half, n);
mergeSort(B);
mergeSort(C);
merge(B, C, A);
}
}
public static <E extends Comparable<E>> void merge(List<E> B, List<E> C, List<E> A) {
int n1 = B.size();
int n2 = C.size();
int i = 0;
int j = 0;
int k = 0;
while (i < n1 && j < n2) {
if (B.get(i).compareTo(C.get(j)) < 0) {
A.add(k, B.get(i));
i++;
}
else {
A.add(k, C.get(j));
j++;
}
k++;
}
if (i == n1)
for (int p = j; p < n2; p++) {
A.add(k, C.get(p)); k++;
}
else if (j == n2)
for (int p = i; p < n1; p++) {
A.add(k, B.get(p)); k++;
}
}
private static <E extends Comparable<E>> List<E> copyPartialArray(List<E> A, int first, int last) {
int n = last - first;
List<E> copy = new ArrayList<E>(n);
for (int i = 0; i < n; i++)
copy.add(i, A.get(first + i));
return copy;
}
This answer will try to make you realise what's wrong.
It's clear that mergeSort won't do anything to a one element array, but what happens if there are two (for instance [2,1])? You mention there are more elements than before in the result list (list A). Why? What's merge doing to that list? Hint.