//TODO: Create a version with just a set of components that we can share with post-optimizations private static void OptimizeAwayFalse(IDictionary<Fact, IComponent> components, Dictionary<Fact, IComponent> negations, PropNet pn, IComponent trueComponent, IComponent falseComponent) { Debug.Assert((components != null && negations != null) || pn != null); Debug.Assert((components == null && negations == null) || pn == null); foreach (IComponent output in falseComponent.Outputs.ToList()) { if (IsEssentialProposition(output) || output is ITransition) { //Since this is the false constant, there are a few "essential" types we don't actually want to keep around. if (!IsLegalOrGoalProposition(output)) continue; } var prop = output as IProposition; if (prop != null) { //Move its outputs to be outputs of false foreach (IComponent child in prop.Outputs) { //Disconnect child.RemoveInput(prop); //output.removeOutput(child); //do at end //Reconnect; will get children before returning, if nonessential falseComponent.AddOutput(child); child.AddInput(falseComponent); } prop.RemoveAllOutputs(); if (!IsEssentialProposition(prop)) { //Remove the proposition entirely falseComponent.RemoveOutput(prop); output.RemoveInput(falseComponent); //Update its location to the trueComponent in our map if (components != null) { components[prop.Name] = falseComponent; negations[prop.Name] = trueComponent; } else pn.RemoveComponent(prop); } } else { var and = output as IAnd; if (and != null) { //Attach children of and to falseComponent foreach (IComponent child in and.Outputs) { child.AddInput(falseComponent); falseComponent.AddOutput(child); child.RemoveInput(and); } //Disconnect and completely and.RemoveAllOutputs(); foreach (IComponent parent in and.Inputs) parent.RemoveOutput(and); and.RemoveAllInputs(); if (pn != null) pn.RemoveComponent(and); } else { var or = output as IOr; if (or != null) { //Remove as input from or or.RemoveInput(falseComponent); falseComponent.RemoveOutput(or); //If or has only one input, remove it if (or.Inputs.Count == 1) { IComponent input = or.GetSingleInput(); or.RemoveInput(input); input.RemoveOutput(or); foreach (IComponent output1 in or.Outputs) { //Disconnect from and output1.RemoveInput(or); //or.removeOutput(out); //do at end //Connect directly to the new input output1.AddInput(input); input.AddOutput(output1); } or.RemoveAllOutputs(); if (pn != null) { pn.RemoveComponent(or); } } else if (!or.Inputs.Any()) { if (pn != null) { pn.RemoveComponent(or); } } } else { var not = output as INot; if (not != null) { //Disconnect from falseComponent not.RemoveInput(falseComponent); falseComponent.RemoveOutput(not); //Connect all children of the not to trueComponent foreach (IComponent child in not.Outputs) { //Disconnect child.RemoveInput(not); //not.removeOutput(child); //Do at end //Connect to trueComponent child.AddInput(trueComponent); trueComponent.AddOutput(child); } not.RemoveAllOutputs(); if (pn != null) pn.RemoveComponent(not); } else if (output is ITransition) { //??? throw new Exception("Fix optimizeAwayFalse's case for Transitions"); } } } } } }
private static void OptimizeAwayTrue(IDictionary<Fact, IComponent> components, IDictionary<Fact, IComponent> negations, PropNet pn, IComponent trueComponent, IComponent falseComponent) { Debug.Assert((components != null && negations != null) || pn != null); foreach (IComponent output in trueComponent.Outputs.ToList()) { if (IsEssentialProposition(output) || output is ITransition) continue; var prop = output as IProposition; if (prop != null) { //Move its outputs to be outputs of true foreach (IComponent child in prop.Outputs) { //Disconnect child.RemoveInput(prop); //output.removeOutput(child); //do at end //Reconnect; will get children before returning, if nonessential trueComponent.AddOutput(child); child.AddInput(trueComponent); } prop.RemoveAllOutputs(); if (!IsEssentialProposition(prop)) { //Remove the proposition entirely trueComponent.RemoveOutput(prop); output.RemoveInput(trueComponent); //Update its location to the trueComponent in our map if (components != null) { components[prop.Name] = trueComponent; Debug.Assert(negations != null, "negations != null"); negations[prop.Name] = falseComponent; } else pn.RemoveComponent(prop); } } else { var or = output as IOr; if (or != null) { //Attach children of or to trueComponent foreach (IComponent child in or.Outputs) { child.AddInput(trueComponent); trueComponent.AddOutput(child); child.RemoveInput(or); } //Disconnect or completely or.RemoveAllOutputs(); foreach (IComponent parent in or.Inputs) parent.RemoveOutput(or); or.RemoveAllInputs(); if (pn != null) pn.RemoveComponent(or); } else { var and = output as IAnd; if (and != null) { //Remove as input from and and.RemoveInput(trueComponent); trueComponent.RemoveOutput(and); //If and has only one input, remove it if (and.Inputs.Count == 1) { IComponent input = and.GetSingleInput(); and.RemoveInput(input); input.RemoveOutput(and); foreach (IComponent output1 in and.Outputs) { //Disconnect from and output1.RemoveInput(and); //and.removeOutput(out); //do at end //Connect directly to the new input output1.AddInput(input); input.AddOutput(output1); } and.RemoveAllOutputs(); if (pn != null) pn.RemoveComponent(and); } else if (and.Inputs.Any()) if (pn != null) pn.RemoveComponent(and); } else { var not = output as INot; if (not != null) { //Disconnect from trueComponent not.RemoveInput(trueComponent); trueComponent.RemoveOutput(not); //Connect all children of the not to falseComponent foreach (IComponent child in not.Outputs) { //Disconnect child.RemoveInput(not); //not.removeOutput(child); //Do at end //Connect to falseComponent child.AddInput(falseComponent); falseComponent.AddOutput(child); } not.RemoveAllOutputs(); if (pn != null) pn.RemoveComponent(not); } } } } } }
/// <summary> /// Adds inputs and outputs to <tt>source</tt> and <tt>target</tt> such /// that <tt>source</tt> becomes an input to <tt>target</tt>. /// </summary> /// <param name="source">A component.</param> /// <param name="target">A second component.</param> private static void Link(IComponent source, IComponent target) { source.AddOutput(target); target.AddInput(source); }