3

式ツリーの変換に取り組んでいますが、ツリー内の操作の削減/最適化に適用できる既存のライブラリまたは手法があるかどうか疑問に思っています。

たとえば、次のように一連の順次否定操作を折りたたむことができるようにしたいと思います。

arg => !!!!!!!(getValue(arg))
reduces to arg => !getValue(arg)

...または、否定の後に等式演算を続けて、等式でない演算に変換します。

arg => !(getValue(arg) == 3)
reduces to arg => getValue(arg) != 3

...または一般的な論理式にドモルガンの法則を適用します。

arg => !(getValue(arg) < 3 || getValue(arg) >= 5))
reduces to arg => getValue(arg) >= 3 && getValue(arg) < 5

[簡潔にするために、上記の縮小形式でラムダ式を使用しました。]

これらのツールは、式ツリーのすべての可能な評価に適用できるわけではないことを理解していますが、論理演算を厳密に使用する式ツリーのクラスには役立つようです。

これらのタスクを実行する式ツリーエバリュエーターを構築するための既存の参照はありますか?

4

1 に答える 1

1

質問で提起された要件に対処するための再利用可能な.NETFrameworkコンポーネントはないようです。ただし、Andrey Shchekinの ツールリファレンスは、必要なコンポーネントの作成方法に関する優れたリファレンスを提供しました。

これは、順次Not()演算子のキャンセル、Not()演算子のバイナリ式への分散、およびド・モルガンの法則の適用に対処するスニペットです。

public class NotCollapser : ExpressionVisitor
{
    // Incomplete list; others removed for brevity.
    private static readonly IDictionary<ExpressionType, Func<BinaryExpression, BinaryExpression>> NotDistributionMap = 
    {
        { ExpressionType.Equal, e => Expression.MakeBinary(ExpressionType.NotEqual, e.Left, e.Right) },
        { ExpressionType.NotEqual, e => Expression.MakeBinary(ExpressionType.Equal, e.Left, e.Right) },
        { ExpressionType.GreaterThan, e => Expression.MakeBinary(ExpressionType.LessThanOrEqual, e.Left, e.Right) },
        { ExpressionType.AndAlso, e => Expression.MakeBinary(ExpressionType.OrElse, Expression.Not(e.Left), Expression.Not(e.Right)) },
        { ExpressionType.OrElse, e => Expression.MakeBinary(ExpressionType.AndAlso, Expression.Not(e.Left), Expression.Not(e.Right)) }
    };


    protected override Expression VisitUnary(UnaryExpression expression)
    {
        if (expression.NodeType == ExpressionType.Not)
        {
            if (expression.Operand.NodeType == ExpressionType.Not)
            {
                return Visit((expression.Operand as UnaryExpression).Operand);
            }

            if (NotDistributionMap.ContainsKey(expression.Operand.NodeType))
            {
                var distribute = NotDistributionMap[expression.Operand.NodeType];
                return Visit(distribute(expression.Operand as BinaryExpression));
            }
        }

        return base.VisitUnary(expression);
    }
}
于 2012-08-10T02:36:21.473 に答える