I have been working on building a name generator based off of Markov Chains. So far, the code can find the probability of the next letter and place it nicely in the LinkedHashMap
(Which I will refer to as LHM past this point) named states
by using the generateProbabilities()
function. The LHM stores the data so that the first key is the state, and the second is the transition letter.
However, this is where things start to get interesting. I have three output statements, one in the generate()
function, and two in the WeightedRandom
init. Here is my output:
EDITED SECTION:
Called from generate(): [0.13333333333333333, 0.13333333333333333, 0.13333333333333333, 0.06666666666666667, 0.13333333333333333, 0.06666666666666667, 0.06666666666666667, 0.13333333333333333, 0.06666666666666667, 0.06666666666666667]
Called from WeightedRandom (Size): 10
Called from WeightedRandom (Values): [0.13333333333333333, 0.13333333333333333, 0.13333333333333333, 0.06666666666666667, 0.13333333333333333, 0.06666666666666667, 0.06666666666666667, 0.13333333333333333, 0.06666666666666667, 0.06666666666666667]
Exception in thread "main" java.lang.NullPointerException
at WeightedRandom.<init>(WeightedRandom.java:14)
at MarkovChain.generate(MarkovChain.java:102)
at Temp.main(Temp.java:7)
The weird part is that the NPE on line 14 is the second println statement in WeightedRandom
, and it was thrown after it printed out the data. The third println prints without an error. So, it isn't like I forgot to initialize it, or didn't have the right key to get the NPE. The code is below:
MarkovChain.java
public class MarkovChain {
public String filePath;
public LinkedHashMap<String,LinkedHashMap<String,Double>> states = new LinkedHashMap<String,LinkedHashMap<String,Double>>();
public MarkovChain(String filePath){
this.filePath = filePath;
}
public void generateProbabilities(String delimiter){
//Creates a hashmap of probabilities for each letter.
}
public String generate(int iterations){
Random rand = new Random();
LinkedHashMap<String,Double> currProbabilities = states.get("a"); // Placeholder for random start state;
String output = "";
WeightedRandom weightRand;
System.out.println("Called from generate(): " + currProbabilities.values());
for(int i = 0; i<iterations; i++){
weightRand = new WeightedRandom(currProbabilities);
String newState = weightRand.compute();
output+=newState;
currProbabilities = states.get(newState);
}
return output;
}
}
WeightedRandom.java
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
public class WeightedRandom {
LinkedHashMap<String,Double> items;
Random rand = new Random();
public WeightedRandom(LinkedHashMap<String,Double> items){ //Currently Single-Purpose.
this.items = items;
System.out.println("Called from WeightedRandom (Size): " + items.size());
System.out.println("Called from WeightedRandom (Values): " + items.values());
}
public String compute(){
items.values();
/*
Set s = items.entrySet();
Iterator i = s.iterator();
double randNum = rand.nextDouble();
double runningTotal = 0;
String output = null;
while(i.hasNext() && output == null){
Map.Entry entry = (Map.Entry)i.next();
if(randNum < runningTotal + (double)entry.getValue() && randNum > runningTotal){
output = (String)entry.getKey();
}
}
return output;
*/
return null;
}
}