public static IGate SimplifyMultiplicate(IGate g) { Debug.Assert(g.Type == GateType.AND); var or = new ORGate(); or.AddInput(new TrueGate()); IGate r = or; foreach (var e in g.GetInputs()) { if (e.Type == GateType.OR) { r = Gate.Multiply(r.GetInputs(), e.GetInputs()); } else { r = Gate.Multiply(r.GetInputs(), e); } } r = Gate.Simplify(r); TraceSimplify(g, r, "simplify AND"); return r; }
public static IGate SimplifyMultiplicate(IGate g) { Debug.Assert(g.Type == GateType.AND); var or = new ORGate(); or.AddInput(new TrueGate()); IGate r = or; foreach (var e in g.GetInputs()) { if (e.Type == GateType.OR) { r = Gate.Multiply(r.GetInputs(), e.GetInputs()); } else { r = Gate.Multiply(r.GetInputs(), e); } } r = Gate.Simplify(r); TraceSimplify(g, r, "simplify AND"); return(r); }
/// <summary> /// Multiplies two sums of products /// </summary> /// <param name="list1"></param> /// <param name="list2"></param> /// <returns></returns> public static IGate Multiply(IEnumerable<IGate> list1, IEnumerable<IGate> list2) { var r = new ORGate(); foreach (var a in list1) { foreach (var b in list2) { r.AddInput(ComposeAND(a, b)); } } return r; }
public static IGate ExtractCommonFactors(IGate gate) { var original = gate; if (gate.Type == GateType.OR) { // TraceOptimize("extract common factors from {0} ...", gate); var sop = gate.GetSOP(); // count how many times each factor appears var inmap = new Dictionary<int, IInput>(); var dict = new SortedList<int, int>(); foreach (var p in sop.GetPrimitiveFactors()) { // a gate representing the factors (may be multiple per state variable) var pg = p.ToGate(); foreach (var i in pg.GetInputs().OfType<IInput>()) { var address = i.Address; // TraceOptimize("check factor {0} @ {1:X6}", i, address); if (!inmap.ContainsKey(i.Address)) { inmap.Add(i.Address, i); } if (!dict.ContainsKey(address)) { dict[address] = 1; } else { dict[address]++; } } } var m = dict.Values.Max(); // TraceOptimize("maximum factor count {0}", m); if (m > 1) { // go for it, take the first input with maximum multiplicity, inputs are ordered. var pivotindex = dict.Where(e => e.Value == m).Select(e => e.Key).First(); var pivot = inmap[pivotindex]; var pivotlist = new List<Product>(); var otherlist = new List<Product>(); TraceOptimize("use pivot {0:X6} ...", pivot); // split sop into two groups: factor or not foreach (var p in sop) { if (p.ContainsFactor(pivot)) { p.RemoveInput(pivot); pivotlist.Add(p); } else { otherlist.Add(p); } } IGate and = new ANDGate(); and.AddInput(pivot); IGate inneror = new ORGate(); foreach (var p in pivotlist) { var z = p.ToGate().Simplify(); // Debug.Assert(z.GetInputs().Count() > 1); Trace("adding pivot {0} [{1}]", z, z.GetType().Name); inneror.AddInput(z); } inneror = ExtractCommonFactors(inneror); and.AddInput(inneror); if (otherlist.Any()) { //var rh = ExtractCommonFactors(otherlist); var or = new ORGate(); or.AddInput(and); foreach (var p in otherlist) { var z = p.ToGate(); or.AddInput(z.Simplify()); } gate = or; } else { gate = and; } } } if (gate != original && TraceFlags.ShowOptimize) { Log.TraceGateOp2(original, gate, "optimize AND"); } return gate; }
/// <summary> /// Composes two gates with the logical OR operator. /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns>The resulting gate.</returns> public static IGate ComposeOR(IGate a, IGate b, ComposeOptions options = ComposeOptions.None) { IGate result; DecomposeExchange(ref a, ref b); if (a.Type == GateType.OR && b.Type == GateType.OR) { var r = new ORGate(); r.AddInputRange(a.GetInputs()); r.AddInputRange(b.GetInputs()); result = r; } else if (a.Type == GateType.OR) { var r = new ORGate(); r.AddInputRange(a.GetInputs()); r.AddInput(b); result = r; } else { var r = new ORGate(); r.AddInput(a); r.AddInput(b); result = r; } if (0 == (options & ComposeOptions.NoSimplify)) { result = Simplify(result); } TraceCompose(a, b, result, "OR"); return result; }
/// <summary> /// Looks for common subfactors. /// </summary> /// <param name="gate"></param> private bool SimplifyRule2(ref IGate gate) { var originalgate = gate; var gset = gate.GetSOP(); // try all elementary factors ... foreach (var elementaryfactor in gset.GetPrimitiveFactors().ToArray()) { // Trace("trying factor {0}", elementaryfactor); // collect all products that contain the factor as candidates var candidates = new List<Product>(); foreach (var p in gset) { if (1 == p.ContainsFactor(elementaryfactor)) { candidates.Add(p); } } // need at least two if (candidates.Count < 2) { continue; } TraceSimplify("common factor {0} found in {1} ...", elementaryfactor, candidates.ToSeparatorList()); // construct a new gate consisting of the sum of remaining products var reducedsum = new ORGate(); Gate newgate = reducedsum; foreach (var involvedproduct in candidates) { var reducedproduct = involvedproduct.Clone(); reducedproduct.Remove(elementaryfactor); if (reducedproduct.Factors.Any()) { reducedsum.AddInput(reducedproduct.ToGate()); } else { // candidate equals elementary factor => TRUE newgate = new TrueGate(); break; } } // remove original elements from the set foreach (var x in candidates) { gset.Remove(x); } // simplify the resulting gate recursively var partialsum = newgate.Simplify(); var factor = elementaryfactor.ToGate(); TraceSimplify(" is ({0}) AND {1}", partialsum, factor); if (partialsum.Type == GateType.Fixed) { if (partialsum is TrueGate) { // factor only gate = factor; } else { // simplification yields FALSE gate = partialsum; } } else if (partialsum.Type == GateType.AND) { // multiply with factor gate = Gate.Multiply(factor.GetInputs(), partialsum); } else if (partialsum.Type == GateType.OR) { // multiply with all factors gate = Gate.Multiply(factor.GetInputs(), partialsum.GetInputs()); } else { // multiply with factor gate = Gate.Multiply(factor.GetInputs(), partialsum); } // compose with the remaining terms foreach (var term in gset.Select(e => e.ToGate())) { gate = Gate.ComposeOR(gate, term, ComposeOptions.NoSimplify); } break; } if (gate != originalgate) { Gate.TraceSimplify(originalgate, gate, "simplify OR (2)"); } return gate != originalgate; }
private bool SimplifyRule1(ref IGate gate) { var original = gate; var garg = gate as ORGate; if(null == garg) return false; // handle the rules: // A + !A B = A + B // A + A B = A var gset = garg.GetSOP(); int changes = 0; var gplan = gset.OrderBy(e => e.Inputs.Count()).ToList(); for (int j = 0; j < gplan.Count; ++j) { var glist = gplan[j]; if (glist.IsEmpty) continue; TraceSimplify(" product [{0}] : {1}", glist.Signature, glist.ToGate()); for (int k = j + 1; k < gplan.Count; ++k) { var olist = gplan[k]; switch (olist.ContainsFactor(glist)) { case 1: // contains the sequence => eliminate entry? TraceSimplify(" is contained in {0} ...", olist.ToGate()); olist.Clear(); changes++; break; case 2: // contains negation => remove negations TraceSimplify(" negation is contained in {0} ...", olist.ToGate()); olist.Remove(glist); if(olist.IsEmpty) { // full negation ==> ALL glist.Clear(); gset.Fixed = new TrueGate(); } changes++; break; } } } gset.Purge(); if (gset.Fixed != null) { gate = gset.Fixed; } else { // construct an OR expression containing the ordered factors var or = new ORGate(); foreach (var glist in gset.OrderBy(e => e.Signature, StringComparer.Ordinal)) { or.AddInput(glist.ToGate().Simplify()); } if (or.Inputs.Count() == 0) { gate = new FalseGate(); } else if (or.Inputs.Count() == 1) { gate = or.Inputs.First(); } else { gate = or; } } if (changes > 0) { TraceSimplify(original, gate, "simplify OR (1)"); } return changes > 0; }
private bool SimplifyRule1(ref IGate gate) { var original = gate; var garg = gate as ORGate; if (null == garg) { return(false); } // handle the rules: // A + !A B = A + B // A + A B = A var gset = garg.GetSOP(); int changes = 0; var gplan = gset.OrderBy(e => e.Inputs.Count()).ToList(); for (int j = 0; j < gplan.Count; ++j) { var glist = gplan[j]; if (glist.IsEmpty) { continue; } TraceSimplify(" product [{0}] : {1}", glist.Signature, glist.ToGate()); for (int k = j + 1; k < gplan.Count; ++k) { var olist = gplan[k]; switch (olist.ContainsFactor(glist)) { case 1: // contains the sequence => eliminate entry? TraceSimplify(" is contained in {0} ...", olist.ToGate()); olist.Clear(); changes++; break; case 2: // contains negation => remove negations TraceSimplify(" negation is contained in {0} ...", olist.ToGate()); olist.Remove(glist); if (olist.IsEmpty) { // full negation ==> ALL glist.Clear(); gset.Fixed = new TrueGate(); } changes++; break; } } } gset.Purge(); if (gset.Fixed != null) { gate = gset.Fixed; } else { // construct an OR expression containing the ordered factors var or = new ORGate(); foreach (var glist in gset.OrderBy(e => e.Signature, StringComparer.Ordinal)) { or.AddInput(glist.ToGate().Simplify()); } if (or.Inputs.Count() == 0) { gate = new FalseGate(); } else if (or.Inputs.Count() == 1) { gate = or.Inputs.First(); } else { gate = or; } } if (changes > 0) { TraceSimplify(original, gate, "simplify OR (1)"); } return(changes > 0); }
/// <summary> /// Looks for common subfactors. /// </summary> /// <param name="gate"></param> private bool SimplifyRule2(ref IGate gate) { var originalgate = gate; var gset = gate.GetSOP(); // try all elementary factors ... foreach (var elementaryfactor in gset.GetPrimitiveFactors().ToArray()) { // Trace("trying factor {0}", elementaryfactor); // collect all products that contain the factor as candidates var candidates = new List <Product>(); foreach (var p in gset) { if (1 == p.ContainsFactor(elementaryfactor)) { candidates.Add(p); } } // need at least two if (candidates.Count < 2) { continue; } TraceSimplify("common factor {0} found in {1} ...", elementaryfactor, candidates.ToSeparatorList()); // construct a new gate consisting of the sum of remaining products var reducedsum = new ORGate(); Gate newgate = reducedsum; foreach (var involvedproduct in candidates) { var reducedproduct = involvedproduct.Clone(); reducedproduct.Remove(elementaryfactor); if (reducedproduct.Factors.Any()) { reducedsum.AddInput(reducedproduct.ToGate()); } else { // candidate equals elementary factor => TRUE newgate = new TrueGate(); break; } } // remove original elements from the set foreach (var x in candidates) { gset.Remove(x); } // simplify the resulting gate recursively var partialsum = newgate.Simplify(); var factor = elementaryfactor.ToGate(); TraceSimplify(" is ({0}) AND {1}", partialsum, factor); if (partialsum.Type == GateType.Fixed) { if (partialsum is TrueGate) { // factor only gate = factor; } else { // simplification yields FALSE gate = partialsum; } } else if (partialsum.Type == GateType.AND) { // multiply with factor gate = Gate.Multiply(factor.GetInputs(), partialsum); } else if (partialsum.Type == GateType.OR) { // multiply with all factors gate = Gate.Multiply(factor.GetInputs(), partialsum.GetInputs()); } else { // multiply with factor gate = Gate.Multiply(factor.GetInputs(), partialsum); } // compose with the remaining terms foreach (var term in gset.Select(e => e.ToGate())) { gate = Gate.ComposeOR(gate, term, ComposeOptions.NoSimplify); } break; } if (gate != originalgate) { Gate.TraceSimplify(originalgate, gate, "simplify OR (2)"); } return(gate != originalgate); }