【问题标题】:Generate Random Mathematical Functions生成随机数学函数
【发布时间】:2015-12-20 00:05:45
【问题描述】:

这是一个奇怪的问题,可能并不完全适合 Stack Overflow,但我在网上找不到任何关于它的信息,所以在这里......

有没有办法(或最好的办法)来生成随机数学函数?我的意思不是说我想要一个生成随机数的函数(一行 RNG),而是我想动态创建一些函数,该函数使用一些 mutate 将一个或多个真实输入从域映射到单个输出-able 规则。

例如,在最简单的情况下,我可以通过对 x1 和 x2 应用随机运算符来生成 f(x1,x2) -> Y 形式的函数。例如 f 可以是:

   f = x1 + x2
or f = x1 - x2
or f = x1 * x2
etc...

但是,我希望能够包含更复杂的公式,包括三角函数、幂函数、伪随机常数,可能还有一些微积分函数等......显然,我不能只是以完全随机的方式连接不同的块,因为这些函数总是需要始终具有有效的语法。

这不适用于任何与加密相关的东西,因此它不必是完美的,但熵越多越好。如果有一种简单的方法可以跟踪正在执行的操作并对其进行变异,那就太好了。

我不确定是否有人对此有任何见解,或者是否有道理,但还是谢谢你

【问题讨论】:

  • 解决这个问题的方法太多了。答案只会变成一个人们喜欢的稻草民意调查。最好的办法是自己对这个主题进行一些研究,找到两三个,分析它们,确定它们是否适合你,然后尝试一下。如果您对尝试做的事情有具体问题,请联系我们。
  • 这不是一个非常精确的问题。 “生成函数”是什么意思?您的意思是仅将功能显示为文本吗?或者生成执行函数的代码?你知道你想要将你的生成限制为哪些操作(例如,它是否包括超越函数,或者只有 4 个操作 +、-、*、/)?一种方法是编写解析树生成器,然后将解析树转换为表达式。解析树生成器会在树中的每个节点上应用随机性。
  • 在构造此类生成器时需要约束(尤其是在深度方面,否则生成可能永远不会终止),否则您很可能会得到诸如(仅作为示例)之类的术语:gamma(sqrt(gamma(sqrt(gamma(sqrt(sin(x + sqrt((gamma(sqrt(x))))))))))))

标签: function math random


【解决方案1】:

我建议你尝试生成随机表达式树;伪代码(有点受 Scala 启发)可能看起来像这样:

NVars = 2
def generateTree(level) = {
   if (level > 100) { generateVarref() }
   else {
     val choice = randomChoice(4)
     switch (choice) {
       case 0 => generateVarref()
       case 1 => generateConstant()
       case 2 => generateUnary(level + 1)
       case 3 => generateBinary(level + 1)
     }
   }
}
def generateVarref() = {
  val c = randomChoice(NVars)
  VarRef(c)
}
def generateConstant() = {
  Number(randomChoice(100))
}
def generateUnary(level) = {
  val c = randomChoice(6)
  val subexpr = generateTree(level)
  switch (c) {
    case 0 => Negate(subexpr)
    case 1 => Sin(subexpr)
    // etc. More unary functions here
  }
}
def generateBinary(level) = {
  val c = randomChoice(4)
  val sub1 = generateTree(level)
  val sub2 = generateTree(level)
  switch (c) {
    case 0 => Plus(sub1, sub2)
    case 1 => Minus(sub1, sub2)
    case 2 => Times(sub1, sub2)
    case 3 => Divide(sub1, sub2)
  }
}

其中Plus、Varref 等是表达式类型的构造函数,该构造函数实现了一个方法,然后允许您以给定值计算表达式。

【讨论】:

    【解决方案2】:

    假设您的函数有2 变量x1 和x2(如果这个假设过于严格,只需将我的答案调整为n 变量x1,...,xn。)

    [开始]生成随机多项式函数

    这需要

    • 在2 变量中建模多项式(@​​987654328@ 和x2)
    • 对变量的(任何)特定值执行多项式评估
    • 通过采用随机度(达到某个最大值)和随机系数(在给定区间内)生成随机多项式函数

    [Compose]启用函数组合

    这需要

    • 实现函数的组合,如果f、g 和h 是模型中的函数(随机生成或非随机生成),那么f(g,h) 也是模型中的函数。李>

    [丰富]向您的模型添加新的函数族

    在这里,您必须考虑(并实现)其他类型的函数(多项式):有理函数、三角函数、对数函数、指数函数等。对于每种新类型,您都必须对其进行建模,并且,实现一种生成它们的随机实例的方法(就像你为多项式所做的那样。)

    [Generate]结合以上所有创建随机函数

    • 随机选择一些类型
    • 为每种类型生成一个随机实例
    • 将所有类型组合成最终结果。

    [迭代]进入[丰富]并添加新的函数类型

    • 同上。

    【讨论】:

      【解决方案3】:

      感谢大家的帮助。我最终做的是类似于解析树的事情,递归地生成具有 2、1 或 0 个子节点的新节点(用于二元或一元运算符或常量)。您可以通过检查 Node.getDepth() 来限制深度。下面是一些显示此过程的 JavaScript 代码。我不确定它会有多大用处,但它的工作原理与我预想的差不多。

      'use strict';
      
      var print = console.log;
      
      function randint(a, b) {
        return Math.floor((Math.random() * (b + 1 - a)) + a);
      }
      
      function Node(parentNode, numberOfVars,
                     mode, weight, method, numberOfChildren, varIndex, value) {
      
        this.mode = mode ? mode : randint(0, 3);
      
        this.parent = parentNode;
        this.weight = weight ? weight : 1;
      
        if (this.mode == 0) { //constant
          this.value = value ? value : 1;
        } else if (this.mode == 1) { //variable
          this.varIndex = varIndex ? varIndex : randint(0, numberOfVars - 1);
        } else if (this.mode == 2) { //binary
          this.method = method ? method : Node.binary[randint(0, Node.binary.length - 1)];
        } else if (this.mode == 3) { //unary
          this.method = method ? method : Node.unary[randint(0, Node.unary.length - 1)];
        }
      
        if (numberOfChildren) {
          this.children = new Array(numberOfChildren);
        } else {
          this.children = [];
      
          if (this.mode == 2) { //binary
            this.children = [new Node(this, numberOfVars),
                             new Node(this, numberOfVars)
                            ];
          } else if (this.mode == 3) { //unary
            this.children = [new Node(this, numberOfVars)];
          }
        }
      
        //Methods
        this.execute = function(top_level_variables) {
          print("executing " + this.mode);
          var inputs = [];
          this.children.forEach(function(child, index) {
            print("child index " + index);
            inputs.push(child.execute(top_level_variables) * child.weight);
          });
          print("    inputs = " + inputs);
      
          if (this.mode == 0) {
            print("    mode == 0");
            return this.constant();
          }
          if (this.mode == 1) {
            print("    mode == 1");
            return this.variable(top_level_variables);
          }
          if (this.mode == 2) {
            print("    mode == 2");
            return this.method(inputs[0], inputs[1]);
          }
          if (this.mode == 3) {
            print("    mode == 3");
            return this.method(inputs[0]);
          }
        };
        var getIndent = function(indent) {
          var str = "";
          if (indent === 0)
            return str;
      
          for (var i = 0; i < indent; i++) {
            str += " | ";
          }
          return str;
        };
        this.getTree = function(indent) {
          if (this.mode == 0) {
            print(getIndent(indent) + "(" + this.value + ")");
          } else if (this.mode == 1) {
            print(getIndent(indent) + "x[" + this.varIndex + "]");
          } else if (this.mode == 2) {
            print(getIndent(indent) + this.method.name);
            this.children[0].getTree(indent + 1);
            this.children[1].getTree(indent + 1);
          } else if (this.mode == 3) {
            print(getIndent(indent) + this.method.name);
            this.children[0].getTree(indent + 1);
          }
        };
        this.getStr = function() {
          if (this.mode == 0) {
            return this.value;
          } else if (this.mode == 1) {
            return "x[" + this.varIndex + "]";
          } else if (this.mode == 2) {
            return this.method.name + "( " + this.children[0].getStr() + ", " + this.children[1].getStr() + " )";
          } else if (this.mode == 3) {
            return this.method.name + "( " + this.children[0].getStr() + " )";
          }
        };
      }
      
      Node.binary = [
        function add(a, b) {
          return a + b
        },
        function multiply(a, b) {
          return a * b
        },
        function power(a, b) {
          return Math.pow(a, b)
        }
      ];
      Node.unary = [
        function sin(a) {
          return Math.sin(a)
        }
      ];
      Node.prototype.constant = function() {
        return this.value
      };
      Node.prototype.variable = function(variables) {
        return variables[this.varIndex]
      };
      
      //Test
      var a = new Node(null, 2, 2);
      a.getTree(0);
      print(a.getStr())
      print(a.getDepth());
      var b = a.execute([1, 3]);
      print(b);

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-12
        • 1970-01-01
        • 2022-10-07
        • 1970-01-01
        相关资源
        最近更新 更多