2015-09-22 4 views
0

Это своего рода странный вопрос, и может быть не совсем подходит для переполнения стека, но я не мог найти ничего об этом в Интернете, поэтому здесь ...Генерация случайных математических функций

Есть (или как лучше всего) генерировать случайные математические функции? Под этим я не имею в виду, что мне нужна функция, которая генерирует случайное число (строка RNG), но я хочу динамически создать некоторую функцию, которая отображает один или несколько реальных входов из домена в один вывод с использованием некоторого мутанта .

Например, в простейшем случае я мог бы просто сгенерировать функцию вида f(x1,x2) -> Y, применяя случайный оператор к x1 и x2. Например е могут быть:

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

Однако, я хотел бы иметь возможность включать более сложные формулы, включая тригонометрию, функцию питания, псевдослучайные константы, возможно, некоторые функции математического анализа, и т.д. ... Очевидно, что я не могу просто сцепить разные куски совершенно случайным образом, так как эти функции всегда должны иметь действительный синтаксис.

Это не что-то связанное с криптосвязью, поэтому оно не должно быть совершенным, но чем больше энтропия, тем лучше. Было бы также здорово, если бы был простой способ отслеживать, какие операции предварительно формируются и мутировать их.

Я не уверен, что если у кого есть какие-либо идеи по этому поводу, или, если это даже имело смысл, но все равно спасибо

+0

Есть слишком много способов решить эту проблему. Ответы просто превратились бы в соломенный опрос, который понравился одному человеку.Лучше всего сделать некоторые исследования по теме самостоятельно, найти два или три, проанализировать их, определить, работают ли они на вас или нет, и вывести их из себя. Приходите к нам, когда у вас есть конкретный вопрос о том, что вы пытались сделать. –

+0

Это не очень точно сформулированный вопрос. Что вы подразумеваете под «сгенерированием функции»? Вы хотите просто показать функцию как текст? Или сгенерировать код, который выполняет эту функцию? Знаете ли вы, какие операции вы хотите ограничить своим поколением (например, включают ли трансцендентные функции или всего 4 операции +, -, *, /)? Один из подходов - написать генератор дерева синтаксического анализа, а затем перевести дерево разбора в выражение. Генератор дерева разбора применил бы случайность в каждом узле дерева. – lurker

+0

Вам нужны ограничения (особенно по глубине, или генерация никогда не может заканчиваться) при построении генератора этого типа, иначе вы можете в конечном итоге получить такие термины, как (например, как пример): 'gamma (sqrt (gamma (sqrt (гамма (sqrt (sin (x + sqrt ((гамма (sqrt (x)))))))))))) ' –

ответ

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);

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) 
    } 
} 

Где Plus, Varref, и т.д. Конструкторы типа выражения, который реализует метод, который затем позволит вам оценить выражение при заданных значениях ,

1

Давайте предположим, что ваши функции имеют 2 переменные x1 и x2 (если это предположение является слишком ограничительным просто адаптировать свой ответ на n переменных x1, ..., xn.)

[Старт] Генерация случайных полиномиальных функций

Это повлечет за собой

  • моделирующие полиномов в 2 переменных (x1 и x2)
  • , реализующих оценку многочленов от (любой) конкретных значения переменных
  • , генерирующие случайные полиномиальные функции, принимая случайную степень (u р до некоторой макс) и случайные коэффициенты (внутри заданного интервала)

[Сотроз] Включение функции Состав

Это повлечет за собой

  • реализации состава функций, так что если , скажем, f, g и h - это функции в вашей модели (случайно сгенерированные или нет), тогда f(g,h) также является функцией вашей модели.

[Обогатить] Добавить новые функции семьи модели

Здесь вы должны рассмотреть (и реализации) и другие типы функций в одном у вас уже есть (полиномиальное): рациональный, тригонометрические, логарифмические , экспоненциальный и т.д. для каждого нового типа, вам придется моделировать их, а также, чтобы реализовать способ генерации случайных экземпляров из них (сколько вы сделали для полиномов.)

[Сформировать] Создание случайного функции, объединяющие все вышеперечисленное

  • Выберите некоторые типы случайного образом
  • Для каждого типа, генерировать случайный экземпляр
  • composé всех типов в конечный результат.

[Перебор] Перейти к [Enrich] и добавлять новые типы функций

  • Ditto.
Смежные вопросы