Plushi is an embadable language agnostic push interpreter capable of running push programs via JSON interface.
Push is a programming language designed for AI systems to write software in. It has virtually no syntax and supports all common data types and can express a variety of control structures and data structures.
To read more about the push language, see the Push Redux.
Download the standalone jar from https://github.com/erp12/plushi/releases.
To build your own standalone jar, clone the repository and run the following leiningen commands.
lein deps
lein uberjar
For easy integration with Clojure projects, a public clojars release coming soon!
The Plushi interpreter is wrapped in an HTTP server written using ring. Any environment capable of making POST requests can use Plushi. JVM languages can also attempt to use plushi via inerop, although this is not the primary design goal.
To start the plushi HTTP server, simply run the jar with the --start
flag.
java -jar plushi-0.1.0-standalone.jar --start
# or
$ java -jar plushi-0.1.0-standalone.jar -s
The default port is 8075
. To specify the port number, supply the --port
flag
followed by a valid port number.
java -jar plushi-0.1.0-standalone.jar --start --port 8076
# or
$ java -jar plushi-0.1.0-standalone.jar -s -p 8076
All of the actions required to synthesis plushi programs are available via POST requests to the plushi HTTP server. Other applications can send JSON blobs that describe what action the plushi server should take.
The Plushi interpreter supports a set of instructions which can appear in programs along side literals (ints, floats, strings, booleans). These instructions and literals in a linear sequence is a "plush program" which can be executed by the plushi interpreter.
To request the Plushi instruction set, the JSON blob in the request body must
have 2 keys: "action"
and "arity"
. The value of the "action"
key must
be "instructions"
and the value of the "arity"
key should be an integer
denoting how many inputs the programs you would like to generate will accept.
Below is an example of this in python.
import json, requests
instr_set = requests.post("http://localhost:8075/", json=json.dumps({
'action': 'instructions',
'arity': arity
})).json()
Depending on what kinds of programs you intend on synthesizing, it maybe be
helful to know what kinds of data types the Plushi interpreter is capable of
manipulating. The "types"
action returns this information on requst.
Below is an example of this in python.
import json, requests
plushi_types = requests.post("http://localhost:8075/",
json=json.dumps({'action': 'types'})).json()
If the value associated with the "action"
key is "run"
then Plushi will
expect to be running a given plush program.
Below is an example of request made through python. All of the required and optional values are described in detail in the paragraphs below.
import json, requests
X = json.load("data.json")
request_body = {
'action': 'run',
'code': [1, 2, "plushi:integer_add"],
'arity': 1,
'output-types': ['integer'],
'dataset': X
}
outputs = requests.post("http://localhost:8075/",
json=json.dumps(request_body)).json()
The value for the "code"
key should be a flat list containing valid plushi atoms.
A valid plushi atom can be any of the following:
- an integer
- a float
- a boolean
- a string
If a string atom is equal to a name of any instruction (ie "plushi:float_mult"
)
Plushi will assume that the atom at that position should be the instruction.
Otherwise the string (or any other atom) will be assumed to be a literal.
Unlike other implemenations of the the Push language, Plushi programs are always
linear. Certain instructions (ie. exec_if
) assume that the subsequent atom is
a nested Push expression (or "code block"). Plushi has a dedicated instruction
called close
which denotes the closing of a code block. Using these instructions
a linear Plushi program can be translated into a traditional, executable Push
program. If no code blocks are open, the close
instructions are a noop.
An integer denoting how many inputs the program specified by "code"
will expect. This is also the number of features in the dataset.
A list of plushi types to return after program execution. If more than one value of a certain type should be output, that type name should appear in the list multiple times.
For example a program which returns two integer and a string should set the
"output-types"
value to ["integer", "integer", "string"]
.
Plushi is designed to be used inside of inductive machine learning frameworks. Thus, it is expected that each program will need to be run on an entire dataset of inputs for evaluation.
The value of the "dataset"
key is expected to be a list of JSON objects.
Each JSON object is one record in the dataset with the keys being feature names
and values being feature values.
[
{"name" : "Alice", "age": 31},
{"name" : "Bob", "age": 45},
{"name" : "Cathy", "age": 24},
]
The dataset should not contain the training label you are trying to predict. Currently Plushi only requires you specify the arity of the program, not the names of which feature to use, and thus Plushi may use your label as an input by mistake.
Below is a list of other projects which use Plushi:
- plushi-annealing - A simple simulated annealing algorithm for synthesizing Plushi programs.
All contributions and ideas are strongly encouraged!
To see the list of proposed new features and changes, check the issues on the project's issues. Feel free to open new issues with any ideas or suggestions.
If you would like to contribute to either the source code or the documentation, please follow the "GitHub Flow" which is simply summarized here.
TLDR:
- Fork the official repository.
- Create a branch for your contribution.
- Make commits (Including tests).
- Open a pull request and await review and merge.
Copyright © 2018 Edward Pantridge
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.