Skip to content

Commit

Permalink
Add MergeEquivalentAnalyses
Browse files Browse the repository at this point in the history
  • Loading branch information
jtmaxwell3 committed Jan 20, 2025
1 parent c304a75 commit d088fce
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 3 deletions.
15 changes: 15 additions & 0 deletions src/SIL.Machine.Morphology.HermitCrab/AnalysisStratumRule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ public IEnumerable<Word> Apply(Word input)

_prulesRule.Apply(input);
input.Freeze();
IDictionary<Shape, Word> shapeWord = null;
// Don't merge if tracing because it messes up the tracing.
bool mergeEquivalentAnalyses = _morpher.MergeEquivalentAnalyses && !_morpher.TraceManager.IsTracing;
if (mergeEquivalentAnalyses)
shapeWord = new Dictionary<Shape, Word>(FreezableEqualityComparer<Shape>.Default);

// AnalysisStratumRule.Apply should cover the inverse of SynthesisStratumRule.Apply.
IEnumerable<Word> mruleOutWords = ApplyTemplates(input).Concat(ApplyMorphologicalRules(input));
Expand All @@ -82,6 +87,16 @@ public IEnumerable<Word> Apply(Word input)
_morpher.TraceManager.EndUnapplyStratum(_stratum, input);
foreach (Word mruleOutWord in mruleOutWords)
{
if (mergeEquivalentAnalyses)
{
Shape shape = mruleOutWord.Shape;
if (shapeWord.ContainsKey(shape))
{
shapeWord[shape].Alternatives.Add(mruleOutWord);
continue;
}
shapeWord[shape] = mruleOutWord;
}
output.Add(mruleOutWord);
if (_morpher.TraceManager.IsTracing)
_morpher.TraceManager.EndUnapplyStratum(_stratum, mruleOutWord);
Expand Down
16 changes: 13 additions & 3 deletions src/SIL.Machine.Morphology.HermitCrab/Morpher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public Morpher(ITraceManager traceManager, Language lang)
_synthesisRule = lang.CompileSynthesisRule(this);
MaxStemCount = 2;
MaxUnapplications = 0;
MergeEquivalentAnalyses = true;
LexEntrySelector = entry => true;
RuleSelector = rule => true;

Expand All @@ -78,6 +79,12 @@ public ITraceManager TraceManager
/// </summary>
public int MaxUnapplications { get; set; }

/// <summary>
/// Merge analyses that have equivalent shapes.
/// Merged analyses will be expanded if lexical lookup succeeds.
/// </summary>
public bool MergeEquivalentAnalyses { get; set; }

public Func<LexEntry, bool> LexEntrySelector { get; set; }
public Func<IHCRule, bool> RuleSelector { get; set; }

Expand Down Expand Up @@ -304,10 +311,13 @@ private IEnumerable<Word> Synthesize(string word, ConcurrentQueue<Word> analyses
analyses.TryDequeue(out Word analysisWord);
foreach (Word synthesisWord in LexicalLookup(analysisWord))
{
foreach (Word validWord in _synthesisRule.Apply(synthesisWord).Where(IsWordValid))
foreach (Word alternativeSynthesis in synthesisWord.ExpandAlternatives())
{
if (IsMatch(word, validWord))
matches.Add(validWord);
foreach (Word validWord in _synthesisRule.Apply(alternativeSynthesis).Where(IsWordValid))
{
if (IsMatch(word, validWord))
matches.Add(validWord);
}
}
}
}
Expand Down
49 changes: 49 additions & 0 deletions src/SIL.Machine.Morphology.HermitCrab/Word.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public class Word : Freezable<Word>, IAnnotatedData<ShapeNode>, ICloneable<Word>
private bool _isPartial;
private readonly Dictionary<string, HashSet<int>> _disjunctiveAllomorphIndices;
private int _mruleAppCount = 0;
private readonly Word _cloneOf = null;
private readonly IList<Word> _alternatives = new List<Word>();

public Word(RootAllomorph rootAllomorph, FeatureStruct realizationalFS)
{
Expand Down Expand Up @@ -92,6 +94,7 @@ protected Word(Word word)
kvp => new HashSet<int>(kvp.Value)
);
_mruleAppCount = word._mruleAppCount;
_cloneOf = word;
}

public IEnumerable<Annotation<ShapeNode>> Morphs
Expand Down Expand Up @@ -396,6 +399,52 @@ internal void NonHeadUnapplied(Word nonHead)
_nonHeadAppIndex++;
}

internal Word CloneOf
{
get { return _cloneOf; }
}

internal IList<Word> Alternatives
{
get { return _alternatives; }
}

internal IList<Word> ExpandAlternatives()
{
IList<Word> alternatives = new List<Word>();
IList<Word> originals = _cloneOf?.ExpandAlternatives();
// Update the alternatives of _cloneOf with any changes made since the clone.
if (originals == null || originals.Count < 2)
{
// Special case.
alternatives.Add(this);
}
else
{
foreach (Word original in originals)
{
Word alternative = original.Clone();
alternative._shape = this.Shape;
// Add new rules to alternative.
foreach (IMorphologicalRule rule in MorphologicalRules)
{
if (_cloneOf != null && _cloneOf.MorphologicalRules.Contains(rule))
continue;
alternative.MorphologicalRuleUnapplied(rule);
}
if (RootAllomorph != null)
alternative.RootAllomorph = RootAllomorph;
alternative.Freeze();
alternatives.Add(alternative);
}

}
// Add local alternatives.
foreach (Word alternative in _alternatives)
alternatives.AddRange(alternative.ExpandAlternatives());
return alternatives;
}

public Allomorph GetAllomorph(Annotation<ShapeNode> morph)
{
var alloID = (string)morph.FeatureStruct.GetValue(HCFeatureSystem.Allomorph);
Expand Down

0 comments on commit d088fce

Please sign in to comment.