Skip to content
Go to file

Latest commit


Git stats


Failed to load latest commit information.

PYGGI(Python General Framework for Genetic Improvement) Build Status Coverage Status

PYGGI logo

PYGGI is the lightweight and simple framework for Genetic Improvement. It helps one practice or experience GI with only few code lines by reducing the costs of implementing typical GI process such as source code manipulation and patch management.



You can find the PYGGI's documentation here. (Currently outdated, will be updated soon!)


 author = {An, Gabin and Blot, Aymeric and Petke, Justyna and Yoo, Shin},
 title = {PyGGI 2.0: Language Independent Genetic Improvement Framework},
 booktitle = {Proceedings of the 2019 27th ACM Joint Meeting on European Software Engineering Conference and Symposium on the Foundations of Software Engineering},
 series = {ESEC/FSE 2019},
 year = {2019},
 isbn = {978-1-4503-5572-8},
 location = {Tallinn, Estonia},
 pages = {1100--1104},
 numpages = {5},
 url = {},
 doi = {10.1145/3338906.3341184},
 acmid = {3341184},
 publisher = {ACM},
 address = {New York, NY, USA},
 keywords = {Genetic Improvement, Search-based Software Engineering},

The pdf file is available at link.

Getting Started

1. Clone the repository

$ git clone ~
$ cd PYGGI

2. Install

$ python install

3. Run the example

1. Improving runtime of Triangle by deleting delay() function call
  • java
$ cd example
$ python --project_path ../sample/Triangle_fast_java --mode [line|tree] --epoch [EPOCH] --iter [MAX_ITER]
  • python
$ cd example
$ python --project_path ../sample/Triangle_fast_python/ --mode [line|tree] --epoch [EPOCH] --iter [MAX_ITER]
2. Repairing the bug of Triangle
  • java
$ cd example
$ python --project_path ../sample/Triangle_bug_java --mode [line|tree] --epoch [EPOCH] --iter [MAX_ITER]
  • python
$ cd example
$ python --project_path ../sample/Triangle_bug_python/ --mode [line|tree] --epoch [EPOCH] --iter [MAX_ITER]
Important notice about using tree mode for Java, C++, or C programs

For the Java samples (Triangle_fast_java, Triangle_bug_java), we provide the XML version of files translated by srcML (download). However, in the general case, you should translate the target Java, C++, or C files into XML files before initialising Program instances and provide the translated those XML files as target files.

Or, you can simply override the setup method of AbstractProgram, which is initially empty, to execute the translation command.

ex) Translating to using srcML (See the context at example/

class MyTreeProgram(TreeProgram):
    def setup(self):
        if not os.path.exists(os.path.join(self.tmp_path, "")):
            self.exec_cmd("srcml -o")

Then, PyGGI will manipulate the XML files using XmlEngine(in pyggi/tree/ and convert it back to the original language by stripping all the XML tags before running the test command.

Program setup convention

Two files should be provided: a configuration file and a test script. You can refer the sample programs in the sample directory.

1. Config file (JSON format)


ex) sample/Triangle_fast_java/.pyggi.config

  "target_files": [
  "test_command": "./"

However, you can also specify the config file name (default: .pyggi.config),


program = LineProgram("sample/Triangle_fast_java", config='.custom.pyggi.config')

or directly provide the dict type configuration when initialising Program. ex)

config = {
    "target_files": [""],
    "test_command": "./"
program = LineProgram("sample/Triangle_fast_java", config=config)

2. Test script file


ex) sample/Triangle_fast/

set -e

# cd $1

rm -f *.class
javac -cp "./junit-4.10.jar"
java -cp "./junit-4.10.jar:./" TestRunner TriangleTest

The output of the test command should be the fitness of the program (only number),


or, you can use own result parser by overriding the compute_fitness method of Program classes.

This is the example of a custom result parser from example/,

class MyProgram(AbstractProgram):
    def compute_fitness(self, elapsed_time, stdout, stderr):
        import re
        m = re.findall("runtime: ([0-9.]+)", stdout)
        if len(m) > 0:
            runtime = m[0]
            failed = re.findall("([0-9]+) failed", stdout)
            pass_all = len(failed) == 0
            if pass_all:
                return round(float(runtime), 3)
                raise ParseError
            raise ParseError

class MyLineProgram(LineProgram, MyProgram):

class MyTreeProgram(TreeProgram, MyProgram):

, when the standard output is in the pytest format, such as:

======================================== test session starts ========================================
platform linux -- Python 3.6.2, pytest-3.2.3, py-1.4.34, pluggy-0.4.0
rootdir: /media/ssd/Workspace/PYGGI, inifile:
collected 4 items                                                                             ....runtime: 0.22184443473815918

===================================== 4 passed in 0.23 seconds ======================================