# cgpy.cgp module

CGP stands for Cartesian Genetic Programming, and is a network that represents a function. It's really nice. Google it!

It is defined by a gene and an operation table. The operation table is a list of mathematical operations (for example [+, -, *, cos]). The gene consists of n nodes and an ouput node. Each node, except for the output, consists of 3 numbers: the operation and the two inputs. There are always two inputs. If the operation is unary (meaning that it only takes one input - for example cos), then the second input is simply ignored. The last node defines which of the other nodes that is to be the output.

Let's the the example of a 2-dimensional CGP, with operation_table = [+, -, *, cos] gene = [0, 1, 0, 1, 2, 1, 3]

let's call the inputs x0 and x1. One can illustrate what's going on by switching out the elements of the genes that correspond to operations. Thus [0, 1, 0, 0, 2, 1, 3] becomes [+, 1, 0, -, 2, 1, 3] since operation_table[0] = + and operation_table[1] = -

The other two numbers in the nodes are the indexes of the inputs. 0 in this case corresponds to x0, and 1 to x1. Simple. But what would 2 means? That is simply the first node (the one that goes: +, 1, 0,).

Thus [0, 1, 0, 0, 2, 1, 3] becomes [+, x1, x0, -, node0, x1, 3]

The last number works on the same principle and hence 3 corresponds to the second node.

Okay, so what does all of this mean? Well, the second node is the output. And the second node is the first node minus x1. The first node is x1 plus x0. Which means that [0, 1, 0, 1, 2, 1, 3] is (x1+x0)-x1.

## Module variables

var pi

## Functions

def convert_cgp_2_str(

op_table, gene, variable_names, nr_of_nodes, dims, parameters=[])

def convert_rec(

op_table, gene, variable_names, nr_of_nodes, total_dims, nr_of_parameters, current_node_nr, parameters=[])

A recursive help function that takes a node in the CGP object and converts it into a str. Since a node depends on other nodes, it will recursively call this function but with the other nodes as input. If the input is a variable or a parameter, then it will simply return the name of the variable (as given by variable_name), or the value of the parameter (as given by parameters).

def create_random_cgp(

dims, nr_of_parameters, op_table, nr_of_nodes, nodes_per_layer=1, fast_setup=False)

Does what it says on the tin, duh.

def get_gene_max_values(

dims, nr_of_parameters, len_of_op_table, nr_of_nodes, nodes_per_layer=1)

A gene is a list of n ints, that define the CGP. Each such number has a minimum value, and a maximum value. The minimum value is always zero. This function will return a list of the n maximum values.

def random(

...)

random() -> x in the interval [0, 1).

## Classes

class CGP

A Cartesian Genetic Programming object. This is a way of denoting a mathematical function as a "gene" that can be used in evolutionary optimizations.

### Ancestors (in MRO)

### Instance variables

var dims

var gene

var has_setup_used_nodes

var is_constant

var nodes_per_layer

var nr_of_nodes

var nr_of_parameters

var op_table

### Methods

def __init__(

self, dims, op_table, gene, nr_of_parameters=0, fast_setup=False, nodes_per_layer=1)

def calc_function_str(

self, parameters=[], var_names=None)

This function returns the mathematical function of the CGP as a string. For example 'x0+cos(0.4*x0)'.

def convert2str(

self, parameters=[], var_names=None)

def eval(

self, X, parameters=[])

Evaluates the function at point X using the parameters in parameters.

If derivative is true, then it takes the derivative in the point as well. It return the tuple (function_val, derivative_val) in that case.

der_dir is the direction of the derivative. Which means that der_dir=0 => derivative with respect to X[0], and so on. If der_dir >= len(X), then we will start deriving with respect to the parameters

def gene_sanity_check(

self)

Makes sure that the gene input is consistent.

def get_mutated_copy(

self)

Creates a new CGp object by creating a new gene, that is a mutated version of the one in this object.

# TODO: This function will be changed. In the future it will randomly

change the gene UNTIL it alters a part of the gene that is used. A lot of the gene is actually not used (fun fact, the same goes for the human genome).

def merge_lists(

self, x1, x2)

def print_function(

self, parameters=[], var_names=None)

def setup_used_nodes_list(

self)

def which_parameters_are_used(

self)

def which_variables_and_parameters_are_used(

self)

class Operation

A mathematical operation. We have a couple of the elementary ones, but more might be added later.

Each object has: - a name by which it is identified - the function itself - a dual version of the function. This means that dual numbers are used.

### Ancestors (in MRO)

### Instance variables

var op_name

var str

### Methods

def __init__(

self, op_name)