コード例 #1
0
        /// <summary>
        /// Метод вычисления одного подвыражения.
        /// Возвращает значение подвыражения - true или false
        /// </summary>
        /// <param name="subexpression">Подвыражение</param>
        /// <param name="variablesStorage">Хранилище переменных</param>
        /// <param name="enableBooster">Флаг, отвечающий за включение ускорения вычислений</param>
        public bool calculateSubexpressionValue(Subexpression subexpression, VariablesStorage variablesStorage, bool enableBooster)
        {
            //If subexpression already has the value, simply return it
            if (subexpression.value.HasValue)
            {
                return(subexpression.value.Value);
            }

            if (subexpression.isLeaf())
            {
                int?   intValueFirst = null, intValueSecond = null;
                string stringValueFirst = null, stringValueSecond = null;

                //Checking first lexeme in subexpression
                if (LexemeTypes.IsIntValue(subexpression.lexemeFirst.lexemeType))
                {
                    intValueFirst = Convert.ToInt32(subexpression.lexemeFirst.lexemeText);
                }
                else if (LexemeTypes.IsFuzzyValue(subexpression.lexemeFirst.lexemeType))
                {
                    stringValueFirst = subexpression.lexemeFirst.lexemeText;
                }
                else if (LexemeTypes.IsIdentifier(subexpression.lexemeFirst.lexemeType))
                {
                    var obj = InitVariablesService.getValueFromVariablesStorage(subexpression.lexemeFirst.lexemeText, variablesStorage);
                    if ((obj == null) || (obj is int?))
                    {
                        intValueFirst = Convert.ToInt32(obj);
                    }
                    else
                    {
                        stringValueFirst = Convert.ToString(obj);
                    }
                }

                //Checking second lexeme in subexpression
                if (LexemeTypes.IsIntValue(subexpression.lexemeSecond.lexemeType))
                {
                    intValueSecond = Convert.ToInt32(subexpression.lexemeSecond.lexemeText);
                }
                else if (LexemeTypes.IsFuzzyValue(subexpression.lexemeSecond.lexemeType))
                {
                    stringValueSecond = subexpression.lexemeSecond.lexemeText;
                }
                else if (LexemeTypes.IsIdentifier(subexpression.lexemeSecond.lexemeType))
                {
                    var obj = InitVariablesService.getValueFromVariablesStorage(subexpression.lexemeSecond.lexemeText, variablesStorage);
                    if ((obj == null) || (obj is int?))
                    {
                        intValueSecond = Convert.ToInt32(obj);
                    }
                    else
                    {
                        stringValueSecond = Convert.ToString(obj);
                    }
                }

                //If subexpression has uninitialized variables, we couldn't evaluate it. Return false in this case
                if ((!intValueFirst.HasValue && stringValueFirst == null) || (!intValueSecond.HasValue && stringValueSecond == null))
                {
                    return(false);
                }

                switch (subexpression.operation)
                {
                //It is not OK but possible to use AND and OR operaions in leaf expression
                case OperationEnum.And:
                    if (intValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return((intValueFirst.Value != 0) && (intValueSecond.Value != 0));
                        }
                        else if (stringValueSecond != null)
                        {
                            return((intValueFirst.Value != 0) && (stringValueSecond != null));
                        }
                    }
                    else if (stringValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return((stringValueFirst != null) && (intValueSecond.Value != 0));
                        }
                        else if (stringValueSecond != null)
                        {
                            return((stringValueFirst != null) && (stringValueSecond != null));
                        }
                    }
                    return(false);

                case OperationEnum.Or:
                    if (intValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return((intValueFirst.Value != 0) || (intValueSecond.Value != 0));
                        }
                        else if (stringValueSecond != null)
                        {
                            return((intValueFirst.Value != 0) || (stringValueSecond != null));
                        }
                    }
                    else if (stringValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return((stringValueFirst != null) || (intValueSecond.Value != 0));
                        }
                        else if (stringValueSecond != null)
                        {
                            return((stringValueFirst != null) || (stringValueSecond != null));
                        }
                    }
                    return(false);

                //Comparison operations are fully OK
                case OperationEnum.Equal:
                    if (intValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(intValueFirst.Value == intValueSecond.Value);
                        }
                        else if (stringValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyEquals(intValueFirst.Value, stringValueSecond));
                        }
                    }
                    else if (stringValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyEquals(intValueSecond.Value, stringValueFirst));
                        }
                        else if (stringValueSecond != null)
                        {
                            return(stringValueFirst == stringValueSecond);
                        }
                    }
                    return(false);

                case OperationEnum.NotEqual:
                    if (intValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(intValueFirst.Value != intValueSecond.Value);
                        }
                        else if (stringValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyNotEquals(intValueFirst.Value, stringValueSecond));
                        }
                    }
                    else if (stringValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyNotEquals(intValueSecond.Value, stringValueFirst));
                        }
                        else if (stringValueSecond != null)
                        {
                            return(stringValueFirst != stringValueSecond);
                        }
                    }
                    return(false);

                case OperationEnum.More:
                    if (intValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(intValueFirst.Value > intValueSecond.Value);
                        }
                        else if (stringValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyMore(intValueFirst.Value, stringValueSecond));
                        }
                    }
                    else if (stringValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyMore(stringValueFirst, intValueSecond.Value));
                        }
                        else if (stringValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyMore(stringValueFirst, stringValueSecond));
                        }
                    }
                    return(false);

                case OperationEnum.MoreOrEqual:
                    if (intValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(intValueFirst.Value >= intValueSecond.Value);
                        }
                        else if (stringValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyMoreOrEquals(intValueFirst.Value, stringValueSecond));
                        }
                    }
                    else if (stringValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyMoreOrEquals(stringValueFirst, intValueSecond.Value));
                        }
                        else if (stringValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyMoreOrEquals(stringValueFirst, stringValueSecond));
                        }
                    }
                    return(false);

                case OperationEnum.Less:
                    if (intValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(intValueFirst.Value < intValueSecond.Value);
                        }
                        else if (stringValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyLess(intValueFirst.Value, stringValueSecond));
                        }
                    }
                    else if (stringValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyLess(stringValueFirst, intValueSecond.Value));
                        }
                        else if (stringValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyLess(stringValueFirst, stringValueSecond));
                        }
                    }
                    return(false);

                case OperationEnum.LessOrEqual:
                    if (intValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(intValueFirst.Value <= intValueSecond.Value);
                        }
                        else if (stringValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyLessOrEquals(intValueFirst.Value, stringValueSecond));
                        }
                    }
                    else if (stringValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyLessOrEquals(stringValueFirst, intValueSecond.Value));
                        }
                        else if (stringValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyLessOrEquals(stringValueFirst, stringValueSecond));
                        }
                    }
                    return(false);

                //Rest operations are not allowed, and in this case false will be returned
                default:
                    return(false);
                }
            }
            else if (subexpression.isMixed())
            {
                if (enableBooster)
                {
                    bool?preBooster = calculationBooster(subexpression);
                    if (preBooster.HasValue)
                    {
                        return(preBooster.Value);
                    }
                }

                //Calculate first subexpression value if it doesn't exists
                if (!subexpression.subexpressionFirst.value.HasValue)
                {
                    subexpression.subexpressionFirst.value = calculateSubexpressionValue(subexpression.subexpressionFirst, variablesStorage, enableBooster);
                }

                if (enableBooster)
                {
                    bool?secondBooster = calculationBooster(subexpression);
                    if (secondBooster.HasValue)
                    {
                        return(secondBooster.Value);
                    }
                }

                int?   intValueSecond    = null;
                string stringValueSecond = null;

                //Checking second lexeme in subexpression
                if (LexemeTypes.IsIntValue(subexpression.lexemeSecond.lexemeType))
                {
                    intValueSecond = Convert.ToInt32(subexpression.lexemeSecond.lexemeText);
                }
                else if (LexemeTypes.IsFuzzyValue(subexpression.lexemeSecond.lexemeType))
                {
                    stringValueSecond = subexpression.lexemeSecond.lexemeText;
                }
                else if (LexemeTypes.IsIdentifier(subexpression.lexemeSecond.lexemeType))
                {
                    var obj = InitVariablesService.getValueFromVariablesStorage(subexpression.lexemeSecond.lexemeText, variablesStorage);
                    if ((obj == null) || (obj is int?))
                    {
                        intValueSecond = Convert.ToInt32(obj);
                    }
                    else
                    {
                        stringValueSecond = Convert.ToString(obj);
                    }
                }

                //If subexpression has uninitialized variables, we couldn't evaluate it. Return false in this case
                if (!intValueSecond.HasValue && stringValueSecond == null)
                {
                    return(false);
                }

                switch (subexpression.operation)
                {
                //AND and OR operaions are fully OK in mixed subexpression
                case OperationEnum.And:
                    if (intValueSecond != null)
                    {
                        return(subexpression.subexpressionFirst.value.Value && (intValueSecond.Value != 0));
                    }
                    else if (stringValueSecond != null)
                    {
                        return(subexpression.subexpressionFirst.value.Value && (stringValueSecond != null));
                    }
                    else
                    {
                        return(false);
                    }

                case OperationEnum.Or:
                    if (intValueSecond != null)
                    {
                        return(subexpression.subexpressionFirst.value.Value || (intValueSecond.Value != 0));
                    }
                    else if (stringValueSecond != null)
                    {
                        return(subexpression.subexpressionFirst.value.Value || (stringValueSecond != null));
                    }
                    else
                    {
                        return(false);
                    }

                //Comparison operations are strange but possible
                case OperationEnum.Equal:
                    if (intValueSecond != null)
                    {
                        return(subexpression.subexpressionFirst.value.Value == (intValueSecond.Value != 0));
                    }
                    else if (stringValueSecond != null)
                    {
                        return(subexpression.subexpressionFirst.value.Value == (stringValueSecond != null));
                    }
                    else
                    {
                        return(false);
                    }

                case OperationEnum.NotEqual:
                    if (intValueSecond != null)
                    {
                        return(subexpression.subexpressionFirst.value.Value != (intValueSecond.Value != 0));
                    }
                    else if (stringValueSecond != null)
                    {
                        return(subexpression.subexpressionFirst.value.Value != (stringValueSecond != null));
                    }
                    else
                    {
                        return(false);
                    }

                //Rest operations are not allowed, and in this case false will be returned
                default:
                    return(false);
                }
            }
            //Ordinary subexpression are here
            else
            {
                if (enableBooster)
                {
                    bool?preBooster = calculationBooster(subexpression);
                    if (preBooster.HasValue)
                    {
                        return(preBooster.Value);
                    }
                }

                //Calculate first subexpression value if it doesn't exists
                if (!subexpression.subexpressionFirst.value.HasValue)
                {
                    subexpression.subexpressionFirst.value = calculateSubexpressionValue(subexpression.subexpressionFirst, variablesStorage, enableBooster);
                }

                if (enableBooster)
                {
                    bool?secondBooster = calculationBooster(subexpression);
                    if (secondBooster.HasValue)
                    {
                        return(secondBooster.Value);
                    }
                }

                //Calculate second subexpression value if it doesn't exists
                if (!subexpression.subexpressionSecond.value.HasValue)
                {
                    subexpression.subexpressionSecond.value = calculateSubexpressionValue(subexpression.subexpressionSecond, variablesStorage, enableBooster);
                }

                switch (subexpression.operation)
                {
                //AND and OR operaions are fully OK in mixed subexpression
                case OperationEnum.And:
                    return(subexpression.subexpressionFirst.value.Value && subexpression.subexpressionSecond.value.Value);

                case OperationEnum.Or:
                    return(subexpression.subexpressionFirst.value.Value || subexpression.subexpressionSecond.value.Value);

                //Comparison operations are strange but possible
                case OperationEnum.Equal:
                    return(subexpression.subexpressionFirst.value.Value == subexpression.subexpressionSecond.value.Value);

                case OperationEnum.NotEqual:
                    return(subexpression.subexpressionFirst.value.Value != subexpression.subexpressionSecond.value.Value);

                //Rest operations are not allowed, and in this case false will be returned
                default:
                    return(false);
                }
            }
        }
コード例 #2
0
ファイル: MainForm.cs プロジェクト: betanets/master-piece
        private void button_process_Click(object sender, EventArgs e)
        {
            var watch = Stopwatch.StartNew();

            loggingService           = new LoggingService(richTextBox_log);
            loggingService.noLogMode = checkBox_measureExecutionTime.Checked;
            clearWorkplace();

            //Init int and fuzzy variables
            VariablesStorage variablesStorage =
                InitVariablesService.initVariables(dataGridView_intVariables.Rows, dataGridView_intVariables.NewRowIndex, loggingService);

            //Select fuzzy variables by their names
            FuzzyVariableSelectionResult selectionResult = fuzzyVariableService.makeSelection(variablesStorage);

            if (!selectionResult.isSuccess)
            {
                loggingService.logFuzzySelectionError(selectionResult);
                return;
            }

            //Copy int and fuzzy variables into holder
            variablesStorage_holder.intVariables.AddRange(variablesStorage.intVariables);
            variablesStorage_holder.fuzzyVariables.AddRange(variablesStorage.fuzzyVariables);

            //Init expressions
            expressionsStorage.AddRange(
                InitExpressionsService.initExpressions(dataGridView_expressions.Rows, dataGridView_expressions.NewRowIndex, loggingService)
                );

            foreach (Expression expression in expressionsStorage)
            {
                //Checking IF expression
                List <Lexeme> ifParserResult = ParserService.parseIfExpression(expression.ifExpressionText);
                loggingService.logIfParser(expression.ifExpressionText, ifParserResult);

                //Checking parser result on fuzzy values existence
                FuzzyVariableSelectionResult ifSelectionResult = fuzzyVariableService.makeSelection(ifParserResult);
                if (!ifSelectionResult.isSuccess)
                {
                    loggingService.logFuzzySelectionError(ifSelectionResult);
                    return;
                }

                //Checking semantic
                LexicalAnalysisResult semanticResult = LexicalAnalysisService.makeSemanticAnalysis(ifParserResult, variablesStorage);
                loggingService.logLexicalAnalysis(semanticResult);

                //Next steps are available only if semantic analysis is correct
                if (!semanticResult.isCorrect)
                {
                    return;
                }

                //Sorting by reverse polish notation
                List <Lexeme> reversePolishNotationLexemeList = ReversePolishNotationService.createNotation(ifParserResult);
                loggingService.logReversePolishNotation(reversePolishNotationLexemeList);

                //Creating subexpressions
                List <Subexpression> currentSubexpressions = subexpressionService.createSubexpressionsList(reversePolishNotationLexemeList, expression.expressionLevel);
                loggingService.logSubexpressions(currentSubexpressions);
                subexpressions.AddRange(currentSubexpressions);

                //Checking THEN expression
                List <Lexeme> thenParserResult = ParserService.parseThenOrElseExpression(expression.thenExpressionText);
                loggingService.logThenOrElseParser(expression.thenExpressionText, thenParserResult, true);


                //Variable assignment
                //We should assign variables now to correctly mark duplicates
                //We have no idea now whether THEN or ELSE expression will be executed
                LexicalAnalysisService.assignVariables(thenParserResult, variablesStorage, expression.expressionLevel);
                loggingService.logAssignedVariables(variablesStorage, true);

                //Select fuzzy variables by their names
                FuzzyVariableSelectionResult thenSelectionResult = fuzzyVariableService.makeSelection(variablesStorage);
                if (!thenSelectionResult.isSuccess)
                {
                    loggingService.logFuzzySelectionError(thenSelectionResult);
                    return;
                }

                //Checking ELSE expression
                List <Lexeme> elseParserResult = ParserService.parseThenOrElseExpression(expression.elseExpressionText);
                loggingService.logThenOrElseParser(expression.elseExpressionText, elseParserResult, false);

                LexicalAnalysisService.assignVariables(elseParserResult, variablesStorage, expression.expressionLevel);
                loggingService.logAssignedVariables(variablesStorage, true);

                //Select fuzzy variables by their names
                FuzzyVariableSelectionResult elseSelectionResult = fuzzyVariableService.makeSelection(variablesStorage);
                if (!elseSelectionResult.isSuccess)
                {
                    loggingService.logFuzzySelectionError(elseSelectionResult);
                    return;
                }
            }

            //Marking duplicates
            DuplicateExpressionService.markDuplicates(subexpressions, variablesStorage);
            loggingService.logDuplicates(subexpressions);

            if (!checkBox_disableBoosters.Checked)
            {
                //Precalculating duplicates
                subexpressionService.calculateDuplicates(subexpressions, variablesStorage, !checkBox_disableBoosters.Checked);
                loggingService.logDuplicatesValues(subexpressions);
            }

            //Restore int variables storage to init state
            variablesStorage.Clear();
            variablesStorage.intVariables.AddRange(variablesStorage_holder.intVariables);
            variablesStorage.fuzzyVariables.AddRange(variablesStorage_holder.fuzzyVariables);

            //Calculating major subexpressions one by one
            //TODO: check level and compare it with local counter to avoid wrong order
            foreach (Subexpression subexpression in subexpressions)
            {
                if (subexpression.major)
                {
                    //Calculate subexpression
                    subexpression.value = subexpressionService.calculateSubexpressionValue(subexpression, variablesStorage, !checkBox_disableBoosters.Checked);

                    //Prepare int variables storage to next iteration
                    List <Lexeme> parserResult;
                    if (subexpression.value.Value)
                    {
                        parserResult = ParserService.parseThenOrElseExpression(expressionsStorage[subexpression.expressionLevel - 1].thenExpressionText);
                    }
                    else
                    {
                        parserResult = ParserService.parseThenOrElseExpression(expressionsStorage[subexpression.expressionLevel - 1].elseExpressionText);
                    }
                    LexicalAnalysisService.assignVariables(parserResult, variablesStorage, subexpression.expressionLevel);

                    //Select fuzzy variables by their names
                    FuzzyVariableSelectionResult sfvSelectionResult = fuzzyVariableService.makeSelection(variablesStorage);
                    if (!sfvSelectionResult.isSuccess)
                    {
                        loggingService.logFuzzySelectionError(sfvSelectionResult);
                        return;
                    }
                }
            }

            loggingService.logString("------========РЕЗУЛЬТАТЫ:========---------\n");
            loggingService.logSubexpressions(subexpressions);

            loggingService.noLogMode = false;
            loggingService.logAssignedVariables(variablesStorage, false);

            watch.Stop();
            if (checkBox_measureExecutionTime.Checked)
            {
                loggingService.logExecutionTime(watch.ElapsedMilliseconds);
            }
        }