/// <summary>
        /// Unifies this set of feature values with the specified set of feature values. If the specified
        /// set of feature values does not contain a feature specified in this set of feature values, then the
        /// default value will be used for that feature.
        /// </summary>
        /// <param name="fv">The feature values.</param>
        /// <param name="output">The unification.</param>
        /// <returns><c>true</c> if the feature values could be unified, otherwise <c>false</c>.</returns>
        public bool UnifyDefaults(FeatureValues fv, out FeatureValues output)
        {
            output = fv.Clone();
            foreach (KeyValuePair <Feature, ValueInstance> kvp in m_values)
            {
                ValueInstance value;
                if (fv.m_values.TryGetValue(kvp.Key, out value))
                {
                    ValueInstance vi = null;
                    if (kvp.Value != null && !kvp.Value.UnifyDefaults(value, out vi))
                    {
                        output = null;
                        return(false);
                    }
                    output.m_values[kvp.Key] = vi;
                }
                else if (kvp.Key.DefaultValue != null)
                {
                    ValueInstance vi = null;
                    if (kvp.Value != null && !kvp.Value.UnifyDefaults(kvp.Key.DefaultValue, out vi))
                    {
                        output = null;
                        return(false);
                    }
                    output.m_values[kvp.Key] = vi;
                }
                else
                {
                    output.m_values[kvp.Key] = kvp.Value;
                }
            }

            return(true);
        }
        /// <summary>
        /// Gets the difference between this subset and the specified superset. If this set is
        /// not a subset of the specified superset, it will return <c>false</c>.
        /// </summary>
        /// <param name="superset">The superset feature values.</param>
        /// <param name="remainder">The remainder.</param>
        /// <returns><c>true</c> if this is a subset, otherwise <c>false</c>.</returns>
        public bool GetSupersetRemainder(FeatureValues superset, out FeatureValues remainder)
        {
            FeatureValues result = superset.Clone();

            foreach (KeyValuePair <Feature, ValueInstance> kvp in m_values)
            {
                ValueInstance value;
                if (kvp.Value != null && (!result.m_values.TryGetValue(kvp.Key, out value) || !value.Equals(kvp.Value)))
                {
                    remainder = null;
                    return(false);
                }

                result.m_values.Remove(kvp.Key);
            }

            remainder = result;
            return(true);
        }
Exemple #3
0
        /// <summary>
        /// Applies the rule to the specified word analysis.
        /// </summary>
        /// <param name="input">The input word synthesis.</param>
        /// <param name="output">The output word syntheses.</param>
        /// <returns>
        ///     <c>true</c> if the rule was successfully applied, otherwise <c>false</c>
        /// </returns>
        public override bool Apply(WordSynthesis input, out ICollection <WordSynthesis> output)
        {
            output = null;

            // these should probably be moved to IsApplicable, but we will leave it here for
            // now so we don't have to call it again to set the features for the output word
            // synthesis record

            // check head features
            FeatureValues headHeadFeatures;

            if (!m_headRequiredHeadFeatures.UnifyDefaults(input.HeadFeatures, out headHeadFeatures))
            {
                return(false);
            }

            FeatureValues nonHeadHeadFeatures;

            if (!m_nonHeadRequiredHeadFeatures.UnifyDefaults(input.NonHead.HeadFeatures, out nonHeadHeadFeatures))
            {
                return(false);
            }

            // check foot features
            FeatureValues headFootFeatures;

            if (!m_headRequiredFootFeatures.UnifyDefaults(input.FootFeatures, out headFootFeatures))
            {
                return(false);
            }

            FeatureValues nonHeadFootFeatures;

            if (!m_nonHeadRequiredFootFeatures.UnifyDefaults(input.NonHead.FootFeatures, out nonHeadFootFeatures))
            {
                return(false);
            }

            MorphologicalRuleSynthesisTrace trace = null;

            if (TraceSynthesis)
            {
                // create morphological rule synthesis trace record
                trace = new MorphologicalRuleSynthesisTrace(this, input.Clone());
                input.CurrentTrace.AddChild(trace);
            }

            output = new List <WordSynthesis>();
            foreach (Subrule sr in m_subrules)
            {
                WordSynthesis ws;
                if (sr.Apply(input, out ws))
                {
                    if (m_outPOS != null)
                    {
                        ws.POS = m_outPOS;
                    }

                    if (m_outHeadFeatures != null)
                    {
                        ws.HeadFeatures = m_outHeadFeatures.Clone();
                    }

                    ws.HeadFeatures.Add(headHeadFeatures);

                    if (m_outFootFeatures != null)
                    {
                        ws.FootFeatures = m_outFootFeatures.Clone();
                    }

                    ws.FootFeatures.Add(headFootFeatures);

                    if (m_obligHeadFeatures != null)
                    {
                        foreach (Feature feature in m_obligHeadFeatures)
                        {
                            ws.AddObligatoryHeadFeature(feature);
                        }
                    }

                    ws.MorphologicalRuleApplied(this);

                    ws = CheckBlocking(ws);

                    if (trace != null)
                    {
                        // set current trace record to the morphological rule trace record for each
                        // output analysis
                        ws.CurrentTrace = trace;
                        // add output to morphological rule trace record
                        trace.RuleAllomorph = sr;
                        trace.Output        = ws.Clone();
                    }

                    output.Add(ws);
                    // 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
                    // property of allomorphs at that time
                    if (sr.RequiredEnvironments == null && sr.ExcludedEnvironments == null)
                    {
                        break;
                    }
                }
            }

            return(output.Count > 0);
        }
Exemple #4
0
        /// <summary>
        /// Applies the rule to the specified word synthesis.
        /// </summary>
        /// <param name="input">The input word synthesis.</param>
        /// <param name="output">The output word syntheses.</param>
        /// <returns>
        ///     <c>true</c> if the rule was successfully applied, otherwise <c>false</c>
        /// </returns>
        public override bool Apply(WordSynthesis input, out ICollection <WordSynthesis> output)
        {
            output = null;

            // these should probably be moved to IsApplicable, but we will leave it here for
            // now so we don't have to call it again to set the features for the output word
            // synthesis record

            // check head features
            FeatureValues headFeatures;

            if (!m_requiredHeadFeatures.UnifyDefaults(input.HeadFeatures, out headFeatures))
            {
                return(false);
            }

            // check foot features
            FeatureValues footFeatures;

            if (!m_requiredFootFeatures.UnifyDefaults(input.FootFeatures, out footFeatures))
            {
                return(false);
            }

            output = new List <WordSynthesis>();
            for (int i = 0; i < m_subrules.Count; i++)
            {
                WordSynthesis ws;
                if (m_subrules[i].Apply(input, out ws))
                {
                    if (m_outPOS != null)
                    {
                        ws.POS = m_outPOS;
                    }

                    if (m_outHeadFeatures != null)
                    {
                        ws.HeadFeatures = m_outHeadFeatures.Clone();
                    }

                    ws.HeadFeatures.Add(headFeatures);

                    if (m_outFootFeatures != null)
                    {
                        ws.FootFeatures = m_outFootFeatures.Clone();
                    }

                    ws.FootFeatures.Add(footFeatures);

                    if (m_obligHeadFeatures != null)
                    {
                        foreach (Feature feature in m_obligHeadFeatures)
                        {
                            ws.AddObligatoryHeadFeature(feature);
                        }
                    }

                    ws.MorphologicalRuleApplied(this);

                    ws = CheckBlocking(ws);

                    if (TraceSynthesis)
                    {
                        MorphologicalRuleSynthesisTrace trace = new MorphologicalRuleSynthesisTrace(this, input.Clone());
                        // add output to morphological rule trace record
                        trace.RuleAllomorph = m_subrules[i];
                        trace.Output        = ws.Clone();
                        ws.CurrentTrace.AddChild(trace);
                        // set current trace record to the morphological rule trace record for each
                        // output analysis
                        ws.CurrentTrace = trace;
                    }

                    output.Add(ws);
                    // 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
                    // property of allomorphs at that time

                    // HC also checks for free fluctuation, if the next subrule has the same constraints, we
                    // do not treat them as disjunctive
                    if ((i != m_subrules.Count - 1 && !m_subrules[i].ConstraintsEqual(m_subrules[i + 1])) &&
                        m_subrules[i].RequiredEnvironments == null && m_subrules[i].ExcludedEnvironments == null)
                    {
                        break;
                    }
                }
            }

            if (TraceSynthesis && output.Count == 0)
            {
                input.CurrentTrace.AddChild(new MorphologicalRuleSynthesisTrace(this, input.Clone()));
            }

            return(output.Count > 0);
        }
Exemple #5
0
		/// <summary>
		/// Gets the difference between this subset and the specified superset. If this set is
		/// not a subset of the specified superset, it will return <c>false</c>.
		/// </summary>
		/// <param name="superset">The superset feature values.</param>
		/// <param name="remainder">The remainder.</param>
		/// <returns><c>true</c> if this is a subset, otherwise <c>false</c>.</returns>
		public bool GetSupersetRemainder(FeatureValues superset, out FeatureValues remainder)
		{
			FeatureValues result = superset.Clone();
			foreach (KeyValuePair<Feature, ValueInstance> kvp in m_values)
			{
				ValueInstance value;
				if (kvp.Value != null && (!result.m_values.TryGetValue(kvp.Key, out value) || !value.Equals(kvp.Value)))
				{
					remainder = null;
					return false;
				}

				result.m_values.Remove(kvp.Key);
			}

			remainder = result;
			return true;
		}
Exemple #6
0
		/// <summary>
		/// Unifies this set of feature values with the specified set of feature values. If the specified
		/// set of feature values does not contain a feature specified in this set of feature values, then the
		/// default value will be used for that feature.
		/// </summary>
		/// <param name="fv">The feature values.</param>
		/// <param name="output">The unification.</param>
		/// <returns><c>true</c> if the feature values could be unified, otherwise <c>false</c>.</returns>
		public bool UnifyDefaults(FeatureValues fv, out FeatureValues output)
		{
			output = fv.Clone();
			foreach (KeyValuePair<Feature, ValueInstance> kvp in m_values)
			{
				ValueInstance value;
				if (fv.m_values.TryGetValue(kvp.Key, out value))
				{
					ValueInstance vi = null;
					if (kvp.Value != null && !kvp.Value.UnifyDefaults(value, out vi))
					{
						output = null;
						return false;
					}
					output.m_values[kvp.Key] = vi;
				}
				else if (kvp.Key.DefaultValue != null)
				{
					ValueInstance vi = null;
					if (kvp.Value != null && !kvp.Value.UnifyDefaults(kvp.Key.DefaultValue, out vi))
					{
						output = null;
						return false;
					}
					output.m_values[kvp.Key] = vi;
				}
				else
				{
					output.m_values[kvp.Key] = kvp.Value;
				}
			}

			return true;
		}