/// <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, TraceManager trace, 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, trace);

					if (trace != null)
						trace.MorphologicalRuleApplied(this, input, ws, m_subrules[i]);

					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 (trace != null && output.Count == 0)
				trace.MorphologicalRuleNotApplied(this, input);

			return output.Count > 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, TraceManager trace, 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;

			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, trace);

					if (trace != null)
						trace.MorphologicalRuleApplied(this, input, ws, sr);

					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;
		}