将二进制字符串转换为数学表达式

我最近一直在试验遗传算法,现在我想用基因组构建数学表达式(简单来说,就是找到一个与特定结果匹配的表达式)。

我的基因组由字节表示的基因组成。一个基因组可能看起来像这样:{12, 127, 82, 35, 95, 223, 85, 4, 213, 228}。 长度是预定义的(虽然它必须落在一定的范围内),形式也是预定义的。 也就是说,任何条目都可以采用任何字节值。

现在的诀窍是将它翻译成数学表达式。确定基本表达式相当容易,例如:选取前 2 个值并将它们视为乘数,选取第 3 个值并将其选为运算符(+、-、*、/、^、mod),选取第 4 个值作为乘数,然后再次选取第 5 个值作为运算符,对前 2 个乘数的第 3 个运算符的结果进行运算。(或者只是将其作为后缀表达式处理)

当您开始允许优先级规则时,复杂性会上升。 现在,例如,索引 2 下的条目表示“(”,那么您肯定会在更远的地方找到一个“)”,但条目 3 除外,但条目 4 不一定。

当然,很多事情都是如此,你不能以运算符结尾,你不能以一个孤立的数字结尾等等。

现在我可以做一个巨大的 switch 语句(例如),接受所有可能的可能性,但这会使代码难以阅读。 我希望有人知道如何处理这个问题的好策略。

提前致谢!

** 编辑 **

根据要求:我试图实现的目标是制作一个可以为一组数字解析函数的应用程序。 至于我在下面的评论中给出的示例:{4, 11, 30},它可能会提出函数 (X ^ 3) + X


回答:

Belisarius 在评论中给出了一个相同主题的链接:运算符和操作数的排列算法

我的代码:

    private static double ResolveExpression(byte[] genes, double valueForX)    {        // folowing: https://stackoverflow.com/questions/3947937/algorithm-for-permutations-of-operators-and-operands/3948113#3948113        Stack<double> operandStack = new Stack<double>();        for (int index = 0; index < genes.Length; index++)        {            int genesLeft = genes.Length - index;            byte gene = genes[index];            bool createOperand;            // only when there are enough possbile operators left, possibly add operands            if (genesLeft > operandStack.Count)            {                // only when there are at least 2 operands on the stack                if (operandStack.Count >= 2)                {                    // randomly determine wether to create an operand by threating everything below 127 as an operand and the rest as an operator (better then / 2 due to 0 values)                    createOperand = gene < byte.MaxValue / 2;                }                else                {                    // else we need an operand for sure since an operator is illigal                    createOperand = true;                }            }            else            {                // false for sure since there are 2 many operands to complete otherwise                createOperand = false;            }            if (createOperand)            {                operandStack.Push(GeneToOperand(gene, valueForX));            }            else            {                double left = operandStack.Pop();                double right = operandStack.Pop();                double result = PerformOperator(gene, left, right);                operandStack.Push(result);            }        }        // should be 1 operand left on the stack which is the ending result        return operandStack.Pop();    }    private static double PerformOperator(byte gene, double left, double right)    {        // There are 5 options currently supported, namely: +, -, *, /, ^ and log (math)        int code = gene % 6;        switch (code)        {            case 0:                return left + right;            case 1:                return left - right;            case 2:                return left * right;            case 3:                return left / right;            case 4:                return Math.Pow(left, right);            case 5:                return Math.Log(left, right);            default:                throw new InvalidOperationException("Impossible state");        }    }    private static double GeneToOperand(byte gene, double valueForX)    {        // We only support numbers 0 - 9 and X        int code = gene % 11; // Get a value between 0 and 10        if (code == 10)        {            // 10 is a placeholder for x            return valueForX;        }        else        {            return code;        }    }    #endregion // Helpers}

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注