Next: , Previous: , Up: Examples   [Contents][Index]


5.2.3 Neutral Variants

In some cases we are interested in “neutral mutants”: variants of the original program that still satisfy the test suite. (For more information, see Software Mutational Robustness available at http://arxiv.org/abs/1204.4224).

The following example constructs a collection of neutral mutants of gcd.c, using the test function defined in the Evaluation example to determine whether or not candidate variants have equivalent behavior to the original.

(defpackage :example
  (:use :gt/full
        :software-evolution-library
        :software-evolution-library/software/compilable
        :software-evolution-library/software/parseable
        :software-evolution-library/software/tree-sitter))
(in-package :example)

;;;; Create a list of 10 neutral variants

;;; Load ASM software object from file
(defvar *orig* (from-file (make-instance 'c :compiler "cc")
                          (asdf:system-relative-pathname :software-evolution-library
                                                         "test/etc/gcd/gcd.c")))

;;; Create an empty list of variants
(defvar variants nil "List to hold accumulated neutral variants.")

;;; Run the GCD unit tests on ASM. Return the number of passing tests.
(defun test (c)
  (ignore-errors
    (with-temporary-file (:pathname bin)
      ;; Build executable
      (phenome c :bin bin)
      (count-if #'identity
                (loop :for i :below 12 :collect
                   (multiple-value-bind (stdout stderr errno)
                       (shell "test/etc/gcd/test.sh ~a ~d" bin i)
                     (declare (ignorable stdout stderr))
                     ;; Collect list of T/NIL indicating if the exit code was 0.
                     ;; Tests whose exit code is 0 are considered successful.
                     (zerop errno)))))))

;;; Initialize fitness of `*orig*'.
(setf (fitness *orig*) (test *orig*))

;; Create a variant by applying a random mutation to a copy of `*orig*'
(let ((num-variants 4))
  (do ((variant (handler-bind
                    ;; Handle errors that might occur during mutation
                    ((no-mutation-targets
                      (lambda (e)
                        (declare (ignorable e))
                        (invoke-restart 'try-another-mutation))))
                  (mutate (copy *orig*)))))
      ((>= (length variants) num-variants) variants)
    ;; Test the fitness of the variant
    (format t "Variant with fitness ~d and genome:~%~a~%"
            (setf (fitness variant) (test variant))
            (genome-string variant))
    ;; When the fitness of the variant matches that of `*orig*', add it
    ;; to the list of neutral variants
    (when (>= (fitness variant) (fitness *orig*))
      (push variant variants)
      (format t "~&Collected ~d of ~d neutral variants~%"
              (length variants) num-variants))))

API components in this example


Next: , Previous: , Up: Examples   [Contents][Index]