Repository navigation
Filter synthesis by the allomorphs used #548
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
fa6e2c5
e36bc03
385337f
bb7211a
f7aea42
57a81e0
c74dfc7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -196,21 +196,34 @@ public IEnumerable<Word> Apply(Word input) | |
| outWord.MorphologicalRuleApplied(_rule, appliedAllomorphIndices); | ||
| appliedAllomorphIndices.Add(i); | ||
|
|
||
| if (_rule.Blockable && outWord.CheckBlocking(out Word newWord)) | ||
| if (input.IsAllomorphApplicable(allo)) | ||
| { | ||
| if (_rule.Blockable && outWord.CheckBlocking(out Word newWord)) | ||
| { | ||
| if (_morpher.TraceManager.IsTracing) | ||
| _morpher.TraceManager.Blocked(_rule, newWord); | ||
| outWord = newWord; | ||
| } | ||
| else | ||
| { | ||
| outWord.Freeze(); | ||
| } | ||
|
|
||
| if (_morpher.TraceManager.IsTracing) | ||
| _morpher.TraceManager.Blocked(_rule, newWord); | ||
| outWord = newWord; | ||
| _morpher.TraceManager.MorphologicalRuleApplied(_rule, i, input, outWord); | ||
| output.Add(outWord); | ||
| } | ||
| else | ||
| else if (_morpher.TraceManager.IsTracing) | ||
| { | ||
| outWord.Freeze(); | ||
| _morpher.TraceManager.MorphologicalRuleNotApplied( | ||
| _rule, | ||
| i, | ||
| input, | ||
| FailureReason.AllomorphNotApplicable, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FieldWorks'
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I plan to add FailureReason.AllmorphNotApplicable to FieldWorks. |
||
| null | ||
| ); | ||
| } | ||
|
|
||
| if (_morpher.TraceManager.IsTracing) | ||
| _morpher.TraceManager.MorphologicalRuleApplied(_rule, i, input, outWord); | ||
| output.Add(outWord); | ||
|
|
||
| // return all word syntheses that match subrules that are constrained by environments, | ||
| // HC violates the disjunctive property of allomorphs here because it cannot check the | ||
| // environmental constraints until it has a surface form, we will enforce the disjunctive | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,6 +18,7 @@ public class Word : Freezable<Word>, IAnnotatedData<ShapeNode>, ICloneable<Word> | |
| private RootAllomorph _rootAllomorph; | ||
| private Shape _shape; | ||
| private readonly List<IMorphologicalRule> _mruleApps; | ||
| private readonly List<Allomorph> _allomorphApps; | ||
|
claude[bot] marked this conversation as resolved.
|
||
| private int _mruleAppIndex = -1; | ||
| private readonly Dictionary<IMorphologicalRule, int> _mrulesUnapplied; | ||
| private readonly Dictionary<IMorphologicalRule, int> _mrulesApplied; | ||
|
|
@@ -42,6 +43,7 @@ public Word(RootAllomorph rootAllomorph, FeatureStruct realizationalFS) | |
| ResetDirty(); | ||
| SetRootAllomorph(rootAllomorph); | ||
| RealizationalFeatureStruct = realizationalFS; | ||
| _allomorphApps = new List<Allomorph>(); | ||
| _mruleApps = new List<IMorphologicalRule>(); | ||
| _mrulesUnapplied = new Dictionary<IMorphologicalRule, int>(); | ||
| _mrulesApplied = new Dictionary<IMorphologicalRule, int>(); | ||
|
|
@@ -61,6 +63,7 @@ public Word(Stratum stratum, Shape shape) | |
| SyntacticFeatureStruct = new FeatureStruct(); | ||
| RealizationalFeatureStruct = new FeatureStruct(); | ||
| _mprFeatures = new MprFeatureSet(); | ||
| _allomorphApps = new List<Allomorph>(); | ||
| _mruleApps = new List<IMorphologicalRule>(); | ||
| _mrulesUnapplied = new Dictionary<IMorphologicalRule, int>(); | ||
| _mrulesApplied = new Dictionary<IMorphologicalRule, int>(); | ||
|
|
@@ -83,6 +86,7 @@ protected Word(Word word) | |
| SyntacticFeatureStruct = word.SyntacticFeatureStruct.Clone(); | ||
| RealizationalFeatureStruct = word.RealizationalFeatureStruct.Clone(); | ||
| _mprFeatures = word.MprFeatures.Clone(); | ||
| _allomorphApps = new List<Allomorph>(word._allomorphApps); | ||
|
claude[bot] marked this conversation as resolved.
|
||
| _mruleApps = new List<IMorphologicalRule>(word._mruleApps); | ||
| _mruleAppIndex = word._mruleAppIndex; | ||
| _mrulesUnapplied = new Dictionary<IMorphologicalRule, int>(word._mrulesUnapplied); | ||
|
|
@@ -247,6 +251,15 @@ internal bool IsMorphologicalRuleApplicable(IMorphologicalRule rule) | |
| return curRule == rule || (curRule == null && rule is CompoundingRule); | ||
| } | ||
|
|
||
| internal bool IsAllomorphApplicable(Allomorph allomorph) | ||
|
claude[bot] marked this conversation as resolved.
|
||
| { | ||
| if (_mruleAppIndex < 0) | ||
| return false; | ||
|
|
||
| Allomorph curAllomorph = _allomorphApps[_mruleAppIndex]; | ||
| return curAllomorph == null || curAllomorph == allomorph; | ||
| } | ||
|
|
||
| internal bool HasRemainingRulesFromStratum(Stratum stratum) | ||
| { | ||
| if (_mruleAppIndex < 0) | ||
|
|
@@ -313,19 +326,21 @@ internal void RemoveMorph(Annotation<ShapeNode> morphAnn) | |
| } | ||
|
|
||
| /// <summary> | ||
| /// Notifies this word that the specified morphological rule was unapplied. Null | ||
| /// Notifies this word that the specified morphological rule and allomorph were unapplied. | ||
| /// A null allomorph means that any allomorph is acceptable. A null morphological rule | ||
| /// indicates that an unknown compounding rule was unapplied. This is used when | ||
| /// generating a compound word, because the compounding rule is usually not known just | ||
| /// the non-head allomorph. | ||
| /// </summary> | ||
| internal void MorphologicalRuleUnapplied(IMorphologicalRule mrule) | ||
| internal void MorphologicalRuleUnapplied(IMorphologicalRule mrule, Allomorph allomorph = null) | ||
|
claude[bot] marked this conversation as resolved.
|
||
| { | ||
| CheckFrozen(); | ||
| if (mrule != null) | ||
| _mrulesUnapplied.UpdateValue(mrule, () => 0, count => count + 1); | ||
| if (!(mrule is RealizationalAffixProcessRule)) | ||
| { | ||
| _mruleApps.Add(mrule); | ||
| _allomorphApps.Add(allomorph); | ||
| _mruleAppIndex++; | ||
| } | ||
| } | ||
|
|
@@ -441,7 +456,7 @@ internal IList<Word> ExpandAlternatives() | |
| // Add new rules to alternative. | ||
| int m_start = Source == null ? 0 : Source._mruleApps.Count(); | ||
| for (int i = m_start; i < _mruleApps.Count(); i++) | ||
| alternative.MorphologicalRuleUnapplied(_mruleApps[i]); | ||
| alternative.MorphologicalRuleUnapplied(_mruleApps[i], _allomorphApps[i]); | ||
| int nh_start = Source == null ? 0 : Source._nonHeadApps.Count(); | ||
| for (int i = nh_start; i < _nonHeadApps.Count(); i++) | ||
| alternative.NonHeadUnapplied(_nonHeadApps[i]); | ||
|
|
@@ -536,6 +551,7 @@ protected override int FreezeImpl() | |
| code = code * 31 + _nonHeadAppIndex.GetHashCode(); | ||
| code = code * 31 + _stratum.GetHashCode(); | ||
| code = code * 31 + (_rootAllomorph == null ? 0 : _rootAllomorph.GetHashCode()); | ||
| code = code * 31 + _allomorphApps.GetSequenceHashCode(); | ||
| code = code * 31 + _mruleApps.GetSequenceHashCode(); | ||
| code = code * 31 + _mruleAppIndex.GetHashCode(); | ||
| code = code * 31 + _isLastAppliedRuleFinal.GetHashCode(); | ||
|
|
@@ -560,6 +576,7 @@ public override bool ValueEquals(Word other) | |
| && _nonHeadAppIndex == other._nonHeadAppIndex | ||
| && _stratum == other._stratum | ||
| && _rootAllomorph == other._rootAllomorph | ||
| && _allomorphApps.SequenceEqual(other._allomorphApps) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I hadn't thought of that, but I'd like to keep it as is. One of my goals is that synthesis not do any search. If the morphemes are underspecified, then synthesis of one Word could be exponential in the number of morphemes it has. I want it to be linear in the number of morphemes, if possible (or polynomial at worst). |
||
| && _mruleApps.SequenceEqual(other._mruleApps) | ||
| && _mruleAppIndex == other._mruleAppIndex | ||
| && _isLastAppliedRuleFinal == other._isLastAppliedRuleFinal | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2031,4 +2031,61 @@ public void NonContiguousRules() | |
| var morpher = new Morpher(TraceManager, Language); | ||
| AssertMorphsEqual(morpher.ParseWord("katibɯd"), "49 PER.ACT"); | ||
| } | ||
|
|
||
| [Test] | ||
| public void IsAllomorphApplicable() | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test builds the analysis
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure that I understand what you want. I'm happy for you to upgrade the test after I merge it if you want. |
||
| { | ||
| FeatureStruct any = FeatureStruct.New().Symbol(HCFeatureSystem.Segment).Value; | ||
| var sSuffix = new AffixProcessRule | ||
| { | ||
| Name = "s_suffix", | ||
| Gloss = "3SG", | ||
| RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("V").Value, | ||
| OutSyntacticFeatureStruct = FeatureStruct | ||
| .New(Language.SyntacticFeatureSystem) | ||
| .Feature(Head) | ||
| .EqualTo(head => head.Feature("pers").EqualTo("3")) | ||
| .Value, | ||
| }; | ||
| var allomorph1 = new AffixProcessAllomorph | ||
| { | ||
| Lhs = { Pattern<Word, ShapeNode>.New("1").Annotation(any).OneOrMore.Value }, | ||
| Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "s") }, | ||
| }; | ||
| var allomorph2 = new AffixProcessAllomorph | ||
| { | ||
| Lhs = { Pattern<Word, ShapeNode>.New("1").Annotation(any).OneOrMore.Value }, | ||
| Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "z") }, | ||
| }; | ||
| sSuffix.Allomorphs.Add(allomorph1); | ||
| sSuffix.Allomorphs.Add(allomorph2); | ||
| Morphophonemic.MorphologicalRules.Add(sSuffix); | ||
| var morpher = new Morpher(TraceManager, Language) { MergeEquivalentAnalyses = true }; | ||
|
|
||
| Shape shape = Morphophonemic.CharacterDefinitionTable.Segment("sag"); | ||
| var input = new Word(Morphophonemic, shape); | ||
| input.MorphologicalRuleUnapplied(sSuffix); | ||
| input.Freeze(); | ||
| Word word = morpher.LexicalLookup(input).First(); | ||
| IEnumerable<Word> output = morpher.SynthesizeWord(word); | ||
| Assert.That(output.Count(), Is.EqualTo(2)); | ||
|
|
||
| shape = Morphophonemic.CharacterDefinitionTable.Segment("sag"); | ||
| input = new Word(Morphophonemic, shape); | ||
| input.MorphologicalRuleUnapplied(sSuffix, allomorph1); | ||
| input.Freeze(); | ||
| word = morpher.LexicalLookup(input).First(); | ||
| output = morpher.SynthesizeWord(word); | ||
| Assert.That(output.Count(), Is.EqualTo(1)); | ||
| Assert.That(output.First().ToString(), Is.EqualTo("sags")); | ||
|
|
||
| shape = Morphophonemic.CharacterDefinitionTable.Segment("sag"); | ||
| input = new Word(Morphophonemic, shape); | ||
| input.MorphologicalRuleUnapplied(sSuffix, allomorph2); | ||
| input.Freeze(); | ||
| word = morpher.LexicalLookup(input).First(); | ||
| output = morpher.SynthesizeWord(word); | ||
| Assert.That(output.Count(), Is.EqualTo(1)); | ||
| Assert.That(output.First().ToString(), Is.EqualTo("sagz")); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.