Plushi: An Embeddable, Language Agnostic, Push Interpreter
Edward Pantridge
Lee Spector
MassMutual
epantridge@massmutual.com
Hampshire College
lspector@hampshire.edu
ABSTRACT
A special stack, called the execution stack (or just the exec stack),
is used to manage program execution. When we wish to execute
a program, we place it on the exec stack and then repeatedly pop
and process the top item on the exec stack until the exec stack is
empty, or until an execution step limit has been reached. At that
point, result values can be taken from the interpreter’s stacks.
When a parenthesized expression is processed, its outermost
parentheses are removed and all of the items that they enclosed are
pushed individually back onto the exec stack, with the last item in
the expression pushed first. When a literal is processed, it is moved
to the top of the stack that matches its type. When an instruction
is processed, all of the arguments that it requires are popped from
the stacks of the appropriate types. The instruction then pushes
any resulting values onto the tops of the stacks of the appropriate
types. If the stacks do not contain sufficient values of the needed
types, then the instruction is a łno-opž and has no effect. Because
the exec stack can itself be manipulated by instructions, it is easy
to provide instructions that implement arbitrary control structures,
including conditionals and loops [14].
One consequence of this design is that all sequences of valid symbols with balanced parentheses are syntactically valid Programs that
will execute without error. This is true even though Push supports
arbitrary data types and is Turing complete, which in most languages make syntax and semantic errors possible. This combination
of features makes Push useful as the target language for program
induction in genetic programming systems, for which it was developed, because it simplifies the random generation and variation
of programs that may use arbitrary data and control structures.
The same features may also make Push useful in other program
induction systems.
Prior Push implementations have generally been designed for
use only within the host language in which they were implemented,
often in conjunction with a specific program induction system that
is written in the same host language. In this paper we present
Plushi, an embeddable, host-language agnostic Push interpreter
that is designed to interoperate with program induction systems
written in any language.
The goal of the Plushi project is to create a Push interpreter
that can be interfaced with as many machine learning and artificial
intelligence systems as possible. This will allow for easier comparison of search methods, and also allow more search methods to be
applied to inductive program synthesis tasks that require the use
of arbitrary data types and control structures [9].
The following section outlines the motivation for creating Plushi.
The subsequent section explains how Plushi is used by machine
learning systems and how synthesized Push programs can be deployed, for example to serve new predictions in data prediction
applications. Finally, we describe the primary implementation details of Plushi and conclude with suggestions for future research
and development.
In the Push programming language, all sequences of valid symbols with balanced parentheses are syntactically valid and execute
without error. Push nonetheless supports arbitrary data types and
is Turing complete. This combination of features makes it useful
as the target language for program induction in genetic programming systems, for which it was developed, and potentially also in
other program induction systems. Prior Push implementations have
generally been designed for use only within the host language in
which they were implemented, often in conjunction with a specific
program induction system that is written in the same host language.
In this paper we present Plushi, a modular, embeddable Push interpreter that is designed to interoperate with program induction
systems written in any language.
CCS CONCEPTS
· Software and its engineering → Automatic programming;
Genetic programming;
KEYWORDS
genetic programming; program synthesis;
ACM Reference Format:
Edward Pantridge and Lee Spector. 2018. Plushi: An Embeddable, Language
Agnostic, Push Interpreter. In GECCO ’18 Companion: Genetic and Evolutionary Computation Conference Companion, July 15ś19, 2018, Kyoto, Japan.
ACM, New York, NY, USA, 7 pages. https://doi.org/10.1145/3205651.3208296
1
INTRODUCTION
The Push programming language operates on a virtual stack machine, with a separate stack for each data type. It was developed to
serve as the language in which evolving programs are expressed in
genetic programming systems, but it may have use in other forms
of programming induction as well.
Push programs are parenthesized sequences of instructions and
literals, which may also contain nested, parenthesized sequences of
instructions and literals. Push implementations typically provide
stacks for common data types such as integers, floating point numbers, boolean values, and strings, but they may also provide stacks
for any other data types that the developers choose to include [14].
Permission to make digital or hard copies of all or part of this work for personal or
classroom use is granted without fee provided that copies are not made or distributed
for profit or commercial advantage and that copies bear this notice and the full citation
on the first page. Copyrights for components of this work owned by others than ACM
must be honored. Abstracting with credit is permitted. To copy otherwise, or republish,
to post on servers or to redistribute to lists, requires prior specific permission and/or a
fee. Request permissions from permissions@acm.org.
GECCO ’18 Companion, July 15ś19, 2018, Kyoto, Japan
© 2018 Association for Computing Machinery.
ACM ISBN 978-1-4503-5764-7/18/07. . . $15.00
https://doi.org/10.1145/3205651.3208296
1379
GECCO ’18 Companion, July 15–19, 2018, Kyoto, Japan
2
MOTIVATION FOR PLUSHI
There have been many push interpreters implemented in recent
years. Most Push interpreters are tightly coupled with a particular genetic programming framework. These interpreters tend to
support slightly different data types and instruction sets. These
interpreters are also implemented in different host programming
languages and generally rely on the host languages’ built-in indexed data structures to store programs. For example, the Python
implementation, pyshgp,1 stores programs in a Python list while
the Clojure implementation, Clojush,2 stores programs in Clojure
vectors. [10]
The consequences of these different implementations is that
programs found by any given Push Genetic Programming system
can only be run by the same framework which produced it. This
made the productionalization of Push programs difficult. After a
program had been found by the genetic programming system, all
future calls to that program would require the use of the entire
genetic programming system.
This called for the design of a standardized, serialized program
representation. If Push programs could be represented in a standard text format that most programming languages are capable
of producing, that would help arbitrary machine learning systems
produce Push programs capable of being run by the same Push interpreter. Plushi chose to represent programs as JSON lists because
of the ubiquity of the format [1].
Aside from a standardized program encoding, it was also beneficial to create a fully featured Push interpreter that is decoupled
from any machine learning framework. The interpreter should be
usable from as many environments as possible and be able to accept
programs encoded in the standard way described above.
Plushi achieves these desired properties by running an HTTP
server in a dedicated process that receives JSON encoded programs
via POST requests. The server responds with the result of running
the program. This allows many machine learning systems to be
used in tandem with Plushi to attempt program synthesis tasks.
3
Edward Pantridge and Lee Spector
PLUSHI USAGE
There are many commonly used machine learning frameworks that
implement a variety of search and optimization methods. These
machine learning frameworks are implemented across a variety
of programming languages. In the Python programming language
alone there are a wide range of machine learning systems including:
DEAP, TensorFlow, Keras, Sci-kit Learn, Spark ML and more.
These machine learning systems implement algorithms from
various fields such as evolutionary computation and artificial neural networks. Given the success of Push in genetic programming
systems, it may be that simply adding Plushi to some of the more
mature evolutionary computation frameworks, such as HeuristicLab [3] and DEAP [4], could yield improved results over existing
results achieved by genetic programming frameworks that synthesize Push programs [6].
The Plushi system aims to provide an interpreter for the Push
language that will enable users to leverage the diverse community of machine learning systems for the purposes of automatic
programming.
In order to achieve an interface that can be used from as many
environments as possible Plushi is implemented as an HTTP server.
The Plushi server can be run locally, or on dedicated hardware.
The user, or users, interact with the Plushi server through POST
requests. The body of each POST request is assumed to be JSON
which the Plushi server parses, and interprets in various ways
described in section 4.1. The response Plushi gives to each POST
request is also serialized in JSON format.
It is very common for programming languages to have built-in or
library support for making POST requests. It is also very common
for programming languages to support the reading and writing of
JSON data. This implies that many systems which are commonly
used for machine learning can now utilize Plushi in addition to existing machine learning frameworks in order to perform automatic
programming tasks.
The Plushi server is written in Clojure, and is built as a standalone
.jar artifact. This makes distribution and deployment on a wide
range of computer systems trivial. Any device that has access to a
JVM can use the Plushi server to execute Push programs [8].
3.1 Plushi Request Types
For every request sent to the Plushi server, the request body is
parsed as JSON data. Each request requires that the action key
be specified with a string for its value. There are two values for
action that are run while using the Plushi interpreter to generate
and execute Push programs. The first action returns the set of
supported instructions which can appear in a program. The second
action returns the output of running a given program on a given
dataset.
3.1.1 The “instructions” Action.
When the value of the łactionž field in the request body JSON is
łinstructionsł the Plushi server will return the set of supported
instructions which can appear in programs that will be run by
the Plushi interpreter. The instruction set is encoded in JSON as
a list of one key-value object per instruction. The schema of each
instruction object contains a key-value pair for the instruction
name, a list of types the instruction requires as input, and a list of
types the instruction produces as output. Each of these instruction
objects is referred to as an instruction signature, because it holds
name and type information related to the instruction, but not a
full specification of its behavior. Below is an example of a single
instruction JSON object for the integer_add instruction which
produces the sum of two integers.
{
" name " : " p l u s h i : i n t e g e r _ a d d " ,
" input −types " : [ " i n t e g e r " , " i n t e g e r " ] ,
" output −types " : [ " i n t e g e r " ] ,
}
1 https://github.com/erp12/pyshgp
When making a request with the łinstructionsž action, it is required that the łarityž key be present in the request body JSON.
2 https://github.com/lspector/Clojush
1380
Plushi: An Embeddable, Language Agnostic, Push Interpreter
GECCO ’18 Companion, July 15–19, 2018, Kyoto, Japan
This field specifies the number of inputs (or features) the program
being searched for, or learned, will take. Plushi needs this information when creating the instruction set because each input value to
a Plushi program receives a dedicated instruction that produces the
input value each time it is evaluated.
Below is a snippet of python code that uses the requests and
json libraries to make an łinstructionsž request. It assumes a Plushi
interpreter is running locally on port 8075.
this include: optimizing a set of coefficients for a linear model, selecting splits to use in a decision tree, and finding parameter values
for the weights of an artificial neural network that minimizes the
loss function. In order to guide these search/optimization procedures, a training dataset is generally used to evaluate intermediate
models until a fit model is produced.
Plushi is designed with this training phase in mind. In order
to minimize the time spent on communication between the machine learning framework and the Plushi server, a program can be
executed on an entire dataset using one request. In other words,
Plushi expects that most use cases would prefer higher throughput
without much regard to maintaining a low latency.
import json as j
import r e q u e s t s as r
body = {
' action ' : ' instructions ' ,
' arity ' : 4
}
i n s t r _ s e t = r . post ( " http : / / localhost :8075/ " ,
j s o n = j . dumps ( body ) ) . j s o n ( )
3.3 Deploying Plushi Models
One of the failings of previous Push systems is the ability to easily
save and deploy the synthesized programs for later use. A benefit
of Plushi’s JSON program representation is that programs found
by machine learning frameworks can easily be persisted. Programs
can also be run in any environment that has access to a Plushi interpreter, regardless of if the environment has access to the machine
learning system used to produce the program. This also implies that
if multiple different machine learning methods produce a collection
of Plushi programs, all programs can be deployed into a system
that uses a single Plushi interpreter.
When models are deployed, or productionalized, they are used
to make predictions on new data. Predictions are often made on
single data records in real-time. Predictions can also be made on
larger batches data on a less frequent schedule. Both use cases
are possible with the Plushi server, however the use case of many,
frequent, single prediction requests has not yet been extensively
tested. The use case of larger, infrequent batches bears resemblance
to the training stage discussed in Section 4.2.
The Plushi server can run a different program on each request,
thus it is possible to run a single Plushi server that can make predictions using all productionalized programs produced by the machine
learning systems within an organization. This use case could benefit from multiple Plushi servers running on different machines
behind a load balancer.
After making a request to retrieve the instruction set from Plushi
server, the user can filter the list of instruction signatures down
to only the instructions that deal data types relevant to the problem. For example, if a machine learning system is using Plushi to
produce a real-valued regression model there does not need to be
instructions that manipulate strings in the programs produced by
the machine learning system. Performing this intuitive filtering of
the instruction set helps limit the search space, but it is not required.
3.1.2 The “run” action.
When the value of the łactionž field in the request body JSON is
łrunł the Plushi server will return a list of output values produced
when running a Plushi program on each case in a dataset. The
required field of a Plushi request with the łrunž action are given in
figure 1.
Below is a snippet of python code that uses the requests and
json libraries to run a program that adds the numbers 1 and 2 on
a Plushi interpreter running locally on port 8075. It assumes that
there is a JSON file containing the dataset to run the program on in
a file named data.json.
3.4 Example Usage
import json as j
import r e q u e s t s as r
X = j . load ( " data . json " )
b = {
' a c t i o n ' : ' run ' ,
' code ' : [ 1 , 2 , " p l u s h i : i n t e g e r _ a d d " ] ,
' arity ' : 1 ,
' output −types ' : [ ' i n t e g e r ' ] ,
' dataset ' : X
}
outputs = r . post ( " http : / / localhost :8075/ " ,
j s o n = j s o n . dumps ( b ) ) . j s o n ( )
To evaluate the ease of Plushi usage, a simple Python implementation of simulated annealing was created that produces Plushi
programs. The full application (simulated annealing and Plushi
calls) was written in under 150 lines of Python code.3
To start a separate process which runs the Plushi server from
within Python, the Popen class from the subprocess library was
used. In other applications if the ability to spawn a new process is
not available, the Plushi server can be started beforehand. Assuming
we have built the Plushi software into a .jar file named łplushistandalone.jarž the system call which is needed to start the server
is as follows:
java -jar plushi-standalone.jar --start
To generate random programs, the simulated annealing scripts
first get the set of supported instructions through an łinstructionsž
3.2 During Training or Search
The core function of a machine learning system is to search for some
kind of optimal structure that solves a problem. Some examples of
3 The
code for this example can be found in the python files here:
https://github.com/erp12/plushi-annealing
1381
GECCO ’18 Companion, July 15–19, 2018, Kyoto, Japan
Key
code
arity
output-types
dataset
Edward Pantridge and Lee Spector
Description
A serialized Plushi program. Must be a JSON list with no nested lists.
The number of inputs (or features) the program will takes. Plushi needs this to create the instruction set because each
input value to a Plushi program receives a dedicated instruction that produces the input value each time it is evaluated.
A list of type names which will be returned in a list as the output value of running the program.
The dataset to run the program on serialized into JSON. The dataset should be a list or records. Each record would be a
JSON object where the keys are the feature names and the values are the feature values.
Figure 1: A table of keys which must appear in the body of the POST request sent to Plushi when the action field is set to łrunž.
The response to these requests will be a JSON blob containing a list of output values produced by running the program from
the łcodež field on each of the records in the dataset from the łdatasetž field.
Processor
Processor Speed
Total Number of Cores
Memory
Intel Core i7
2.8 GHz
4
16 GB
Figure 2: A table of hardware (MacBook Pro) specs used to
benchmark the program executions per second achieved by
the simulated annealing example.
request as described in section 3.1. A random linear sequence of
the name fields from any of these instructions is a valid program.
Programs can also include integers, floats, booleans, and strings
that are not equivalent to instruction names.
The simulated annealing algorithm was selected because it is
fairly lightweight and most of the computation is done during
evaluation of programs. On the hardware described in figure 2 the
Plushi server was able to perform 1998 program executions per
second, where each program was 100 elements long. The number
of program executions per second for various program lengths
is given by Figure 3. At this time, the Plushi request handling
does not utilize any parallel or asynchronous computation during
program execution. This is a valuable area or future research and
development.
4
IMPLEMENTATION
Plushi was written in the Clojure programming language, and is
built as a standalone .jar artifact. Clojure is a modern Lisp language that runs on the Java Virtual Machine (JVM) thus it is possible
for other programming languages that run on the JVM to use Plushi
via direct interop [8]. This is not the primary use case Plushi is
designed for, because producing a standalone service allows Plushi
to be more language agnostic.
The two main implementation differences between Plushi and
other Push interpreters is the variant of the Push language specification that was used to maintain linear programs, and the use of
an HTTP server to allow for the Plushi interpreter to be embedded
in arbitrary systems.
Lastly, it is common to implement custom, domain specific instructions to allow for Push programs to operate in particular domains. For example, previous applications of the Push language
inside of genetic programming systems have been augmented with
instructions that allow Push programs to express quantum circuits
or artificial neural network architectures [11, 13]. To add these
instructions to Plushi a change to the source code is required. A
new instruction can be registered with a single function call, as
described later in Section 4.3.
4.1 Linear Push Variant
The contemporary specification of the Push language is simply
nested sequences of Push atoms, where an atom is either an instruction supported by the interpreter or a literal value of some
primitive data type. The nested structure was generally considered
to be important because a nested sequence is commonly used as
the body of control structures, such as conditionals and loops. The
problem introduced by the nested structure of Push programs is
that many machine learning methods cannot search over arbitrarily
nested structures. The original uses of the Push language in genetic
programming systems did not have this obstacle because it is common to use genetic operators that manipulate nested structures,
such as trees.
Plushi implements a new specification of the Push language
where all programs are represented in a linear structure. Despite
the linear structure, this variant of the push language can still
express synonymous programs to the nested specification, as described in the following paragraphs. This is achieved by through
two implementation details in the Plushi instruction set.
First, each instruction includes a field which denotes the number
of code blocks which should follow it in the program. For example,
the exec_if instruction (which implements a simple if-else logic)
should be followed by two code blocks: one for the if clause, and
one for the else clause. The exec_while instruction (which implements a while loop) should be followed by one code block which
is considered to be the body of the while loop.
Second, programs can contain placeholder atoms called the
łclosež atoms which denote the end of a code block. The Plushi
interpreter use these łclosež atoms along with number of code
blocks opened by the definitions of each instruction to translate
the linear program representations proposed in this paper into the
traditional, nested Push programs. This preserves the expressiveness of Push because control structures, such as loops, can have
arbitrarily long code blocks acting as the body of the loop.
Figure 4 shows a JSON list which could be executed by Plushi
and contains a control structure which utilizes close atoms. The
definition of exec_if specifies that there should be two code blocks
following the instruction. Given the two instances of the close
atom in the program, we know that the first code block contains
the integer literal 1 and the second code block contains the integer
1382
Plushi: An Embeddable, Language Agnostic, Push Interpreter
GECCO ’18 Companion, July 15–19, 2018, Kyoto, Japan
Figure 3: A bar chart with a linear trend line showing the number of program executions the Plushi server was able to run
per second as it relates to the size of the programs being sent to it. All programs were produced by the simulated annealing
example attempting to synthesize the ReLU function [5]. These timings were seen on the hardware described in figure 2.
[ " plushi : input_0 " , " plushi : exec_if " , 1 , " plushi : close " , 0 , " plushi : close " ]
Figure 4: An example program demonstrating the use of the close atoms. The input_0 instruction pushes the value of the first
feature in the feature vector. If we assume that the first first feature is a boolean value the program will output 0 if the input
feature value is true, and zero if it is false. The close atoms mark the ending points of the if and else
literal 0. It is possible for an arbitrary number of instructions and
literals to appear in a code block.
When translating from the linear program representation to the
nested representation, close atoms can be ignored if: 1) no instructions with open code blocks have been present in the program or
2) all instructions which denote the opening of code blocks have
been closed by previous close atoms. If the entire contents of the
linear program representation have been translated and there are
code blocks which have not yet been closed, additional close atoms
are added to the end of the program until all code blocks have been
closed.
The motivation for keeping the program structure linear is that
it removes all syntax requirements from the language specification. Any sequence of Plushi atoms is an executable program. It is
not possible for Plushi programs to produce runtime errors. This
helps machine learning systems search the space of programs unrestricted.
It should be noted that the concept of creating a linear representation of Push programs is not a novel contribution put forth by
this work. Some genetic programming systems have developed linear genomes that are translated into nested Push programs. These
genomes are generally referred to as Plush genomes [7]. These
genomes do not utilize close atoms, but rather mark certain genes
with epigenetic markers to denote the insertion of a close parenthesis.
4.2 The Plushi Server
As described in section 4, Plushi is implemented as an HTTP server
capable of responding to POST requests that ask the server to run a
particular program on a given dataset. Plushi uses the Ring library
written in the Clojure language to implement the HTTP server
abstraction [2].
The Plushi server assumes the body of each request is valid
JSON. The responses given by the Plushi server are also have a
body encoded in JSON. One potential area for future development
is to include support for more expressive file formats, such as EDN.
4.3 Extending the Instruction Set
When human programmers write software for particular domains,
it is common for a library of additional functions related to the
domain to be used. When synthesizing Push programs using machine learning, it is similarly beneficial to augment the standard
instruction set with specialized instructions relating to the problem
domain.
1383
GECCO ’18 Companion, July 15–19, 2018, Kyoto, Japan
Edward Pantridge and Lee Spector
Some notable examples of this include a set of quantum instructions which were used in Push programs to express quantum circuits. Using these specialized instructions, a genetic programming
system was able to search the space of quantum circuits and discover
novel quantum computations [13]. Another example of augmenting
the instruction set is the use of instructions to manipulate the architecture of a neural network. In other words, the result of executing a
Push program containing these instructions is a untrained network.
The number of layers, and each of their sizes, are all determined
by the push program which may have utilized arbitrary control
structures to find interesting architectures [11].
To define custom instruction in Plushi, the source code must
be modified to include additional calls the the register function.
This function takes the following arguments:
properly documented. When defining new instructions, users can
specify a łdocstringž that describes the behavior of the instruction.
When users send an łinstructionsž request, they can specify an
additional field that will include the docstrings of each instruction.
The Plushi standalone .jar artifact can also generate an HTML
page describing the instruction set by running with the --docs flag
instead of the --start flag.
Plushi is an open source project, hosted on GitHub4 . This allows
for easy distribution of releases, coordination of contributions, and
the use of continuous integration tools.
The Plushi repository contains a comprehensive unit test suite,
which includes unit tests of each instruction supported by the Plushi
interpreter. In addition to unit tests, a handful of validation tests
that run sample Plushi programs on small datasets are included in
the repository. Both of these sets of tests are run on every contribution to ensure the language specification and the interpreter are
behaving as expected.
Documentation on the Plushi software is also generated from
files within the repository. These include markdown documents
explaining the use of the software and docstrings embedded in the
source code. Plushi utilizes a tool called lein-codox to convert
both these sources of documentation into a web page which is then
hosted publicly on GitHub Pages5 [12].
• An instruction name that is unique throughout the instruction set.
• A Clojure function which implements the desired behavior
of the instruction. The function should return either a single
value, or a vector of values.
• A vector of Clojure keywords denoting the type of each
argument to the function. This is used to determine which
stacks to pop arguments off of.
• A vector of Clojure keywords denoting the type of each value
returned by the function. This is used to determine which
stacks to route return values to.
• A integer denoting the number of code blocks following the
instruction. This generally zero except when implementing
control structures as described in section 4.1.
• Optionally, a doc-string describing the behavior of the instruction.
5
CONCLUSION
With this proposal of the Plushi system, the Push language can
now be used outside of genetic programming systems. A much
broader set of machine learning algorithms can now perform program synthesis tasks via the use of the push language. Programs
found by these machine learning systems can be deployed and
executed in real-time or on large datasets without the use of the
machine learning system which produced the programs.
Now that there is an embeddable, language agnostic interpreter
for the Push language, we hope to see Push introduced into many
existing machine learning frameworks, both within and outside
the evolutionary computation community. It would be valuable
to closely monitor any project that attempts to add Plushi as a
dependency in order to start using the Push language to perform
program synthesis.
We hope to treat any such integration as a case study to evaluate
the effectiveness of the Plushi server as an interface between the
machine learning system and the Push interpreter. Possible flaws
surrounding the feasibility of the current Plushi system could, and
will, be identified as Plushi sees more application.
More testing needs to be done to determine how well the Plushi
server scales to larger problems, and larger datasets. This may
require research into an appropriate application of parallel computation that Plushi could leverage to see increased throughput.
Another area of future development that may improve the Plushi
system is support for additional formats in which to encode serialized programs. One very promising format is EDN, which supports
a wider range of data types than JSON.
Figure 5 shows a code snippet which calls the register function
to define a new instruction named exec_if. The behavior of this
instruction is simply the if-else control structure, but the call to
register also specifies that the instructions arguments should come
from the boolean and exec stacks. Also, the result of the exec_if
instruction should be pushed back to the exec stack.
In addition to defining new instructions, it is also common to
utilize auxiliary stacks to hold values other than the standard data
types. For example, an custom instruction to manipulate a network
architecture may pop a network encoding off of a dedicated network
stack and push a modified version of the network back onto the
same stack. As shown in Figure 5, the stacks which are used as the
source of arguments and the destination of returned values must
be specified when registering each instruction. When a program
is executed by the Plushi interpreter, the initial stacks are created
based on the set of types which exist in the list of input and output
types across the entire instruction set. Thus, the required stacks
are implicit and no addition work by the user is required to create
more stacks.
4.4 Other Features
Although the Push language, and the linear variant proposed in
this paper, are designed for machine learning systems to produce
programs with, it is still common that human users will want to
investigate the synthesized programs to understand how they work.
For this reason, it is important for the Plushi instruction set to be
4 https://github.com/erp12/plushi
5 https://erp12.github.io/plushi/index.html
1384
Plushi: An Embeddable, Language Agnostic, Push Interpreter
GECCO ’18 Companion, July 15–19, 2018, Kyoto, Japan
( register " exec_if "
( fn [ b then e l s e ] ( i f b then e l s e ) )
[ : boolean : exec : exec ] [ : exec ] 2
" I f the top boolean i s true , execute the top element of the exec
s t a c k and s k i p t h e s e c o n d . O t h e r w i s e , s k i p t h e t o p e l e m e n t o f t h e
e x e c s t a c k and e x e c u t e t h e s e c o n d . " )
Figure 5: A Clojure snippet showing an example call to the register function which creates the exec_if instruction. This
instruction implements the if-else control structure.
ACKNOWLEDGEMENTS
This material is based upon work supported by the National Science
Foundation under Grant No. 1617087. Any opinions, findings, and
conclusions or recommendations expressed in this publication are
those of the authors and do not necessarily reflect the views of the
National Science Foundation.
REFERENCES
[1] [n. d.]. JSON. ([n. d.]). https://www.json.org/
[2] [n. d.]. ring-clojure. ([n. d.]). https://github.com/ring-clojure/ring
[3] Achiya Elyasaf and Moshe Sipper. 2014. Software review: the HeuristicLab
framework. Genetic Programming and Evolvable Machines 15, 2 (01 Jun 2014),
215ś218. https://doi.org/10.1007/s10710-014-9214-4
[4] Félix-Antoine Fortin, François-Michel De Rainville, Marc-André Gardner, Marc
Parizeau, and Christian Gagné. 2012. DEAP: Evolutionary algorithms made easy.
Journal of Machine Learning Research 13, Jul (2012), 2171ś2175.
[5] Richard H. R. Hahnloser, Rahul Sarpeshkar, Misha A. Mahowald, Rodney J. Douglas, and H. Sebastian Seung. 2000. Digital selection and analogue amplification
coexist in a cortex-inspired silicon circuit. Nature 405 (22 06 2000), 947 EP ś.
http://dx.doi.org/10.1038/35016072
[6] Thomas Helmuth and Lee Spector. 2015. General Program Synthesis Benchmark
Suite. In Proceedings of the 2015 Annual Conference on Genetic and Evolutionary
Computation (GECCO ’15). ACM, New York, NY, USA, 1039ś1046. https://doi.
org/10.1145/2739480.2754769
[7] Thomas Helmuth, Lee Spector, Nicholas Freitag McPhee, and Saul Shanabrook.
2016. Linear Genomes for Structured Programs. Genetic Programming Theory
and Practice XIV (Genetic and Evolutionary Computation) (2016).
[8] Rich Hickey. [n. d.]. Clojure. ([n. d.]). https://clojure.org/
[9] Edward Pantridge, Thomas Helmuth, Nicholas Freitag McPhee, and Lee Spector.
2017. On the Difficulty of Benchmarking Inductive Program Synthesis Methods. In
Proceedings of the Genetic and Evolutionary Computation Conference Companion
(GECCO ’17). ACM, New York, NY, USA, 1589ś1596. https://doi.org/10.1145/
3067695.3082533
[10] Edward Pantridge and Lee Spector. 2017. PyshGP: PushGP in Python. In Proceedings of the Genetic and Evolutionary Computation Conference Companion
(GECCO ’17). ACM, New York, NY, USA, 1255ś1262. https://doi.org/10.1145/
3067695.3082468
[11] Edward R. Pantridge and Lee Spector. 2016. Evolution of Layer Based Neural
Networks: Preliminary Report. In Proceedings of the 2016 on Genetic and Evolutionary Computation Conference Companion (GECCO ’16 Companion). ACM, New
York, NY, USA, 1015ś1022. https://doi.org/10.1145/2908961.2931664
[12] James Reeves. [n. d.]. codox. ([n. d.]). https://github.com/weavejester/codox
[13] Lee Spector and Jon Klein. [n. d.]. Machine Invention of Quantum Computing
Circuits by Means of Genetic Programming. AI-EDAM: Artificial Intelligence for
Engineering Design, Analysis and Manufacturing, year=2008, volume=22, number=3
pages=275ś283, ([n. d.]).
[14] Lee Spector, Jon Klein, and Maarten Keijzer. 2005. The Push3 Execution Stack
and the Evolution of Control. In Proceedings of the 7th Annual Conference on
Genetic and Evolutionary Computation (GECCO ’05). ACM, New York, NY, USA,
1689ś1696. https://doi.org/10.1145/1068009.1068292
1385