Transition Matrix_to_Transition (Matrix me) { try { if (my nx != my ny) Melder_throw ("Matrix should be square."); autoTransition thee = Transition_create (my nx); for (long i = 1; i <= my nx; i ++) for (long j = 1; j <= my nx; j ++) thy data [i] [j] = my z [i] [j]; return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": not converted to Transition."); } }
Transition Distributions_to_Transition (Distributions underlying, Distributions surface, long environment, Transition adjacency, int greedy) { if (underlying == NULL) return NULL; Transition thee = NULL; /* * Preconditions: range check and matrix matching. */ if (environment < 1 || environment > underlying -> numberOfColumns) error5 (L"Environment (", Melder_integer (environment), L") out of range (1-", Melder_integer (underlying -> numberOfColumns), L").") if (surface && (underlying -> numberOfColumns != surface -> numberOfColumns || underlying -> numberOfRows != surface -> numberOfRows)) error1 (L"Sizes of underlying and surface distributions do not match.") if (adjacency && adjacency -> numberOfStates != underlying -> numberOfColumns) error5 (L"Number of states (", Melder_integer (adjacency -> numberOfStates), L") in adjacency matrix " "does not match number of distributions (", Melder_integer (underlying -> numberOfColumns), L")") /* * Defaults. */ if (surface == NULL) surface = underlying; /* * Create the output object. */ thee = Transition_create (underlying -> numberOfColumns); cherror /* * Copy labels and set name. */ for (long i = 1; i <= thy numberOfStates; i ++) { thy stateLabels [i] = Melder_wcsdup_e (underlying -> columnLabels [i]); cherror } Thing_setName (thee, underlying -> columnLabels [environment]); cherror /* * Compute the off-diagonal elements of the transition matrix in environment 'environment'. */ for (long i = 1; i <= thy numberOfStates; i ++) { /* * How many states are available for the learner to step to (excluding current state)? */ long numberOfAdjacentStates; if (adjacency) { numberOfAdjacentStates = 0; for (long j = 1; j <= thy numberOfStates; j ++) if (i != j && adjacency -> data [i] [j]) numberOfAdjacentStates ++; } else { numberOfAdjacentStates = thy numberOfStates - 1; } /* * Try all possible steps to adjacent states. */ for (long j = 1; j <= thy numberOfStates; j ++) if (i != j) { /* * Local: grammar step only possible to adjacent grammar. */ if (adjacency && adjacency -> data [i] [j] == 0) continue; /* * Compute element (i, j): sum over all possible data. */ for (long m = 1; m <= underlying -> numberOfRows; m ++) { /* * Error-driven: grammar step only triggered by positive evidence. * If the datum does not conflict with the current hypothesis (i), ignore it. */ if (underlying -> data [m] [i]) continue; /* * Greedy: grammar step only taken if new grammar accepts datum. */ if (greedy && underlying -> data [m] [j] == 0) continue; /* * The step is taken if this datum occurs and this grammar (j) is chosen. */ thy data [i] [j] += surface -> data [m] [environment] / numberOfAdjacentStates; } } } /* * Compute the elements on the diagonal, so that the sum of each row is unity. */ for (long i = 1; i <= thy numberOfStates; i ++) { double sum = 0.0; for (long j = 1; j <= thy numberOfStates; j ++) if (j != i) sum += thy data [i] [j]; thy data [i] [i] = sum > 1.0 ? 0.0 : 1.0 - sum; /* Guard against rounding errors. */ } end: iferror { forget (thee); return (structTransition *)Melder_errorp1 (L"Distributions to Transition: not performed."); } return thee; }