summaryrefslogtreecommitdiff
path: root/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedGrammar.java
diff options
context:
space:
mode:
Diffstat (limited to 'BJC-Utils2/src/main/java/bjc/utils/gen/WeightedGrammar.java')
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/gen/WeightedGrammar.java177
1 files changed, 177 insertions, 0 deletions
diff --git a/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedGrammar.java b/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedGrammar.java
new file mode 100644
index 0000000..8733723
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedGrammar.java
@@ -0,0 +1,177 @@
+package bjc.utils.gen;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+import java.util.function.Function;
+
+import bjc.utils.funcdata.FunctionalList;
+
+/**
+ * A random grammar, where certain rules will come up morre often than
+ * others.
+ *
+ * @author ben
+ *
+ * @param <E> The values that make up sentances of this grammar.
+ */
+public class WeightedGrammar<E> {
+ protected Map<E, WeightedRandom<FunctionalList<E>>> rules;
+ protected Map<E, WeightedGrammar<E>> subgrammars;
+ private Random sr;
+
+ /**
+ * Create a new weighted grammar that uses the specified source of randomness.
+ */
+ public WeightedGrammar(Random src) {
+ this();
+ sr = src;
+ }
+
+ /**
+ * Create a new weighted grammar.
+ */
+ public WeightedGrammar() {
+ rules = new HashMap<>();
+ }
+
+ /**
+ * Add a case to an already existing rule.
+ *
+ * @param rule The rule to add a case to.
+ * @param prob The probability for this rule to be chosen.
+ * @param cse The case being added.
+ */
+ public void addCase(E rule, int prob, FunctionalList<E> cse) {
+ WeightedRandom<FunctionalList<E>> rn = rules.get(rule);
+
+ rn.addProb(prob, cse);
+ }
+
+ /**
+ * Add a new rule with no cases.
+ * @param name The name of the rule to add.
+ * @return Whether or not the rule was succesfully added.
+ */
+ public boolean addRule(E name) {
+ if(sr == null) {
+ sr = new Random();
+ }
+ return addRule(name, new WeightedRandom<>(sr));
+ }
+
+ /**
+ * Add a new rule with a set of cases.
+ * @param name The name of the rule to add.
+ * @param rnd The set of cases for the rule.
+ * @return Whether or not the rule was succesfully added.
+ */
+ public boolean addRule(E name, WeightedRandom<FunctionalList<E>> rnd) {
+ if (rules.containsKey(name)) {
+ return false;
+ } else {
+ rules.put(name, rnd);
+ return true;
+ }
+ }
+
+ /**
+ * Add a subgrammar.
+ * @param name The name of the subgrammar.
+ * @param subG The subgrammar to add.
+ * @return Whether or not the subgrammar was succesfully added.
+ */
+ public boolean addSubGrammar(E name, WeightedGrammar<E> subG) {
+ if (subgrammars.containsKey(name)) {
+ return false;
+ } else {
+ subgrammars.put(name, subG);
+ return true;
+ }
+ }
+
+ /**
+ * Generate a set of debug sentences for the specified rule.
+ * Only generates sentances one layer deep.
+ * @param rl The rule to test.
+ * @return A set of sentances generated by the specified rule.
+ */
+ public FunctionalList<FunctionalList<E>> debugVals(E rl) {
+ FunctionalList<FunctionalList<E>> fl = new FunctionalList<>();
+
+ WeightedRandom<FunctionalList<E>> random = rules.get(rl);
+
+ for (int i = 0; i < 10; i++) {
+ fl.add(random.genVal());
+ }
+
+ return fl;
+ }
+
+ /**
+ * Generate a generic sentance from a initial rule.
+ *
+ * @param initRule The initial rule to start with.
+ * @param f The function to transform grammar output into something.
+ * @param spacer The spacer element to add in between output tokens.
+ * @return A randomly generated sentance from the specified initial rule.
+ */
+ public <T> FunctionalList<T> genGeneric(E initRule, Function<E, T> f,
+ T spacer) {
+ FunctionalList<T> r = new FunctionalList<>();
+
+ if (subgrammars.containsKey(initRule)) {
+ subgrammars.get(initRule).genGeneric(initRule, f, spacer)
+ .forEach(rp -> {
+ r.add(rp);
+ r.add(spacer);
+ });
+ } else if (rules.containsKey(initRule)) {
+ rules.get(initRule).genVal().forEach(
+ rp -> genGeneric(rp, f, spacer).forEach(rp2 -> {
+ r.add(rp2);
+ r.add(spacer);
+ }));
+ } else {
+ r.add(f.apply(initRule));
+ r.add(spacer);
+ }
+
+ return r;
+ }
+
+ /**
+ * Generate a random list of grammar elements from a given initial rule.
+ * @param initRule The initial rule to start with.
+ * @param spacer The item to use to space the list.
+ * @return A list of random grammar elements generated by the specified rule.
+ */
+ public FunctionalList<E> genList(E initRule, E spacer) {
+ return genGeneric(initRule, s -> s, spacer);
+ }
+
+ /**
+ * Get the subgrammar with the specified name.
+ * @param name The name of the subgrammar to get.
+ * @return The subgrammar with the specified name.
+ */
+ public WeightedGrammar<E> getSubGrammar(E name) {
+ return subgrammars.get(name);
+ }
+
+ /**
+ * Remove a rule with the specified name.
+ * @param name The name of the rule to remove.
+ */
+ public void removeRule(E name) {
+ rules.remove(name);
+ }
+
+ /**
+ * Remove a subgrammar with the specified name.
+ * @param name The name of the subgrammar to remove.
+ */
+ public void removeSubgrammar(E name) {
+ subgrammars.remove(name);
+ }
+}