Похоже, вы делаете что-то очень похожее на генетическое программирование ;даже если вы этого не сделаете, GP должен решить некоторые из тех же проблем, используя случайность для создания правильных программ.Подход к этому, который обычно используется, заключается в работе с синтаксическим деревом: вместо хранения x + y * 3 - 2
вы сохраняете что-то вроде следующего:
Затем вместо случайногоизменяя синтаксис, вместо этого можно произвольно менять узлы в дереве.И если x
случайным образом изменится, скажем, на +
, вы можете статически знать, что это означает, что вам нужно вставить двух дочерних элементов (или нет, в зависимости от того, как вы определяете +
).
Aхорошим выбором для языка, с которым можно работать, был бы любой диалект Lisp.В Лиспе вышеприведенная программа будет иметь вид (- (+ x (* y 3)) 2)
, который представляет собой просто линеаризацию синтаксического дерева с использованием скобок для отображения глубины.И на самом деле, Lisps предоставляет эту функцию: вы можете так же легко работать с объектом '(- (+ x (* y 3)) 2)
(обратите внимание на начальную цитату).Это список из трех элементов, первый элемент которого - -
, второй элемент - другой список, а третий элемент - 2
.И, хотя вы можете или не захотите этого для своего конкретного приложения, есть функция eval
, такая, что (eval '(- (+ x (* y 3)) 2))
будет принимать в указанном списке, обрабатывать его как дерево / программу синтаксиса Lisp и оценивать его.Это то, что делает Лиспс таким привлекательным для такой работы;Синтаксис Lisp - это, по сути, повторение синтаксического дерева, и если вы работаете на уровне синтаксического дерева, вы можете работать с кодом, как если бы это было значение.Lisp не поможет вам читать /dev/random
как программу напрямую, но с небольшой интерпретацией, расположенной сверху, вы сможете получить то, что хотите.
Я должен также упомянуть, хотя я незнаю что-нибудь об этом (не то, что я знаю много об обычном генетическом программировании) о существовании линейного генетического программирования .Это что-то вроде упомянутой вами модели сборки - линейный поток очень, очень простых инструкций.Преимущество здесь может заключаться в том, что если вы работаете с /dev/random
или чем-то подобным, объем необходимой интерпретации очень мал;как вы упомянули, недостатком будет низкоуровневая природа кода.