public List<Identity> GetIdentities(List<ExpressionBase> selection)
        {
            var identities = new List<Identity>();

            if (selection.Count == 0)
            {
                return identities;
            }

            ExpressionBase commonParent = GetCommonParent(selection);
            if (commonParent is VariadicOperatorExpression)
            {
                VariadicOperatorExpression variadicParent = commonParent as VariadicOperatorExpression;

                List<ExpressionBase> operandsLeftOfSelection = new List<ExpressionBase>();
                List<ExpressionBase> operandsRightOfSelection = new List<ExpressionBase>();
                List<ExpressionBase> selectedOperands = new List<ExpressionBase>();

                foreach (ExpressionBase operand in variadicParent)
                {
                    if (operand.Selected == false && operand.GetNodesRecursive().Any((n) => n.Selected == true) == false)
                    {
                        if (selectedOperands.Count == 0)
                        {
                            operandsLeftOfSelection.Add(operand);
                        }
                        else
                        {
                            operandsRightOfSelection.Add(operand);
                        }
                    }
                    else
                    {
                        selectedOperands.Add(operand);
                    }
                }

                VariadicOperatorExpression toBeReplaced = new VariadicOperatorExpression(variadicParent.Type, selectedOperands[0].Clone(), selectedOperands[1].Clone());
                List<ExpressionBase> toBeReplacedSelection = new List<ExpressionBase>();
                foreach (ExpressionBase operand in selectedOperands.Skip(2))
                {
                    toBeReplaced.Add(operand.Clone());
                }

                toBeReplacedSelection = toBeReplaced.GetNodesRecursive().Where((n) => n.Selected == true).ToList();
                foreach (ExpressionRule rule in rules)
                {
                    ExpressionBase suggestion = rule(toBeReplaced, toBeReplacedSelection);
                    if (identities.Select((i) => i.Suggestion).Contains(suggestion) == false && suggestion != commonParent)
                    {
                        if (suggestion != null)
                        {
                            ExpressionBase result;
                            if (variadicParent.Count == selectedOperands.Count)
                            {
                                result = suggestion;
                            }
                            else
                            {
                                VariadicOperatorExpression variadicResult = new VariadicOperatorExpression(variadicParent.Type, new NumericExpression(-1), new NumericExpression(-1));
                                variadicResult.Add(operandsLeftOfSelection.Select((o) => o.Clone()).ToList());
                                variadicResult.Add(WrapInDelimiterIfNeccessary(suggestion.Clone(), variadicResult));
                                variadicResult.Add(operandsRightOfSelection.Select((o) => o.Clone()).ToList());
                                variadicResult.RemoveAt(0);
                                variadicResult.RemoveAt(0);
                                result = variadicResult;
                            }
                            identities.Add(new Identity(suggestion, WrapInDelimiterIfNeccessary(result, commonParent.Parent)));
                        }
                    }
                }
            }
            else
            {
                foreach (ExpressionRule rule in rules)
                {
                    ExpressionBase suggestion = WrapInDelimiterIfNeccessary(rule(commonParent, selection), commonParent.Parent);
                    if (identities.Select((i) => i.Suggestion).Contains(suggestion) == false && suggestion != commonParent)
                    {
                        if (suggestion != null)
                        {
                            identities.Add(new Identity(suggestion, suggestion));
                        }
                    }
                }
            }

            return identities;
        }
Esempio n. 2
0
        //a*b+a*c = (b+c)*a
        //a*b-a*c = (b-c)*a
        public static ExpressionBase ProductParenthesis(ExpressionBase expression, List<ExpressionBase> selection)
        {
            //If expression is a sum. e.g. a*b*c - a*b*d
            VariadicOperatorExpression sum = expression as VariadicOperatorExpression;
            if (sum != null && sum.Type == OperatorType.Add)
            {
                List<ExpressionBase> suggestionSum = new List<ExpressionBase>();
                List<ExpressionBase> commonProductOperands = new List<ExpressionBase>();
                //Foreach operand in sum e.g. a*b*c and a*b*d
                foreach (var actualOperand in sum)
                {
                    ExpressionBase operand;
                    bool negative;

                    //If operand is unary minus take its operand and set negative = true. e.g. -a*b*d => operand = a*b*d, negative = true
                    UnaryMinusExpression minus = actualOperand as UnaryMinusExpression;
                    if (minus != null)
                    {
                        operand = minus.Expression;
                        negative = true;
                    }
                    else
                    {
                        operand = actualOperand;
                        negative = false;
                    }
                    List<ExpressionBase> selectedProductOperands = new List<ExpressionBase>() { operand };
                    List<ExpressionBase> nonSelectedProductOperands = new List<ExpressionBase>() { };
                    VariadicOperatorExpression product = operand as VariadicOperatorExpression;
                    //If operand in the sum is a product. e.g. a*b*d
                    if (product != null && product.Type == OperatorType.Multiply)
                    {
                        //Store all selected and nonselected operands in the product.
                        selectedProductOperands = product.Where((o) => (o.Selected == true || o.GetNodesRecursive().Any((n) => n.Selected))).ToList();
                        nonSelectedProductOperands = product.Where((o) => o.Selected == false && o.GetNodesRecursive().Any((n) => n.Selected) == false).ToList();
                    }
                    bool allEqual = true;
                    //Determine if all selected operands of the product are equal and in same order to the commen product operands.
                    if (commonProductOperands.Count == 0 || commonProductOperands.Count == selectedProductOperands.Count)
                    {
                        for (int index = 0; index < commonProductOperands.Count; index++)
                        {
                            if (commonProductOperands[index] != selectedProductOperands[index])
                            {
                                allEqual = false;
                            }
                        }
                    }
                    else
                    {
                        return null;
                    }

                    //If all selected operands in the product are in the common products operands.
                    if (allEqual || commonProductOperands.Count == 0)
                    {
                        commonProductOperands = selectedProductOperands;
                        //If the whole operand of the sum is selected leave 1 or -1 at its placing when factor outside parenthesis.
                        if (nonSelectedProductOperands.Count == 0)
                        {
                            suggestionSum.Add(negative ? ToNumeric(-1) : ToNumeric(1));
                        }
                        else if (nonSelectedProductOperands.Count == 1)
                        {
                            //If one operand of the product is not selected leave it when factorize the rest outside.
                            ExpressionBase clone = nonSelectedProductOperands[0].Clone();
                            suggestionSum.Add(negative ? new UnaryMinusExpression(clone) : clone);
                        }
                        else
                        {
                            //If two or more operands of the product is not selected leave these when factorize the rest outside.
                            VariadicOperatorExpression nonSelectedProduct = new VariadicOperatorExpression(OperatorType.Multiply, nonSelectedProductOperands[0].Clone(), nonSelectedProductOperands[1].Clone());
                            nonSelectedProduct.Add(nonSelectedProductOperands.Skip(2).Select((o) => o.Clone()).ToList());
                            suggestionSum.Add(negative ? (ExpressionBase)new UnaryMinusExpression(nonSelectedProduct) : nonSelectedProduct);
                        }
                    }
                    else
                    {
                        //If two operands in the sum has two different selections return null
                        return null;
                    }
                }
                //Return product where the common product selection is factorized outside a parenthesis. e.g. (c - d)*a*b
                VariadicOperatorExpression sumExpression = new VariadicOperatorExpression(OperatorType.Add, suggestionSum[0], suggestionSum[1]);
                sumExpression.Add(suggestionSum.Skip(2).ToList());
                VariadicOperatorExpression suggestion = new VariadicOperatorExpression(OperatorType.Multiply, sumExpression, new NumericExpression(-1));
                suggestion.Add(commonProductOperands.Select((o) => o.Clone()).ToList());
                suggestion.RemoveAt(1);
                return suggestion;
            }
            return null;
        }