Exemplo n.º 1
0
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;
}