生成随机数学函数

时间:2015-09-22 20:46:03

标签: function math random

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

有没有办法(或什么是最好的方法)生成随机数学函数?通过这个我并不意味着我想要一个生成随机数的函数(行RNG),而是我想动态创建一些函数,该函数使用域将一个或多个实际输入映射到单个输出一些可变异的规则。

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

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

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

这不是任何加密相关的东西,所以它不一定是完美的,但熵越多越好。如果有一种简单的方法可以跟踪正在进行的操作并对其进行变异,那也很棒。

我不确定是否有人对此有任何见解,或者它是否有意义,但无论如何谢谢你

3 个答案:

答案 0 :(得分:2)

我建议您尝试生成随机表达式树;伪代码(有点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)
  }
}

其中PlusVarref等是表达式类型的构造函数,它实现了一个方法,然后允许您在给定值下计算表达式。

答案 1 :(得分:2)

假设您的函数包含2变量x1x2(如果此假设过于严格,只需调整我对n变量的答案{{1 },...,x1。)

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

这需要

  • xn变量(2x1)中建模多项式
  • 在(任何)变量的特定值上实现多项式的评估
  • 通过取随机度(达到某个最大值)和随机系数(在给定间隔内)生成随机多项式函数

[撰写] 启用功能合成

这需要

  • 实现函数的组合,以便如果x2fg是模型中的函数(随机生成或不生成),那么h也是模型中的一个功能。

[丰富] 在模型中添加新功能系列

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

[生成] 创建结合以上所有内容的随机函数

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

[迭代] 转到[丰富]并添加新类型的功能

  • 同上。

答案 2 :(得分:0)

感谢大家的帮助。我最终做的是沿着解析树的行,递归地生成具有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);
&#13;
&#13;
&#13;