internal override bool AddImpl(FeatureValue other, VariableBindings varBindings, IDictionary <FeatureStruct, ISet <FeatureStruct> > visited) { FeatureStruct otherFS; if (Dereference(other, out otherFS)) { ISet <FeatureStruct> visitedOthers = visited.GetValue(this, () => new HashSet <FeatureStruct>()); if (!visitedOthers.Contains(otherFS)) { visitedOthers.Add(otherFS); foreach (KeyValuePair <Feature, FeatureValue> featVal in otherFS._definite) { FeatureValue otherValue = Dereference(featVal.Value); FeatureValue thisValue; if (_definite.TryGetValue(featVal.Key, out thisValue)) { thisValue = Dereference(thisValue); } else { if (otherValue is FeatureStruct) { thisValue = new FeatureStruct(); } else if (otherValue is StringFeatureValue) { thisValue = new StringFeatureValue(); } else { thisValue = new SymbolicFeatureValue((SymbolicFeature)featVal.Key); } _definite[featVal.Key] = thisValue; } if (!thisValue.AddImpl(otherValue, varBindings, visited)) { _definite.Remove(featVal.Key); } } } } return(_definite.Count > 0); }
private void TestBinaryOperation <TResult>(IEqualityComparer <TResult> comparer, Func <FeatureStruct, FeatureStruct, TResult> resultsSelector, Func <FeatureStruct, FeatureStruct, VariableBindings, TResult> varResultsSelector, params Func <FeatureSystem, TResult>[] expectedSelectors) { // simple var featSys = new FeatureSystem { new SymbolicFeature("a", new FeatureSymbol("a1"), new FeatureSymbol("a2"), new FeatureSymbol("a3")), new SymbolicFeature("b", new FeatureSymbol("b1"), new FeatureSymbol("b2"), new FeatureSymbol("b3")), new SymbolicFeature("c", new FeatureSymbol("c1"), new FeatureSymbol("c2"), new FeatureSymbol("c3")) }; featSys.Freeze(); FeatureStruct fs1 = FeatureStruct.NewMutable(featSys).Symbol("a1").Symbol("b1").Value; FeatureStruct fs2 = FeatureStruct.NewMutable(featSys).Symbol("a2").Symbol("c2").Value; Assert.That(resultsSelector(fs1, fs2), Is.EqualTo(expectedSelectors[0](featSys)).Using(comparer)); fs1 = FeatureStruct.NewMutable(featSys).Symbol("a1", "a2").Symbol("b1").Symbol("c2").Value; fs2 = FeatureStruct.NewMutable(featSys).Symbol("a2").Symbol("c2").Value; Assert.That(resultsSelector(fs1, fs2), Is.EqualTo(expectedSelectors[1](featSys)).Using(comparer)); // complex featSys = new FeatureSystem { new ComplexFeature("cx1"), new SymbolicFeature("a", new FeatureSymbol("a1"), new FeatureSymbol("a2"), new FeatureSymbol("a3")), new ComplexFeature("cx2"), new SymbolicFeature("b", new FeatureSymbol("b1"), new FeatureSymbol("b2"), new FeatureSymbol("b3")), new ComplexFeature("cx3"), new SymbolicFeature("c", new FeatureSymbol("c1"), new FeatureSymbol("c2"), new FeatureSymbol("c3")), new ComplexFeature("cx4"), new SymbolicFeature("d", new FeatureSymbol("d1"), new FeatureSymbol("d2"), new FeatureSymbol("d3")) }; featSys.Freeze(); fs1 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(cx1 => cx1.Symbol("a1")) .Feature("cx2").EqualTo(cx2 => cx2.Symbol("b1")) .Feature("cx4").EqualTo(cx4 => cx4.Symbol("d1")).Value; fs2 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(cx1 => cx1.Symbol("a2")) .Feature("cx3").EqualTo(cx2 => cx2.Symbol("c2")) .Feature("cx4").EqualTo(cx4 => cx4.Symbol("d2", "d3")).Value; Assert.That(resultsSelector(fs1, fs2), Is.EqualTo(expectedSelectors[2](featSys)).Using(comparer)); fs1 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(cx1 => cx1.Symbol("a1", "a2")) .Feature("cx2").EqualTo(cx2 => cx2.Symbol("b1")) .Feature("cx4").EqualTo(cx4 => cx4.Symbol("d1")).Value; fs2 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(cx1 => cx1.Symbol("a2")) .Feature("cx3").EqualTo(cx2 => cx2.Symbol("c2")) .Feature("cx4").EqualTo(cx4 => cx4.Symbol("d1", "d2")).Value; Assert.That(resultsSelector(fs1, fs2), Is.EqualTo(expectedSelectors[3](featSys)).Using(comparer)); // re-entrant featSys = new FeatureSystem { new ComplexFeature("cx1"), new SymbolicFeature("a", new FeatureSymbol("a1"), new FeatureSymbol("a2"), new FeatureSymbol("a3"), new FeatureSymbol("a4")), new ComplexFeature("cx2") }; featSys.Freeze(); fs1 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(1, cx1 => cx1.Symbol("a1")) .Feature("cx2").ReferringTo(1).Value; fs2 = FeatureStruct.NewMutable(featSys).Feature("cx2").EqualTo(cx2 => cx2.Symbol("a2")).Value; Assert.That(resultsSelector(fs1, fs2), Is.EqualTo(expectedSelectors[4](featSys)).Using(comparer)); fs1 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(cx1 => cx1.Symbol("a1", "a2")).Value; fs2 = FeatureStruct.NewMutable(featSys).Feature("cx2").EqualTo(1, cx2 => cx2.Symbol("a1", "a3")) .Feature("cx1").ReferringTo(1).Value; Assert.That(resultsSelector(fs1, fs2), Is.EqualTo(expectedSelectors[5](featSys)).Using(comparer)); fs1 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(cx1 => cx1.Symbol("a1", "a2")).Value; fs2 = FeatureStruct.NewMutable(featSys).Feature("cx2").EqualTo(cx2 => cx2.Symbol(1, "a1", "a3")) .Feature("cx1").EqualTo(cx1 => cx1.Feature("a").ReferringTo(1)).Value; Assert.That(resultsSelector(fs1, fs2), Is.EqualTo(expectedSelectors[6](featSys)).Using(comparer)); fs1 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(1, cx1 => cx1.Symbol("a1")) .Feature("cx2").ReferringTo(1).Value; fs2 = FeatureStruct.NewMutable(featSys).Feature("cx2").EqualTo(1, cx2 => cx2.Symbol("a1", "a2")) .Feature("cx1").ReferringTo(1).Value; Assert.That(resultsSelector(fs1, fs2), Is.EqualTo(expectedSelectors[7](featSys)).Using(comparer)); fs1 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(1, cx1 => cx1.Symbol("a1", "a2")) .Feature("cx2").ReferringTo(1).Value; fs2 = FeatureStruct.NewMutable(featSys).Feature("cx2").EqualTo(1, cx2 => cx2.Symbol("a2", "a3", "a4")) .Feature("cx1").ReferringTo(1).Value; Assert.That(resultsSelector(fs1, fs2), Is.EqualTo(expectedSelectors[8](featSys)).Using(comparer)); fs1 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(cx1 => cx1.Symbol(1, "a1", "a2")) .Feature("cx2").EqualTo(cx2 => cx2.Feature("a").ReferringTo(1)).Value; fs2 = FeatureStruct.NewMutable(featSys).Feature("cx2").EqualTo(cx2 => cx2.Symbol(1, "a2", "a3", "a4")) .Feature("cx1").EqualTo(cx1 => cx1.Feature("a").ReferringTo(1)).Value; Assert.That(resultsSelector(fs1, fs2), Is.EqualTo(expectedSelectors[9](featSys)).Using(comparer)); fs1 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(cx1 => cx1.Symbol("a1", "a2")).Value; fs2 = FeatureStruct.NewMutable(featSys).Feature("cx2").EqualTo(1, cx2 => cx2.Symbol("a3")) .Feature("cx1").ReferringTo(1).Value; Assert.That(resultsSelector(fs1, fs2), Is.EqualTo(expectedSelectors[10](featSys)).Using(comparer)); fs1 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(1, cx1 => cx1.Symbol("a1")) .Feature("cx2").ReferringTo(1).Value; fs2 = FeatureStruct.NewMutable(featSys).Feature("cx2").EqualTo(1, cx2 => cx2.Symbol("a2", "a3", "a4")) .Feature("cx1").ReferringTo(1).Value; Assert.That(resultsSelector(fs1, fs2), Is.EqualTo(expectedSelectors[11](featSys)).Using(comparer)); // cyclic featSys = new FeatureSystem { new ComplexFeature("cx1"), new SymbolicFeature("a", new FeatureSymbol("a1"), new FeatureSymbol("a2"), new FeatureSymbol("a3")), new SymbolicFeature("b", new FeatureSymbol("b1"), new FeatureSymbol("b2"), new FeatureSymbol("b3")), new SymbolicFeature("c", new FeatureSymbol("c1"), new FeatureSymbol("c2"), new FeatureSymbol("c3")), new ComplexFeature("cx2") }; featSys.Freeze(); fs1 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(cx1 => cx1 .Symbol("a1").Symbol("b1")).Value; fs2 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(1, cx1 => cx1 .Symbol("a2").Feature("cx2").ReferringTo(1)).Value; Assert.That(resultsSelector(fs1, fs2), Is.EqualTo(expectedSelectors[12](featSys)).Using(comparer)); fs1 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(1, cx1 => cx1 .Symbol("a1", "a2").Feature("cx2").ReferringTo(1)).Value; fs2 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(cx1 => cx1 .Symbol("a2").Symbol("b2")).Value; Assert.That(resultsSelector(fs1, fs2), Is.EqualTo(expectedSelectors[13](featSys)).Using(comparer)); fs1 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(cx1 => cx1 .Symbol("a1", "a2").Symbol("b1").Feature("cx2").EqualTo(cx2 => cx2.Symbol("c1"))).Value; fs2 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(1, cx1 => cx1 .Symbol("a2").Feature("cx2").ReferringTo(1)).Value; Assert.That(resultsSelector(fs1, fs2), Is.EqualTo(expectedSelectors[14](featSys)).Using(comparer)); fs1 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(cx1 => cx1 .Symbol("a1").Symbol("b1").Feature("cx2").EqualTo(cx2 => cx2.Symbol("c1", "c2"))).Value; fs2 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(1, cx1 => cx1 .Symbol("a2").Symbol("c2").Feature("cx2").ReferringTo(1)).Value; Assert.That(resultsSelector(fs1, fs2), Is.EqualTo(expectedSelectors[15](featSys)).Using(comparer)); fs1 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(1, cx1 => cx1 .Symbol("a1").Symbol("b1").Symbol("c1").Feature("cx2").ReferringTo(1)).Value; fs2 = FeatureStruct.NewMutable(featSys).Feature("cx1").EqualTo(1, cx1 => cx1 .Symbol("a2").Symbol("c2").Feature("cx2").ReferringTo(1)).Value; Assert.That(resultsSelector(fs1, fs2), Is.EqualTo(expectedSelectors[16](featSys)).Using(comparer)); // variable featSys = new FeatureSystem { new SymbolicFeature("a", new FeatureSymbol("a+", "+"), new FeatureSymbol("a-", "-")), new SymbolicFeature("b", new FeatureSymbol("b+", "+"), new FeatureSymbol("b-", "-")) }; featSys.Freeze(); fs1 = FeatureStruct.NewMutable(featSys) .Feature("a").EqualToVariable("var1") .Symbol("b-").Value; fs2 = FeatureStruct.NewMutable(featSys) .Feature("a").Not.EqualToVariable("var1") .Symbol("b-").Value; Assert.That(resultsSelector(fs1, fs2), Is.EqualTo(expectedSelectors[17](featSys)).Using(comparer)); fs1 = FeatureStruct.NewMutable(featSys) .Feature("a").EqualToVariable("var1") .Symbol("b-").Value; fs2 = FeatureStruct.NewMutable(featSys) .Symbol("a+") .Symbol("b-").Value; Assert.That(resultsSelector(fs1, fs2), Is.EqualTo(expectedSelectors[18](featSys)).Using(comparer)); fs1 = FeatureStruct.NewMutable(featSys) .Symbol("a+") .Symbol("b-").Value; fs2 = FeatureStruct.NewMutable(featSys) .Feature("a").Not.EqualToVariable("var1") .Symbol("b-").Value; Assert.That(resultsSelector(fs1, fs2), Is.EqualTo(expectedSelectors[19](featSys)).Using(comparer)); fs1 = FeatureStruct.NewMutable(featSys) .Symbol("a+") .Symbol("b-").Value; fs2 = FeatureStruct.NewMutable(featSys) .Feature("a").Not.EqualToVariable("var1") .Symbol("b-").Value; var varBindings = new VariableBindings(); varBindings["var1"] = new SymbolicFeatureValue(featSys.GetSymbol("a-")); Assert.That(varResultsSelector(fs1, fs2, varBindings), Is.EqualTo(expectedSelectors[20](featSys)).Using(comparer)); fs1 = FeatureStruct.NewMutable(featSys) .Symbol("a+") .Symbol("b-").Value; fs2 = FeatureStruct.NewMutable(featSys) .Feature("a").Not.EqualToVariable("var1") .Symbol("b-").Value; varBindings = new VariableBindings(); varBindings["var1"] = new SymbolicFeatureValue(featSys.GetSymbol("a+")); Assert.That(varResultsSelector(fs1, fs2, varBindings), Is.EqualTo(expectedSelectors[21](featSys)).Using(comparer)); }