Random Function Generator
;;; Robert Estelle 23 Aug 2014 | |
(defun random-elt (&rest lists) | |
; Return random element from lists | |
(let ((combined (apply #'concatenate 'list lists))) | |
(elt combined (random (length combined))))) | |
(defun funwith (fn num-args vars ops max-op-depth) | |
; Generate a random operation with the given function `fn` which takes | |
; `num-args` arguments. The scalar variables `vars` may be used, or any of | |
; the `ops` wich are pairs of (name num-args). Will use ops recursively until | |
; `max-op-depth` is exhausted. | |
(let ((args (loop for i to (- num-args 1) collect | |
(if (> max-op-depth 1) | |
(destructuring-bind (op num-op-args) (random-elt ops) | |
(funwith op num-op-args vars ops (- max-op-depth 1))) | |
(random-elt vars))))) | |
`(,fn ,@args))) | |
(defun gensyms (num-syms) | |
; Generate multiple internal symbols | |
(loop for i to (- num-syms 1) collect (gensym))) | |
(defun generate-random-function (num-args ops complexity) | |
; Generates a random function, returning the variable list and the function | |
; body. | |
(let* ((vars (gensyms num-args)) | |
(op-assoc (random-elt ops)) | |
(op (car op-assoc)) | |
(num-args (cadr op-assoc)) | |
(body (funwith op num-args vars ops complexity))) | |
`(,vars ,body))) | |
(defmacro defrandom (fname num-args ops complexity) | |
; Defines a random function with the given name. | |
(let* ((fn (generate-random-function num-args ops complexity)) | |
(vars (car fn)) | |
(body (cdr fn))) | |
`(defun ,fname ,vars ,@body))) | |
;;; EXAMPLE: | |
(defrandom | |
; Define a function called "foo" | |
foo | |
; Taking in two arguments | |
2 | |
; Using the following base operations | |
; List of (operation, number of operands) | |
((+ 2) (- 2) (* 2) (/ 2) (expt 2) (exp 1) (sqrt 1)) | |
; Nest operations three levels deep | |
3) | |
(print #'foo) | |
;;; Outputs: | |
;#<FUNCTION FOO (#:G286086 #:G286087) (DECLARE (SYSTEM::IN-DEFUN FOO)) | |
; (BLOCK FOO (* (SQRT (EXP #:G286087)) (+ (- #:G286087 #:G286086) (* #:G286086 #:G286086))))> | |
(print (foo 17 2)) | |
;;; Outputs: | |
;744.8092 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment