/// <summary> /// Randomly sample an FST, assuming any input. /// </summary> /// <param name="result">The array of output symbols, excluding epsilons.</param> /// <param name="fst">The FST.</param> /// <param name="max">The maximum length of the result.</param> /// <returns>total cost</returns> public static double fst_sample(Intarray result, IGenericFst fst, int max = 1000) { double total_cost = 0; int current = fst.GetStart(); for (int counter = 0; counter < max; counter++) { Intarray inputs = new Intarray(); Intarray outputs = new Intarray(); Intarray targets = new Intarray(); Floatarray costs = new Floatarray(); fst.Arcs(inputs, targets, outputs, costs, current); // now we need to deal with the costs uniformly, so: costs.Push(fst.GetAcceptCost(current)); int choice = sample_by_costs(costs); if (choice == costs.Length() - 1) { break; } result.Push(outputs[choice]); total_cost += costs[choice]; current = targets[choice]; } return(total_cost + fst.GetAcceptCost(current)); }
/// <summary> /// Copy one FST to another. /// </summary> /// <param name="dst">The destination. Will be cleared before copying.</param> /// <param name="src">The FST to copy.</param> public static void fst_copy(IGenericFst dst, IGenericFst src) { dst.Clear(); int n = src.nStates(); for (int i = 0; i < n; i++) { dst.NewState(); } dst.SetStart(src.GetStart()); for (int i = 0; i < n; i++) { dst.SetAccept(i, src.GetAcceptCost(i)); Intarray targets = new Intarray(), outputs = new Intarray(), inputs = new Intarray(); Floatarray costs = new Floatarray(); src.Arcs(inputs, targets, outputs, costs, i); int inlen = inputs.Length(); if (inlen != targets.Length()) { throw new Exception("ASSERT: inputs.length() == targets.length()"); } if (inlen != outputs.Length()) { throw new Exception("ASSERT: inputs.length() == outputs.length()"); } if (inlen != costs.Length()) { throw new Exception("ASSERT: inputs.length() == costs.length()"); } for (int j = 0; j < inputs.Length(); j++) { dst.AddTransition(i, targets.At1d(j), outputs.At1d(j), costs.At1d(j), inputs.At1d(j)); } } }
/// <summary> /// Copy one FST to another, preserving only lowest-cost arcs. /// This is useful for visualization. /// </summary> /// <param name="dst">The destination. Will be cleared before copying.</param> /// <param name="src">The FST to copy.</param> public static void fst_copy_best_arcs_only(IGenericFst dst, IGenericFst src) { dst.Clear(); int n = src.nStates(); for (int i = 0; i < n; i++) { dst.NewState(); } dst.SetStart(src.GetStart()); for (int i = 0; i < n; i++) { dst.SetAccept(i, src.GetAcceptCost(i)); Intarray targets = new Intarray(), outputs = new Intarray(), inputs = new Intarray(); Floatarray costs = new Floatarray(); src.Arcs(inputs, targets, outputs, costs, i); int inlen = inputs.Length(); if (inlen != targets.Length()) { throw new Exception("ASSERT: inputs.length() == targets.length()"); } if (inlen != outputs.Length()) { throw new Exception("ASSERT: inputs.length() == outputs.length()"); } if (inlen != costs.Length()) { throw new Exception("ASSERT: inputs.length() == costs.length()"); } Dictionary <int, int> hash = new Dictionary <int, int>(); for (int j = 0; j < n; j++) { int t = targets[j]; int best_so_far = -1; if (hash.ContainsKey(t)) { best_so_far = hash[t]; } if (best_so_far == -1 || costs[j] < costs[best_so_far]) { hash[t] = j; } } Intarray keys = new Intarray(); //hash.keys(keys); keys.Clear(); foreach (int key in hash.Keys) { keys.Push(key); } for (int k = 0; k < keys.Length(); k++) { int j = hash[keys[k]]; dst.AddTransition(i, targets[j], outputs[j], costs[j], inputs[j]); } } }
public bool Step() { int node = heap.Pop(); if (node == n) { return(true); // accept has popped up } // get outbound arcs Intarray inputs = new Intarray(); Intarray targets = new Intarray(); Intarray outputs = new Intarray(); Floatarray costs = new Floatarray(); fst.Arcs(inputs, targets, outputs, costs, node); for (int i = 0; i < targets.Length(); i++) { int t = targets[i]; if (came_from[t] == -1 || g[node] + costs[i] < g[t]) { // relax the edge came_from[t] = node; g[t] = g[node] + costs[i]; heap.Push(t, g[t] + Convert.ToSingle(Heuristic(t))); } } if (accepted_from == -1 || g[node] + fst.GetAcceptCost(node) < g_accept) { // relax the accept edge accepted_from = node; g_accept = g[node] + fst.GetAcceptCost(node); heap.Push(n, g_accept); } return(false); }
protected static void write_node(BinaryWriter writer, IGenericFst fst, int index) { Intarray inputs = new Intarray(); Intarray targets = new Intarray(); Intarray outputs = new Intarray(); Floatarray costs = new Floatarray(); fst.Arcs(inputs, targets, outputs, costs, index); int narcs = targets.Length(); write_float(writer, fst.GetAcceptCost(index)); write_int64_LE(writer, narcs); for (int i = 0; i < narcs; i++) { write_int32_LE(writer, inputs[i]); write_int32_LE(writer, outputs[i]); write_float(writer, costs[i]); write_int32_LE(writer, targets[i]); } }
/// <summary> /// Reverse the FST's arcs, adding a new start vertex (former accept). /// </summary> public static void fst_copy_reverse(IGenericFst dst, IGenericFst src, bool no_accept = false) { dst.Clear(); int n = src.nStates(); for (int i = 0; i <= n; i++) { dst.NewState(); } if (!no_accept) { dst.SetAccept(src.GetStart()); } dst.SetStart(n); for (int i = 0; i < n; i++) { dst.AddTransition(n, i, 0, src.GetAcceptCost(i), 0); Intarray targets = new Intarray(), outputs = new Intarray(), inputs = new Intarray(); Floatarray costs = new Floatarray(); src.Arcs(inputs, targets, outputs, costs, i); if (inputs.Length() != targets.Length()) { throw new Exception("ASSERT: inputs.length() == targets.length()"); } if (inputs.Length() != outputs.Length()) { throw new Exception("ASSERT: inputs.length() == outputs.length()"); } if (inputs.Length() != costs.Length()) { throw new Exception("ASSERT: inputs.length() == costs.length()"); } for (int j = 0; j < inputs.Length(); j++) { dst.AddTransition(targets.At1d(j), i, outputs.At1d(j), costs.At1d(j), inputs.At1d(j)); } } }
public override void Arcs(Intarray ids, Intarray targets, Intarray outputs, Floatarray costs, int node) { int n1 = node / l2.nStates(); int n2 = node % l2.nStates(); Intarray ids1 = new Intarray(); Intarray ids2 = new Intarray(); Intarray t1 = new Intarray(); Intarray t2 = new Intarray(); Intarray o1 = new Intarray(); Intarray o2 = new Intarray(); Floatarray c1 = new Floatarray(); Floatarray c2 = new Floatarray(); l1.Arcs(ids1, t1, o1, c1, n1); l2.Arcs(ids2, t2, o2, c2, n2); // sort & permute Intarray p1 = new Intarray(); Intarray p2 = new Intarray(); NarrayUtil.Quicksort(p1, o1); NarrayUtil.Permute(ids1, p1); NarrayUtil.Permute(t1, p1); NarrayUtil.Permute(o1, p1); NarrayUtil.Permute(c1, p1); NarrayUtil.Quicksort(p2, ids2); NarrayUtil.Permute(ids2, p2); NarrayUtil.Permute(t2, p2); NarrayUtil.Permute(o2, p2); NarrayUtil.Permute(c2, p2); int k1, k2; // l1 epsilon moves for (k1 = 0; k1 < o1.Length() && o1.At1d(k1) == 0; k1++) { ids.Push(ids1.At1d(k1)); targets.Push(Combine(t1.At1d(k1), n2)); outputs.Push(0); costs.Push(c1.At1d(k1)); } // l2 epsilon moves for (k2 = 0; k2 < o2.Length() && ids2.At1d(k2) == 0; k2++) { ids.Push(0); targets.Push(Combine(n1, t2.At1d(k2))); outputs.Push(o2.At1d(k2)); costs.Push(c2.At1d(k2)); } // non-epsilon moves while (k1 < o1.Length() && k2 < ids2.Length()) { while (k1 < o1.Length() && o1.At1d(k1) < ids2.At1d(k2)) { k1++; } if (k1 >= o1.Length()) { break; } while (k2 < ids2.Length() && o1.At1d(k1) > ids2.At1d(k2)) { k2++; } while (k1 < o1.Length() && k2 < ids2.Length() && o1.At1d(k1) == ids2.At1d(k2)) { for (int j = k2; j < ids2.Length() && o1.At1d(k1) == ids2.At1d(j); j++) { ids.Push(ids1.At1d(k1)); targets.Push(Combine(t1.At1d(k1), t2.At1d(j))); outputs.Push(o2.At1d(j)); costs.Push(c1.At1d(k1) + c2.At1d(j)); } k1++; } } }