File: System\Data\Common\Utils\Boolean\Visitor.cs
Project: ndp\fx\src\DataEntity\System.Data.Entity.csproj (System.Data.Entity)
//---------------------------------------------------------------------
// <copyright file="Visitor.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// @owner Microsoft
// @backupOwner Microsoft
//---------------------------------------------------------------------
 
using System;
using System.Collections.Generic;
using System.Text;
using System.Globalization;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
 
namespace System.Data.Common.Utils.Boolean
{
    /// <summary>
    /// Abstract visitor class. All Boolean expression nodes know how to
    /// 'accept' a visitor, and delegate to the appropriate visitor method.
    /// For instance, AndExpr invokes Visitor.VisitAnd.
    /// </summary>
    /// <typeparam name="T_Identifier">Type of leaf term identifiers in expression.</typeparam>
    /// <typeparam name="T_Return">Return type for visit methods.</typeparam>
    internal abstract class Visitor<T_Identifier, T_Return>
    {
        internal abstract T_Return VisitTrue(TrueExpr<T_Identifier> expression);
        internal abstract T_Return VisitFalse(FalseExpr<T_Identifier> expression);
        internal abstract T_Return VisitTerm(TermExpr<T_Identifier> expression);
        internal abstract T_Return VisitNot(NotExpr<T_Identifier> expression);
        internal abstract T_Return VisitAnd(AndExpr<T_Identifier> expression);
        internal abstract T_Return VisitOr(OrExpr<T_Identifier> expression);
    }
 
    /// <summary>
    /// Basic visitor which reproduces the given expression tree.
    /// </summary>
    /// <typeparam name="T_Identifier">Type of leaf term identifiers in expression.</typeparam>
    internal abstract class BasicVisitor<T_Identifier> : Visitor<T_Identifier, BoolExpr<T_Identifier>>
    {
        internal override BoolExpr<T_Identifier> VisitFalse(FalseExpr<T_Identifier> expression) { return expression; }
        internal override BoolExpr<T_Identifier> VisitTrue(TrueExpr<T_Identifier> expression) { return expression; }
        internal override BoolExpr<T_Identifier> VisitTerm(TermExpr<T_Identifier> expression) { return expression; }
        internal override BoolExpr<T_Identifier> VisitNot(NotExpr<T_Identifier> expression) 
        { 
            return new NotExpr<T_Identifier>(expression.Child.Accept(this)); 
        }
        internal override BoolExpr<T_Identifier> VisitAnd(AndExpr<T_Identifier> expression) 
        { 
            return new AndExpr<T_Identifier>(AcceptChildren(expression.Children)); 
        }
        internal override BoolExpr<T_Identifier> VisitOr(OrExpr<T_Identifier> expression) 
        {
            return new OrExpr<T_Identifier>(AcceptChildren(expression.Children));
        }
        private IEnumerable<BoolExpr<T_Identifier>> AcceptChildren(IEnumerable<BoolExpr<T_Identifier>> children)
        {
            foreach (BoolExpr<T_Identifier> child in children) { yield return child.Accept(this); }
        }
    }
 
    internal class TermCounter<T_Identifier> : Visitor<T_Identifier, int>
    {
        static readonly TermCounter<T_Identifier> s_instance = new TermCounter<T_Identifier>();
 
        internal static int CountTerms(BoolExpr<T_Identifier> expression)
        {
            Debug.Assert(null != expression);
            return expression.Accept(s_instance);
        }
 
        internal override int VisitTrue(TrueExpr<T_Identifier> expression)
        {
            return 0;
        }
 
        internal override int VisitFalse(FalseExpr<T_Identifier> expression)
        {
            return 0;
        }
 
        internal override int VisitTerm(TermExpr<T_Identifier> expression)
        {
            return 1;
        }
 
        internal override int VisitNot(NotExpr<T_Identifier> expression)
        {
            return expression.Child.Accept(this);
        }
 
        internal override int VisitAnd(AndExpr<T_Identifier> expression)
        {
            return VisitTree(expression);
        }
 
        internal override int VisitOr(OrExpr<T_Identifier> expression)
        {
            return VisitTree(expression);
        }
 
        private int VisitTree(TreeExpr<T_Identifier> expression)
        {
            int sum = 0;
            foreach (var child in expression.Children)
            {
                sum += child.Accept(this);
            }
            return sum;
        }
    }
 
    /// <summary>
    /// A Visitor class that returns all the leaves in a boolean expression
    /// </summary>
    /// <typeparam name="T_Identifier">Type of leaf term identifiers in expression.</typeparam>
    internal class LeafVisitor<T_Identifier> : Visitor<T_Identifier, bool>
    {
        readonly List<TermExpr<T_Identifier>> _terms;
 
        private LeafVisitor()
        {
            _terms = new List<TermExpr<T_Identifier>>();
        }
 
        internal static List<TermExpr<T_Identifier>> GetTerms(BoolExpr<T_Identifier> expression)
        {
            Debug.Assert(null != expression, "expression must be given");
            LeafVisitor<T_Identifier> visitor = new LeafVisitor<T_Identifier>();
            expression.Accept(visitor);
            return visitor._terms;
        }
 
        internal static IEnumerable<T_Identifier> GetLeaves(BoolExpr<T_Identifier> expression) 
        {
            return GetTerms(expression).Select(term => term.Identifier);
        }
 
        internal override bool VisitTrue(TrueExpr<T_Identifier> expression)
        {
            return true;
        }
 
        internal override bool VisitFalse(FalseExpr<T_Identifier> expression)
        {
            return true;
        }
 
        internal override bool VisitTerm(TermExpr<T_Identifier> expression)
        {
            _terms.Add(expression);
            return true;
        }
 
        internal override bool VisitNot(NotExpr<T_Identifier> expression)
        {
            return expression.Child.Accept(this);
        }
 
        internal override bool VisitAnd(AndExpr<T_Identifier> expression)
        {
            return VisitTree(expression);
        }
 
        internal override bool VisitOr(OrExpr<T_Identifier> expression)
        {
            return VisitTree(expression);
        }
 
        private bool VisitTree(TreeExpr<T_Identifier> expression)
        {
            foreach (BoolExpr<T_Identifier> child in expression.Children)
            {
                child.Accept(this);
            }
            return true;
        }            
    }
 
    /// <summary>
    /// Rewrites the terms in a Boolean expression tree.
    /// </summary>
    /// <typeparam name="T_From">Term type for leaf nodes of input</typeparam>
    /// <typeparam name="T_To">Term type for leaf nodes of output</typeparam>
    internal class BooleanExpressionTermRewriter<T_From, T_To> : Visitor<T_From, BoolExpr<T_To>>
    {
        private readonly Func<TermExpr<T_From>, BoolExpr<T_To>> _translator;
 
        /// <summary>
        /// Initialize a new translator
        /// </summary>
        /// <param name="translator">Translator delegate; must not be null</param>
        internal BooleanExpressionTermRewriter(Func<TermExpr<T_From>, BoolExpr<T_To>> translator)
        {
            Debug.Assert(null != translator);
            _translator = translator;
        }
 
        internal override BoolExpr<T_To> VisitFalse(FalseExpr<T_From> expression)
        {
            return FalseExpr<T_To>.Value;
        }
 
        internal override BoolExpr<T_To> VisitTrue(TrueExpr<T_From> expression)
        {
            return TrueExpr<T_To>.Value;
        }
 
        internal override BoolExpr<T_To> VisitNot(NotExpr<T_From> expression)
        {
            return new NotExpr<T_To>(expression.Child.Accept(this));
        }
 
        internal override BoolExpr<T_To> VisitTerm(TermExpr<T_From> expression)
        {
            return _translator(expression);
        }
 
        internal override BoolExpr<T_To> VisitAnd(AndExpr<T_From> expression)
        {
            return new AndExpr<T_To>(VisitChildren(expression));
        }
 
        internal override BoolExpr<T_To> VisitOr(OrExpr<T_From> expression)
        {
            return new OrExpr<T_To>(VisitChildren(expression));
        }
 
        private IEnumerable<BoolExpr<T_To>> VisitChildren(TreeExpr<T_From> expression)
        {
            foreach (BoolExpr<T_From> child in expression.Children)
            {
                yield return child.Accept(this);
            }
        }
    }
 
    /// <summary>
    /// Converts a BoolExpr to a Vertex within a solver.
    /// </summary>
    internal class ToDecisionDiagramConverter<T_Identifier> : Visitor<T_Identifier, Vertex>
    {
        private readonly ConversionContext<T_Identifier> _context;
 
        private ToDecisionDiagramConverter(ConversionContext<T_Identifier> context)
        {
            Debug.Assert(null != context, "must provide a context");
            _context = context;
        }
 
        internal static Vertex TranslateToRobdd(BoolExpr<T_Identifier> expr, ConversionContext<T_Identifier> context)
        {
            Debug.Assert(null != expr, "must provide an expression");
            ToDecisionDiagramConverter<T_Identifier> converter =
                new ToDecisionDiagramConverter<T_Identifier>(context);
            return expr.Accept(converter);
        }
 
        internal override Vertex VisitTrue(TrueExpr<T_Identifier> expression)
        {
            return Vertex.One;
        }
 
        internal override Vertex VisitFalse(FalseExpr<T_Identifier> expression)
        {
            return Vertex.Zero;
        }
 
        internal override Vertex VisitTerm(TermExpr<T_Identifier> expression)
        {
            return _context.TranslateTermToVertex(expression);
        }
 
        internal override Vertex VisitNot(NotExpr<T_Identifier> expression)
        {
            return _context.Solver.Not(expression.Child.Accept(this));
        }
 
        internal override Vertex VisitAnd(AndExpr<T_Identifier> expression)
        {
            return _context.Solver.And(expression.Children.Select(child => child.Accept(this)));
        }
 
        internal override Vertex VisitOr(OrExpr<T_Identifier> expression)
        {
            return _context.Solver.Or(expression.Children.Select(child => child.Accept(this)));
        }
    }
}