File: Simplifier.cs

package info (click to toggle)
mono 6.14.1%2Bds2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,282,732 kB
  • sloc: cs: 11,182,461; xml: 2,850,281; ansic: 699,123; cpp: 122,919; perl: 58,604; javascript: 30,841; asm: 21,845; makefile: 19,602; sh: 10,973; python: 4,772; pascal: 925; sql: 859; sed: 16; php: 1
file content (140 lines) | stat: -rw-r--r-- 5,871 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//---------------------------------------------------------------------
// <copyright file="Simplifier.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.Diagnostics;

namespace System.Data.Common.Utils.Boolean
{
    // Simplifier visitor for Boolean expressions. Performs the following
    // simplifications bottom-up:
    // - Eliminate True and False (A Or False iff. A, A And True iff. A)
    // - Resolve tautology (A Or !A iff. True, True Or A iff. True) and 
    // contradiction (A And !A iff. False, False And A iff. False)
    // - Flatten nested negations (!!A iff. A)
    // - Evaluate bound literals (!True iff. False, etc.)
    // - Flatten unary/empty And/Or expressions
    internal class Simplifier<T_Identifier> : BasicVisitor<T_Identifier>
    {
        internal static readonly Simplifier<T_Identifier> Instance = new Simplifier<T_Identifier>();

        protected Simplifier()
        {
        }

        internal override BoolExpr<T_Identifier> VisitNot(NotExpr<T_Identifier> expression)
        {
            BoolExpr<T_Identifier> child = expression.Child.Accept(this);
            switch (child.ExprType)
            {
                case ExprType.Not:
                    return ((NotExpr<T_Identifier>)child).Child;
                case ExprType.True: return FalseExpr<T_Identifier>.Value;
                case ExprType.False: return TrueExpr<T_Identifier>.Value;
                default: return base.VisitNot(expression);
            }
        }

        internal override BoolExpr<T_Identifier> VisitAnd(AndExpr<T_Identifier> expression)
        {
            return SimplifyTree(expression);
        }

        internal override BoolExpr<T_Identifier> VisitOr(OrExpr<T_Identifier> expression)
        {
            return SimplifyTree(expression);
        }

        private BoolExpr<T_Identifier> SimplifyTree(TreeExpr<T_Identifier> tree)
        {
            bool isAnd = ExprType.And == tree.ExprType;
            Debug.Assert(isAnd || ExprType.Or == tree.ExprType);

            // Get list of simplified children, flattening nested And/Or expressions
            List<BoolExpr<T_Identifier>> simplifiedChildren = new List<BoolExpr<T_Identifier>>(tree.Children.Count);
            foreach (BoolExpr<T_Identifier> child in tree.Children)
            {
                BoolExpr<T_Identifier> simplifiedChild = child.Accept(this);
                // And(And(A, B), C) iff. And(A, B, C)
                // Or(Or(A, B), C) iff. Or(A, B, C)
                if (simplifiedChild.ExprType == tree.ExprType)
                {
                    simplifiedChildren.AddRange(((TreeExpr<T_Identifier>)simplifiedChild).Children);
                }
                else
                {
                    simplifiedChildren.Add(simplifiedChild);
                }
            }

            // Track negated children separately to identify tautologies and contradictions
            Dictionary<BoolExpr<T_Identifier>, bool> negatedChildren = new Dictionary<BoolExpr<T_Identifier>, bool>(tree.Children.Count);
            List<BoolExpr<T_Identifier>> otherChildren = new List<BoolExpr<T_Identifier>>(tree.Children.Count);
            foreach (BoolExpr<T_Identifier> simplifiedChild in simplifiedChildren)
            {
                switch (simplifiedChild.ExprType)
                {
                    case ExprType.Not:
                        negatedChildren[((NotExpr<T_Identifier>)simplifiedChild).Child] = true;
                        break;
                    case ExprType.False:
                        // False And A --> False
                        if (isAnd) { return FalseExpr<T_Identifier>.Value; }
                        // False || A --> A (omit False from child collections)
                        break;
                    case ExprType.True:
                        // True Or A --> True
                        if (!isAnd) { return TrueExpr<T_Identifier>.Value; }
                        // True And A --> A (omit True from child collections)
                        break;
                    default:
                        otherChildren.Add(simplifiedChild);
                        break;
                }
            }
            List<BoolExpr<T_Identifier>> children = new List<BoolExpr<T_Identifier>>();
            foreach (BoolExpr<T_Identifier> child in otherChildren)
            {
                if (negatedChildren.ContainsKey(child))
                {
                    // A && !A --> False, A || !A --> True
                    if (isAnd) { return FalseExpr<T_Identifier>.Value; }
                    else { return TrueExpr<T_Identifier>.Value; }
                }
                children.Add(child);
            }
            foreach (BoolExpr<T_Identifier> child in negatedChildren.Keys)
            {
                children.Add(child.MakeNegated());
            }
            if (0 == children.Count)
            {
                // And() iff. True
                if (isAnd) { return TrueExpr<T_Identifier>.Value; }
                // Or() iff. False
                else { return FalseExpr<T_Identifier>.Value; }
            }
            else if (1 == children.Count)
            {
                // Or(A) iff. A, And(A) iff. A
                return children[0];
            }
            else
            {
                // Construct simplified And/Or expression
                TreeExpr<T_Identifier> result;
                if (isAnd) { result = new AndExpr<T_Identifier>(children); }
                else { result = new OrExpr<T_Identifier>(children); }
                return result;
            }
        }
    }
}