/* praat_OT.c */
/* Paul Boersma, May 11, 2002 */

#include "praat.h"

#include "OTGrammar.h"
#include "OTGrammarEditor.h"
#include "OTfile.h"
#include "OTtongueRoot.h"
#include "OTAnyGrammarEditor.h"

/***** HELP *****/

DIRECT (OT_learning_tutorial) Melder_help ("OT learning"); END

DIRECT (OTGrammar_help) Melder_help ("OTGrammar"); END

/***** OTANYGRAMMAR *****/

FORM (Create_tongue_root_method_grammar, "Create tongue-root method grammar", "Create tongue-root method grammar...")
	RADIO ("Constraint set", 1)
		RADIOBUTTON ("Five")
		RADIOBUTTON ("Nine")
	RADIO ("Ranking", 3)
		RADIOBUTTON ("Equal")
		RADIOBUTTON ("Random")
		RADIOBUTTON ("Infant")
		RADIOBUTTON ("Wolof")
	OK
DO
	if (! praat_new (OTGrammar_tongueRoot_create (GET_INTEGER ("Constraint set"),
		GET_INTEGER ("Ranking")), GET_STRING ("Ranking"))) return 0;
END

DIRECT (OTAnyGrammar_edit)
	if (praat.batch) {
		return Melder_error ("Cannot edit from batch.");
	} else {
		WHERE (SELECTED) {
			if (! praat_installEditor (OTAnyGrammarEditor_create (praat.topShell, FULL_NAME,
				OBJECT), IOBJECT)) return 0;
		}
	}
END

FORM (OTAnyGrammar_generateInputs, "OT grammar: generate inputs", 0)
	NATURAL ("Number of strings", "100")
	OK
DO
	WHERE (SELECTED)
		if (! praat_new (OTAnyGrammar_generateInputs (OBJECT, GET_INTEGER ("Number of strings")), "%s_in", NAME)) return 0;
END

DIRECT (OTAnyGrammar_generateOneInput)
	char input [100];
	OTAnyGrammar_generateOneInput (ONLY_OBJECT, input);
	Melder_information ("%s", input);
END

FORM (OTAnyGrammar_inputToOutput, "OTAnyGrammar: Input to output", "OTAnyGrammar: Input to output...")
	SENTENCE ("Input string", "")
	REAL ("Evaluation noise", "2.0")
	OK
DO
	char output [100];
	if (! OTAnyGrammar_inputToOutput (ONLY_OBJECT, GET_STRING ("Input string"), output, GET_REAL ("Evaluation noise"))) return 0;
	Melder_information ("%s", output);
	praat_dataChanged (ONLY_OBJECT);
END

FORM (OTAnyGrammar_inputToOutputs, "OTAnyGrammar: Input to outputs", 0)
	SENTENCE ("Input string", "")
	NATURAL ("Trials", "1000")
	REAL ("Evaluation noise", "2.0")
	OK
DO
	OTAnyGrammar grammar = ONLY_GENERIC (classOTAnyGrammar);
	if (! praat_new (OTAnyGrammar_inputToOutputs (grammar,
		GET_STRING ("Input string"), GET_INTEGER ("Trials"), GET_REAL ("Evaluation noise")), "%s_out", grammar -> name)) return 0;
	praat_dataChanged (ONLY_OBJECT);
END

FORM (OTAnyGrammar_inputsToOutputs, "OTAnyGrammar: Inputs to outputs", "OTAnyGrammar: Inputs to outputs...")
	REAL ("Evaluation noise", "2.0")
	OK
DO
	OTAnyGrammar grammar = ONLY_GENERIC (classOTAnyGrammar);
	if (! praat_new (OTAnyGrammar_inputsToOutputs (grammar,
		ONLY (classStrings), GET_REAL ("Evaluation noise")), "%s_out", grammar -> name)) return 0;
	praat_dataChanged (grammar);
END

FORM (OTAnyGrammar_learn_mgla, "OTAnyGrammar: Learn (GLA)", "OTAnyGrammar: Learn (GLA)...")
	REAL ("Evaluation noise", "2.0")
	OPTIONMENU ("Reranking strategy", 3)
		OPTION ("Demotion only")
		OPTION ("Symmetric highest")
		OPTION ("Symmetric all")
		OPTION ("Weighted uncancelled")
		OPTION ("Weighted all")
	REAL ("Plasticity", "0.1")
	REAL ("Rel. plasticity spreading", "0.1")
	BOOLEAN ("Honour local rankings", 1)
	OK
DO
	OTAnyGrammar grammar = ONLY_GENERIC (classOTAnyGrammar);
	Strings inputs = NULL, outputs = NULL;
	WHERE (SELECTED && CLASS == classStrings) if (! inputs) inputs = OBJECT; else outputs = OBJECT;
	OTAnyGrammar_learn_mgla (grammar, inputs, outputs,
		GET_REAL ("Evaluation noise"), GET_INTEGER ("Reranking strategy") - 1, GET_INTEGER ("Honour local rankings"),
		GET_REAL ("Plasticity"), GET_REAL ("Rel. plasticity spreading"));
	praat_dataChanged (grammar);
	iferror return 0;
END

DIRECT (OTAnyGrammar_learn_ts)
	OTAnyGrammar grammar = ONLY_GENERIC (classOTAnyGrammar);
	Strings inputs = NULL, outputs = NULL;
	WHERE (SELECTED && CLASS == classStrings) if (! inputs) inputs = OBJECT; else outputs = OBJECT;
	OTAnyGrammar_learn_ts (grammar, inputs, outputs);
	praat_dataChanged (grammar);
	iferror return 0;
END

FORM (OTAnyGrammar_learnOne_mgla, "OTAnyGrammar: Learn one (GLA)", "OTAnyGrammar: Learn one (GLA)...")
	LABEL ("", "Underlying form (= adult surface form or adult underlying form):")
	SENTENCE ("Input string", "")
	LABEL ("", "Adult surface form:")
	SENTENCE ("Output string", "")
	REAL ("Evaluation noise", "2.0")
	OPTIONMENU ("Reranking strategy", 3)
		OPTION ("Demotion only")
		OPTION ("Symmetric highest")
		OPTION ("Symmetric all")
		OPTION ("Weighted uncancelled")
		OPTION ("Weighted all")
	REAL ("Plasticity", "0.1")
	REAL ("Rel. plasticity spreading", "0.1")
	BOOLEAN ("Honour local rankings", 1)
	OK
DO
	WHERE (SELECTED) {
		OTAnyGrammar_learnOne_mgla (OBJECT, GET_STRING ("Input string"), GET_STRING ("Output string"),
			GET_REAL ("Evaluation noise"), GET_INTEGER ("Reranking strategy") - 1, GET_INTEGER ("Honour local rankings"),
			GET_REAL ("Plasticity"), GET_REAL ("Rel. plasticity spreading"));
		praat_dataChanged (OBJECT);
		iferror return 0;
	}
END

FORM (OTAnyGrammar_learnOne_ts, "OTAnyGrammar: Learn one (T&S)", "OTAnyGrammar: Learn one (T&S)...")
	LABEL ("", "Adult underlying form:")
	SENTENCE ("Input string", "")
	LABEL ("", "Adult surface form:")
	SENTENCE ("Output string", "")
	OK
DO
	WHERE (SELECTED) {
		OTAnyGrammar_learnOne_ts (OBJECT, GET_STRING ("Input string"), GET_STRING ("Output string"));
		praat_dataChanged (OBJECT);
		iferror return 0;
	}
END

FORM (OTAnyGrammar_sort, "OTAnyGrammar: Sort", "OTAnyGrammar: Sort...")
	REAL ("Evaluation noise", "0.0")
	OK
DO
	WHERE (SELECTED) {
		OTAnyGrammar_sort (OBJECT, GET_REAL ("Evaluation noise"));
		praat_dataChanged (OBJECT);
	}
END

FORM (OTAnyGrammar_to_Tableau, "OTAnyGrammar: To Tableau", 0)
	SENTENCE ("Input", "")
	OK
DO
	char *input = GET_STRING ("Input");
	WHERE (SELECTED)
		if (! praat_new (OTAnyGrammar_to_Tableau (OBJECT, input), input)) return 0;
END

/***** OTANYTABLEAU *****/

DIRECT (OTAnyTableau_draw)
	EVERY_DRAW (OTAnyTableau_draw (OBJECT, GRAPHICS))
END

DIRECT (OTAnyTableau_getWinner)
	OTAnyTableau tableau = ONLY_OBJECT;
	long winner = OTAnyTableau_getWinner (tableau);
	if (winner) Melder_information ("%ld (%s)", winner, tableau -> candidates [winner]);
	else Melder_information ("<undefined>");
END

/***** OTGRAMMAR *****/

FORM (Create_metrics_grammar, "Create metrics grammar", 0)
	RADIO ("Direction", 2)
		RADIOBUTTON ("Parsing")
		RADIOBUTTON ("Production")
	RADIO ("Ranking", 1)
		RADIOBUTTON ("Equal")
		RADIOBUTTON ("Foot form high")
		RADIOBUTTON ("WSP high")
	OK
DO
	if (! praat_new (OTGrammar_create_metrics (GET_INTEGER ("Direction") == 1,
		GET_INTEGER ("Ranking")), GET_STRING ("Ranking"))) return 0;
END

DIRECT (Create_NoCoda_grammar)
	if (! praat_new (OTGrammar_create_NoCoda_grammar (), "NoCoda")) return 0;
END

DIRECT (Create_NPA_grammar)
	if (! praat_new (OTGrammar_create_NPA_grammar (), "assimilation")) return 0;
END

DIRECT (Create_NPA_distribution)
	if (! praat_new (OTGrammar_create_NPA_distribution (), "assimilation")) return 0;
END

FORM (Create_tongue_root_grammar, "Create tongue-root grammar", "Create tongue-root grammar...")
	RADIO ("Constraint set", 1)
		RADIOBUTTON ("Five")
		RADIOBUTTON ("Nine")
	RADIO ("Ranking", 3)
		RADIOBUTTON ("Equal")
		RADIOBUTTON ("Random")
		RADIOBUTTON ("Infant")
		RADIOBUTTON ("Wolof")
	OK
DO
	if (! praat_new (OTGrammar_create_tongueRoot_grammar (GET_INTEGER ("Constraint set"),
		GET_INTEGER ("Ranking")), GET_STRING ("Ranking"))) return 0;
END

FORM (OTGrammar_drawTableau, "Draw tableau", "OT learning")
	SENTENCE ("Input string", "")
	OK
DO
	EVERY_DRAW (OTGrammar_drawTableau (OBJECT, GRAPHICS, GET_STRING ("Input string")))
END

DIRECT (OTGrammar_edit)
	if (praat.batch) {
		return Melder_error ("Cannot edit from batch.");
	} else {
		WHERE (SELECTED) {
			if (! praat_installEditor (OTGrammarEditor_create (praat.topShell, FULL_NAME,
				OBJECT), IOBJECT)) return 0;
		}
	}
END

FORM (OTGrammar_generateInputs, "Generate inputs", "OTGrammar: Generate inputs...")
	NATURAL ("Number of trials", "1000")
	OK
DO
	WHERE (SELECTED) {
		int status = praat_new (OTGrammar_generateInputs (OBJECT, GET_INTEGER ("Number of trials")),
			"%s_in", NAME);
		praat_dataChanged (OBJECT);
		if (! status) return 0;
	}
END

FORM (OTGrammar_getCandidate, "Get candidate", 0)
	NATURAL ("Tableau", "1")
	NATURAL ("Candidate", "1")
	OK
DO
	OTGrammar me = ONLY_OBJECT;
	OTGrammarTableau tableau;
	long itab = GET_INTEGER ("Tableau"), icand = GET_INTEGER ("Candidate");
	REQUIRE (itab <= my numberOfTableaus, "'Tableau' should not exceed number of tableaus.")
	tableau = & my tableaus [itab];
	REQUIRE (icand <= tableau -> numberOfCandidates, "'Candidate' should not exceed number of candidates.")
	Melder_information ("%s", tableau -> candidates [icand]. output);
END

FORM (OTGrammar_getInput, "Get input", 0)
	NATURAL ("Tableau", "1")
	OK
DO
	OTGrammar me = ONLY_OBJECT;
	long itab = GET_INTEGER ("Tableau");
	REQUIRE (itab <= my numberOfTableaus, "'Tableau' should not exceed number of tableaus.")
	Melder_information ("%s", my tableaus [itab]. input);
END

DIRECT (OTGrammar_getInputs)
	WHERE (SELECTED) {
		if (! praat_new (OTGrammar_getInputs (OBJECT), "%s_in", NAME)) return 0;
	}
END

FORM (OTGrammar_getInterpretiveParse, "OTGrammar: Interpretive parse", 0)
	SENTENCE ("Overt form", "")
	OK
DO
	OTGrammar me = ONLY_OBJECT;
	long bestInput, bestOutput;
	OTGrammarCandidate cand = OTGrammar_getInterpretiveParse
		(me, GET_STRING ("Overt form"), & bestInput, & bestOutput);
	if (! cand) return 0;
	Melder_information ("Best input = %ld: %s\nBest output = %ld: %s",
		bestInput, my tableaus [bestInput]. input, bestOutput, cand -> output);
END

FORM (OTGrammar_getNumberOfCandidates, "Get number of candidates", 0)
	NATURAL ("Tableau", "1")
	OK
DO
	OTGrammar me = ONLY_OBJECT;
	long itab = GET_INTEGER ("Tableau");
	REQUIRE (itab <= my numberOfTableaus, "'Tableau' should not exceed number of tableaus.")
	Melder_information ("%ld", my tableaus [itab]. numberOfCandidates);
END

DIRECT (OTGrammar_getNumberOfTableaus)
	OTGrammar me = ONLY_OBJECT;
	Melder_information ("%ld", my numberOfTableaus);
END

FORM (OTGrammar_getWinner, "Get winner", 0)
	NATURAL ("Tableau", "1")
	OK
DO
	long winner = OTGrammar_getWinner (ONLY_OBJECT, GET_INTEGER ("Tableau"));
	Melder_information ("%ld", winner);
END

FORM (OTGrammar_inputToOutput, "OTGrammar: Input to output", "OTGrammar: Input to output...")
	SENTENCE ("Input form", "")
	REAL ("Evaluation noise", "2.0")
	OK
DO
	char output [100];
	if (! OTGrammar_inputToOutput (ONLY_OBJECT, GET_STRING ("Input form"), output, GET_REAL ("Evaluation noise"))) return 0;
	Melder_information ("%s", output);
	praat_dataChanged (ONLY_OBJECT);
END

FORM (OTGrammar_inputToOutputs, "OTGrammar: Input to outputs", "OTGrammar: Input to outputs...")
	NATURAL ("Trials", "1000")
	REAL ("Evaluation noise", "2.0")
	SENTENCE ("Input form", "")
	OK
DO
	OTGrammar ot = ONLY (classOTGrammar);
	if (! praat_new (OTGrammar_inputToOutputs (ot,
		GET_STRING ("Input form"), GET_INTEGER ("Trials"), GET_REAL ("Evaluation noise")), "%s_out", ot -> name)) return 0;
	praat_dataChanged (ot);
END

FORM (OTGrammar_inputsToOutputs, "OTGrammar: Inputs to outputs", "OTGrammar: Inputs to outputs...")
	REAL ("Evaluation noise", "2.0")
	OK
DO
	OTGrammar ot = ONLY (classOTGrammar);
	if (! praat_new (OTGrammar_inputsToOutputs (ot,
		ONLY (classStrings), GET_REAL ("Evaluation noise")), "%s_out", ot -> name)) return 0;
	praat_dataChanged (ot);
END

FORM (OTGrammar_learn, "OTGrammar: Learn", "OTGrammar & 2 Strings: Learn...")
	REAL ("Evaluation noise", "2.0")
	OPTIONMENU ("Reranking strategy", 3)
		OPTION ("Demotion only")
		OPTION ("Symmetric one")
		OPTION ("Symmetric all")
		OPTION ("Weighted uncancelled")
		OPTION ("Weighted all")
		OPTION ("EDCD")
	REAL ("Plasticity", "0.1")
	REAL ("Rel. plasticity spreading", "0.1")
	BOOLEAN ("Honour local rankings", 1)
	NATURAL ("Number of chews", "1")
	OK
DO
	OTGrammar grammar = ONLY (classOTGrammar);
	Strings inputs = NULL, outputs = NULL;
	WHERE (SELECTED && CLASS == classStrings) if (! inputs) inputs = OBJECT; else outputs = OBJECT;
	OTGrammar_learn (grammar, inputs, outputs,
		GET_REAL ("Evaluation noise"), GET_INTEGER ("Reranking strategy") - 1, GET_INTEGER ("Honour local rankings"),
		GET_REAL ("Plasticity"), GET_REAL ("Rel. plasticity spreading"), GET_INTEGER ("Number of chews"));
	praat_dataChanged (grammar);
	iferror return 0;
END

FORM (OTGrammar_learnFromPartialOutputs, "OTGrammar: Learn from partial adult outputs", 0)
	REAL ("Evaluation noise", "2.0")
	OPTIONMENU ("Reranking strategy", 3)
		OPTION ("Demotion only")
		OPTION ("Symmetric one")
		OPTION ("Symmetric all")
		OPTION ("Weighted uncancelled")
		OPTION ("Weighted all")
		OPTION ("EDCD")
	REAL ("Plasticity", "0.1")
	REAL ("Rel. plasticity spreading", "0.1")
	BOOLEAN ("Honour local rankings", 1)
	NATURAL ("Number of chews", "1")
	OK
DO
	OTGrammar grammar = ONLY (classOTGrammar);
	OTGrammar_learnFromPartialOutputs (grammar, ONLY (classStrings),
		GET_REAL ("Evaluation noise"), GET_INTEGER ("Reranking strategy") - 1, GET_INTEGER ("Honour local rankings"),
		GET_REAL ("Plasticity"), GET_REAL ("Rel. plasticity spreading"), GET_INTEGER ("Number of chews"));
	praat_dataChanged (grammar);
	iferror return 0;
END

FORM (OTGrammar_learnOne, "OTGrammar: Learn one", "OTGrammar: Learn one...")
	LABEL ("", "Underlying form (= adult surface form or adult underlying form):")
	SENTENCE ("Input string", "")
	LABEL ("", "Adult surface form:")
	SENTENCE ("Output string", "")
	REAL ("Evaluation noise", "2.0")
	OPTIONMENU ("Reranking strategy", 3)
		OPTION ("Demotion only")
		OPTION ("Symmetric one")
		OPTION ("Symmetric all")
		OPTION ("Weighted uncancelled")
		OPTION ("Weighted all")
		OPTION ("EDCD")
	REAL ("Plasticity", "0.1")
	REAL ("Rel. plasticity spreading", "0.1")
	BOOLEAN ("Honour local rankings", 1)
	OK
DO
	WHERE (SELECTED) {
		OTGrammar_learnOne (OBJECT, GET_STRING ("Input string"), GET_STRING ("Output string"),
			GET_REAL ("Evaluation noise"), GET_INTEGER ("Reranking strategy") - 1, GET_INTEGER ("Honour local rankings"),
			GET_REAL ("Plasticity"), GET_REAL ("Rel. plasticity spreading"), TRUE);
		praat_dataChanged (OBJECT);
		iferror return 0;
	}
END

FORM (OTGrammar_learnOneFromPartialOutput, "OTGrammar: Learn one from partial adult output", 0)
	LABEL ("", "Partial adult surface form (e.g. overt form):")
	SENTENCE ("Partial output", "")
	REAL ("Evaluation noise", "2.0")
	OPTIONMENU ("Reranking strategy", 3)
		OPTION ("Demotion only")
		OPTION ("Symmetric one")
		OPTION ("Symmetric all")
		OPTION ("Weighted uncancelled")
		OPTION ("Weighted all")
		OPTION ("EDCD")
	REAL ("Plasticity", "0.1")
	REAL ("Rel. plasticity spreading", "0.1")
	BOOLEAN ("Honour local rankings", 1)
	OK
DO
	WHERE (SELECTED) {
		OTGrammar_learnOneFromPartialOutput (OBJECT, GET_STRING ("Partial output"),
			GET_REAL ("Evaluation noise"), GET_INTEGER ("Reranking strategy") - 1, GET_INTEGER ("Honour local rankings"),
			GET_REAL ("Plasticity"), GET_REAL ("Rel. plasticity spreading"));
		praat_dataChanged (OBJECT);
		iferror return 0;
	}
END

FORM (OTGrammar_setRanking, "OTGrammar: Set ranking", 0)
	NATURAL ("Constraint", "1")
	REAL ("Ranking", "100.0")
	REAL ("Disharmony", "100.0")
	OK
DO
	WHERE (SELECTED) {
		if (! OTGrammar_setRanking (OBJECT, GET_INTEGER ("Constraint"), GET_REAL ("Ranking"), GET_REAL ("Disharmony"))) return 0;
		praat_dataChanged (OBJECT);
	}
END

FORM (OTGrammar_PairDistribution_getFractionCorrect, "OTGrammar & PairDistribution: Get fraction correct...", 0)
	REAL ("Evaluation noise", "2.0")
	INTEGER ("Replications", "100000")
	OK
DO
	OTGrammar grammar = ONLY (classOTGrammar);
	double result;
	OTGrammar_PairDistribution_getFractionCorrect (grammar, ONLY (classPairDistribution),
		GET_REAL ("Evaluation noise"), GET_INTEGER ("Replications"), & result);
	praat_dataChanged (grammar);
	iferror return 0;
	Melder_informationReal (result, NULL);
END

FORM (OTGrammar_PairDistribution_learn, "OTGrammar & PairDistribution: Learn", "OT learning 6. Shortcut to OT learning")
	REAL ("Evaluation noise", "2.0")
	OPTIONMENU ("Reranking strategy", 3)
		OPTION ("Demotion only")
		OPTION ("Symmetric one")
		OPTION ("Symmetric all")
		OPTION ("Weighted uncancelled")
		OPTION ("Weighted all")
		OPTION ("EDCD")
	REAL ("Initial plasticity", "1.0")
	INTEGER ("Replications per plasticity", "100000")
	REAL ("Plasticity decrement", "0.1")
	INTEGER ("Number of plasticities", "4")
	REAL ("Rel. plasticity spreading", "0.1")
	BOOLEAN ("Honour local rankings", 1)
	NATURAL ("Number of chews", "1")
	OK
DO
	OTGrammar grammar = ONLY (classOTGrammar);
	OTGrammar_PairDistribution_learn (grammar, ONLY (classPairDistribution),
		GET_REAL ("Evaluation noise"), GET_INTEGER ("Reranking strategy") - 1, GET_INTEGER ("Honour local rankings"),
		GET_REAL ("Initial plasticity"), GET_INTEGER ("Replications per plasticity"),
		GET_REAL ("Plasticity decrement"), GET_INTEGER ("Number of plasticities"),
		GET_REAL ("Rel. plasticity spreading"), GET_INTEGER ("Number of chews"));
	praat_dataChanged (grammar);
	iferror return 0;
END

FORM (OTGrammar_to_Distributions, "OTGrammar: Compute output distributions", "OTGrammar: To output Distributions...")
	NATURAL ("Trials per input", "100000")
	REAL ("Evaluation noise", "2.0")
	OK
DO
	WHERE (SELECTED) {
		int status = praat_new (OTGrammar_to_Distribution (OBJECT, GET_INTEGER ("Trials per input"), GET_REAL ("Evaluation noise")), "%s_out", NAME);
		praat_dataChanged (OBJECT);
		if (! status) return 0;
	}
END

FORM (OTGrammar_to_PairDistribution, "OTGrammar: Compute output distributions", 0)
	NATURAL ("Trials per input", "100000")
	REAL ("Evaluation noise", "2.0")
	OK
DO
	WHERE (SELECTED) {
		int status = praat_new (OTGrammar_to_PairDistribution (OBJECT, GET_INTEGER ("Trials per input"), GET_REAL ("Evaluation noise")), "%s_out", NAME);
		praat_dataChanged (OBJECT);
		if (! status) return 0;
	}
END

DIRECT (OTGrammar_measureTypology)
	WHERE (SELECTED) {
		int status = praat_new (OTGrammar_measureTypology (OBJECT), "%s_out", NAME);
		praat_dataChanged (OBJECT);
		if (! status) return 0;
	}
END

/***** buttons *****/

void praat_OTAnyGrammar_init (void *klas);   /* Buttons for the subclasses of OTAnyGrammar. */
void praat_OTAnyGrammar_init (void *klas) {
	praat_addAction1 (klas, 1, "Edit", 0, 0, DO_OTAnyGrammar_edit);
	praat_addAction1 (klas, 0, "Generate inputs...", 0, 0, DO_OTAnyGrammar_generateInputs);
	praat_addAction1 (klas, 1, "Generate one input", 0, 0, DO_OTAnyGrammar_generateOneInput);
	praat_addAction1 (klas, 0, "To tableau...", 0, 0, DO_OTAnyGrammar_to_Tableau);
	praat_addAction1 (klas, 1, "Input to output...", 0, 0, DO_OTAnyGrammar_inputToOutput);
	praat_addAction1 (klas, 1, "Input to outputs...", 0, 0, DO_OTAnyGrammar_inputToOutputs);
praat_addAction1 (klas, 0, "Modify", 0, 0, 0);
	praat_addAction1 (klas, 0, "Sort...", 0, 0, DO_OTAnyGrammar_sort);
	praat_addAction1 (klas, 0, "Learn one (T&S)...", 0, 0, DO_OTAnyGrammar_learnOne_ts);
	praat_addAction1 (klas, 0, "Learn one (GLA)...", 0, 0, DO_OTAnyGrammar_learnOne_mgla);

	praat_addAction2 (klas, 1, classStrings, 1, "Inputs to outputs...", 0, 0, DO_OTAnyGrammar_inputsToOutputs);
	praat_addAction2 (klas, 1, classStrings, 2, "Learn (T&S)", 0, 0, DO_OTAnyGrammar_learn_ts);
	praat_addAction2 (klas, 1, classStrings, 2, "Learn (GLA)...", 0, 0, DO_OTAnyGrammar_learn_mgla);
}

void praat_uvafon_OT_init (void);
void praat_uvafon_OT_init (void) {
	Thing_recognizeClassesByName (classOTGrammar,
		classOTConstraint, classOTAnyGrammar, classOTAnyTableau,
		classOTGrammar_tongueRoot, classOTGrammar_file, NULL);
	Thing_recognizeClassByOtherName (classOTGrammar, "OTCase");

	praat_addMenuCommand ("Objects", "New", "-- new optimality --", 0, 0, 0);
	praat_addMenuCommand ("Objects", "New", "Optimality Theory", 0, 0, 0);
		praat_addMenuCommand ("Objects", "New", "OT learning tutorial", 0, 1, DO_OT_learning_tutorial);
		praat_addMenuCommand ("Objects", "New", "-- tableau grammars --", 0, 1, 0);
		praat_addMenuCommand ("Objects", "New", "Create NoCoda grammar", 0, 1, DO_Create_NoCoda_grammar);
		praat_addMenuCommand ("Objects", "New", "Create place assimilation grammar", 0, 1, DO_Create_NPA_grammar);
		praat_addMenuCommand ("Objects", "New", "Create place assimilation distribution", 0, 1, DO_Create_NPA_distribution);
		praat_addMenuCommand ("Objects", "New", "Create tongue-root grammar...", 0, 1, DO_Create_tongue_root_grammar);
		praat_addMenuCommand ("Objects", "New", "Create metrics grammar...", 0, 1, DO_Create_metrics_grammar);
		praat_addMenuCommand ("Objects", "New", "-- method grammars --", 0, 1, 0);
		praat_addMenuCommand ("Objects", "New", "Create tongue-root method grammar...", 0, 1, DO_Create_tongue_root_method_grammar);

	praat_addAction1 (classOTGrammar, 0, "OTGrammar help", 0, 0, DO_OTGrammar_help);
	praat_addAction1 (classOTGrammar, 0, "Edit", 0, 0, DO_OTGrammar_edit);
	praat_addAction1 (classOTGrammar, 0, "Draw tableau...", 0, 0, DO_OTGrammar_drawTableau);
	praat_addAction1 (classOTGrammar, 0, "Query -          ", 0, 0, 0);
	praat_addAction1 (classOTGrammar, 1, "Get number of tableaus", 0, 1, DO_OTGrammar_getNumberOfTableaus);
	praat_addAction1 (classOTGrammar, 1, "Get input...", 0, 1, DO_OTGrammar_getInput);
	praat_addAction1 (classOTGrammar, 1, "Get number of candidates...", 0, 1, DO_OTGrammar_getNumberOfCandidates);
	praat_addAction1 (classOTGrammar, 1, "Get candidate...", 0, 1, DO_OTGrammar_getCandidate);
	praat_addAction1 (classOTGrammar, 1, "-- evaluate --", 0, 1, 0);
	praat_addAction1 (classOTGrammar, 1, "Get winner...", 0, 1, DO_OTGrammar_getWinner);
	praat_addAction1 (classOTGrammar, 1, "Get interpretive parse...", 0, 1, DO_OTGrammar_getInterpretiveParse);
	praat_addAction1 (classOTGrammar, 0, "Generate inputs...", 0, 0, DO_OTGrammar_generateInputs);
	praat_addAction1 (classOTGrammar, 0, "Get inputs", 0, 0, DO_OTGrammar_getInputs);
	praat_addAction1 (classOTGrammar, 1, "Input to output...", 0, 0, DO_OTGrammar_inputToOutput);
	praat_addAction1 (classOTGrammar, 1, "Input to outputs...", 0, 0, DO_OTGrammar_inputToOutputs);
	praat_addAction1 (classOTGrammar, 0, "To output Distributions...", 0, 0, DO_OTGrammar_to_Distributions);
	praat_addAction1 (classOTGrammar, 0, "To PairDistribution...", 0, 0, DO_OTGrammar_to_PairDistribution);
	praat_addAction1 (classOTGrammar, 0, "Measure typology", 0, 0, DO_OTGrammar_measureTypology);
	praat_addAction1 (classOTGrammar, 0, "Modify", 0, 0, 0);
	praat_addAction1 (classOTGrammar, 0, "Set ranking...", 0, 0, DO_OTGrammar_setRanking);
	praat_addAction1 (classOTGrammar, 0, "Learn one...", 0, 0, DO_OTGrammar_learnOne);
	praat_addAction1 (classOTGrammar, 0, "Learn one from partial output...", 0, 0, DO_OTGrammar_learnOneFromPartialOutput);

	praat_OTAnyGrammar_init (classOTGrammar_file);
	praat_OTAnyGrammar_init (classOTGrammar_tongueRoot);

	praat_addAction1 (classOTAnyTableau, 1, "Get winner", 0, 0, DO_OTAnyTableau_getWinner);
	praat_addAction1 (classOTAnyTableau, 0, "Draw", 0, 0, DO_OTAnyTableau_draw);

	praat_addAction2 (classOTGrammar, 1, classPairDistribution, 1, "Learn...", 0, 0, DO_OTGrammar_PairDistribution_learn);
	praat_addAction2 (classOTGrammar, 1, classPairDistribution, 1, "Get fraction correct...", 0, 0, DO_OTGrammar_PairDistribution_getFractionCorrect);
	praat_addAction2 (classOTGrammar, 1, classStrings, 1, "Inputs to outputs...", 0, 0, DO_OTGrammar_inputsToOutputs);
	praat_addAction2 (classOTGrammar, 1, classStrings, 1, "Learn from partial outputs...", 0, 0, DO_OTGrammar_learnFromPartialOutputs);
	praat_addAction2 (classOTGrammar, 1, classStrings, 2, "Learn...", 0, 0, DO_OTGrammar_learn);
}

/* End of file praat_OT.c */
