public OpExpression(BooleanOperation op, BooleanExpression left, BooleanExpression right)
 {
     Op = op;
     Left = left;
     Right = right;
 }
 public OpExpression(BooleanOperation op, BooleanVariable left, BooleanVariable right)
 {
     Op = op;
     Left = new VarExpression(left);
     Right = new VarExpression(right);
 }
 public bool Equals(BooleanExpression obj)
 {
     return ToString() == obj.ToString();
 }
        public IEnumerable<BooleanExpression> CombineWith(BooleanExpression anotherExpression,
			BooleanOperation[] ops)
        {
            foreach(var op in ops) {
                yield return new OpExpression(op, Clone(), anotherExpression.Clone());
                yield return new OpExpression(op, anotherExpression.Clone(), Clone());
            }
        }
        public static BooleanExpression FindMininalExpressionForBinary(BooleanExpression targetBinary, BooleanFunction f,
			List<BooleanExpression> availableExpressions)
        {
            var queue = new ImprovisedPriorityQueue<BooleanExpression>(20);
            var knownTruthTables = new HashSet<byte>();
            var knownExpressions = new HashSet<BooleanExpression>();

            foreach(var expression in availableExpressions) {
                queue.TryEnqueue(expression, 1);
            }

            while(queue.Count != 0) {
                var curExperession = queue.Dequeue();

                byte truthTable = curExperession.Eval();

                if(knownTruthTables.Contains(truthTable)) {
                    continue;
                }

                if((curExperession.Eval() & 0xAA) == (targetBinary.Eval() & 0xAA)) {
                    return curExperession;
                }

                knownExpressions.Add(curExperession);
                knownTruthTables.Add(truthTable);

                foreach(var anotherExpression in knownExpressions) {
                    foreach(var thirdExpression in knownExpressions) {
                        foreach(var neighbourExpression in CombineTertiary(f, curExperession, anotherExpression, thirdExpression)) {
                            queue.TryEnqueue(neighbourExpression, neighbourExpression.CountOps());
                        }
                    }
                }
            }

            throw new CouldntFindExpressionException();
        }
        public static IEnumerable<TertiaryOpExpression> CombineTertiary(BooleanFunction f,
			BooleanExpression firstExpression, BooleanExpression anotherExpression, BooleanExpression thirdExpression)
        {
            yield return new TertiaryOpExpression(f, firstExpression.Clone(), anotherExpression.Clone(),
                thirdExpression.Clone());
            yield return new TertiaryOpExpression(f, firstExpression.Clone(), thirdExpression.Clone(),
                anotherExpression.Clone());
            yield return new TertiaryOpExpression(f, anotherExpression.Clone(), firstExpression.Clone(),
                thirdExpression.Clone());
            yield return new TertiaryOpExpression(f, thirdExpression.Clone(), firstExpression.Clone(),
                anotherExpression.Clone());
            yield return new TertiaryOpExpression(f, anotherExpression.Clone(), thirdExpression.Clone(),
                firstExpression.Clone());
            yield return new TertiaryOpExpression(f, thirdExpression.Clone(), anotherExpression.Clone(),
                firstExpression.Clone());
        }
 public TertiaryOpExpression(BooleanFunction f, BooleanExpression first, BooleanExpression second, BooleanExpression third)
 {
     F = f;
     First = first;
     Second = second;
     Third = third;
 }