New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

cartesian

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cartesian - pypi Package Compare versions

Comparing version
0.1.7
to
0.1.8
+8
.readthedocs.yml
build:
image: latest
python:
version: 3.6
setup_py_install: true
requirements_file: requirements-dev.txt
<!-- Alabaster (krTheme++) Hacks -->
<!-- CSS Adjustments (I'm very picky.) -->
<style type="text/css">
/* Rezzy requires precise alignment. */
img.logo {margin-left: -20px!important;}
/* "Quick Search" should be capitalized. */
div#searchbox h3 {text-transform: capitalize;}
/* Make the document a little wider, less code is cut-off. */
div.document {width: 1008px;}
/* Much-improved spacing around code blocks. */
div.highlight pre {padding: 11px 14px;}
/* Remain Responsive! */
@media screen and (max-width: 1008px) {
div.sphinxsidebar {display: none;}
div.document {width: 100%!important;}
/* Have code blocks escape the document right-margin. */
div.highlight pre {margin-right: -30px;}
}
</style>
<h3>Useful Links</h3>
<ul>
<li><a href="http://github.com/Ohjeah/cartesian">cartesian @ GitHub</a></li>
<li><a href="http://pypi.python.org/pypi/cartesian">cartesian @ PyPI</a></li>
<li><a href="http://github.com/Ohjeah/cartesian/issues">Issue Tracker</a></li>
</ul>
import os
import sys
import datetime
sys.path.insert(0, os.path.abspath("../"))
import cartesian
project = "Cartesian"
copyright = "{}, Markus Quade".format(datetime.datetime.now().year)
author = "Markus Quade"
version = release = cartesian.__version__
master_doc = "index"
extensions = [
"sphinxcontrib.apidoc",
"sphinx.ext.autodoc",
"sphinx.ext.todo",
"sphinx.ext.viewcode",
"sphinx.ext.autosummary",
"sphinx.ext.napoleon",
]
apidoc_module_dir = "../cartesian"
apidoc_excluded_paths = ["tests"]
autodoc_default_flags = ["members"]
autodoc_member_order = "bysource"
autoclass_content = "init"
language = None
exclude_patterns = ["_build"]
pygments_style = "sphinx"
add_module_names = True
add_function_parentheses = False
todo_include_todos = True
html_theme = "sphinx_rtd_theme"
html_show_sourcelink = False
html_show_sphinx = False
html_show_copyright = True
default_role = "any"
Overview
--------
.. include:: ../README.rst
API Documentation
-----------------
.. toctree::
:maxdepth: 4
api/modules
Indices and tables
------------------
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SPHINXPROJ = cartesian
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
[tool.black]
line-length = 111
py36 = true
include = '\.pyi?$'
exclude = '''
/(
\.git
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| _build
| buck-out
| build
| dist
)/
'''
**cartesian**: is a lightweight implementation of Cartesian genetic
programming with symbolic regression in mind.
|image0| |image1| |PyPI| |DOI| |Documentation Status| |Code style:
black|
--------------
It is meant to be used in conjunction with
`deap <https://github.com/DEAP/deap>`__ or
`glyph <https://github.com/Ambrosys/glyph>`__.
The basic components are provided:
- data structure
- 1+4 Algorithm
- symbolic, ephemeral random and structure-based constants
Installation
------------
cartesian is available on PyPI
``pip install cartesian``
.. |image0| image:: https://travis-ci.org/Ohjeah/cartesian.svg?branch=master
:target: https://travis-ci.org/Ohjeah/cartesian
.. |image1| image:: https://codecov.io/gh/Ohjeah/cartesian/branch/master/graph/badge.svg
:target: https://codecov.io/gh/Ohjeah/cartesian
.. |PyPI| image:: https://img.shields.io/pypi/v/cartesian.svg
:target: https://pypi.python.org/pypi/cartesian
.. |DOI| image:: https://zenodo.org/badge/79949716.svg
:target: https://zenodo.org/badge/latestdoi/79949716
.. |Documentation Status| image:: https://readthedocs.org/projects/cartesian/badge/?version=latest
:target: https://cartesian.readthedocs.io/en/latest/?badge=latest
.. |Code style: black| image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/ambv/black
+5
-2
.pytest_cache
_build
.idea
.vscode
docs/api
# Byte-compiled / optimized / DLL files

@@ -7,3 +10,3 @@ __pycache__/

*$py.class
doc
# C extensions

@@ -10,0 +13,0 @@ *.so

language: python
cache:
directories:
- $HOME/.cache/pip
- tests/.hypothesis
python:
- "3.6"
install:
- pip install -r requirements-dev.txt
- pip install --upgrade -r requirements-dev.txt
script:

@@ -7,0 +11,0 @@ - py.test

@@ -1,4 +0,4 @@

Metadata-Version: 2.1
Metadata-Version: 1.2
Name: cartesian
Version: 0.1.7
Version: 0.1.8
Summary: Minimal cartesian genetic programming for symbolic regression.

@@ -9,23 +9,39 @@ Home-page: https://github.com/ohjeah/cartesian

License: MIT
Description: **cartesian**: is a lightweight implementation of Cartesian genetic programming with symbolic regression in mind.
Description: **cartesian**: is a lightweight implementation of Cartesian genetic
programming with symbolic regression in mind.
[![](https://travis-ci.org/Ohjeah/cartesian.svg?branch=master)](https://travis-ci.org/Ohjeah/cartesian) [![](https://codecov.io/gh/Ohjeah/cartesian/branch/master/graph/badge.svg)](https://codecov.io/gh/Ohjeah/cartesian) [![PyPI](https://img.shields.io/pypi/v/cartesian.svg)](https://pypi.python.org/pypi/cartesian) [![DOI](https://zenodo.org/badge/79949716.svg)](https://zenodo.org/badge/latestdoi/79949716)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)
|image0| |image1| |PyPI| |DOI| |Documentation Status| |Code style:
black|
***
--------------
It is meant to be used in conjunction with [deap](https://github.com/DEAP/deap) or [glyph](https://github.com/Ambrosys/glyph).
It is meant to be used in conjunction with
`deap <https://github.com/DEAP/deap>`__ or
`glyph <https://github.com/Ambrosys/glyph>`__.
The basic components are provided:
- data structure
- 1+4 Algorithm
- symbolic, ephemeral random and structure-based constants
- data structure
- 1+4 Algorithm
- symbolic, ephemeral random and structure-based constants
Installation
------------
## Installation
cartesian is available on PyPI
`pip install cartesian`
``pip install cartesian``
.. |image0| image:: https://travis-ci.org/Ohjeah/cartesian.svg?branch=master
:target: https://travis-ci.org/Ohjeah/cartesian
.. |image1| image:: https://codecov.io/gh/Ohjeah/cartesian/branch/master/graph/badge.svg
:target: https://codecov.io/gh/Ohjeah/cartesian
.. |PyPI| image:: https://img.shields.io/pypi/v/cartesian.svg
:target: https://pypi.python.org/pypi/cartesian
.. |DOI| image:: https://zenodo.org/badge/79949716.svg
:target: https://zenodo.org/badge/latestdoi/79949716
.. |Documentation Status| image:: https://readthedocs.org/projects/cartesian/badge/?version=latest
:target: https://cartesian.readthedocs.io/en/latest/?badge=latest
.. |Code style: black| image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/ambv/black
Platform: UNKNOWN

@@ -36,5 +52,4 @@ Classifier: Programming Language :: Python

Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
Classifier: License :: OSI Approved :: MIT License
Classifier: Topic :: Scientific/Engineering :: Mathematics
Requires-Python: >=3.6
Description-Content-Type: text/markdown

@@ -5,1 +5,2 @@ scikit-learn[alldeps]

numpy
dataclasses

@@ -5,6 +5,8 @@ .editorconfig

.gitignore
.readthedocs.yml
.travis.yml
LICENSE
MANIFEST.in
README.md
README.rst
pyproject.toml
requirements-dev.txt

@@ -24,2 +26,7 @@ requirements.txt

cartesian.egg-info/top_level.txt
docs/Makefile
docs/conf.py
docs/index.rst
docs/_templates/hacks.html
docs/_templates/sidebarintro.html
examples/basic.py

@@ -26,0 +33,0 @@ examples/ephemeral_constant.py

@@ -7,2 +7,4 @@ from pkg_resources import get_distribution, DistributionNotFound

pass
from .sklearn_api import Symbolic
from .cgp import Primitive, Symbol, Structural, Constant, Ephemeral

@@ -7,7 +7,8 @@ import math

from scipy.optimize import OptimizeResult, minimize
from joblib import Parallel, delayed
from .cgp import Base, point_mutation, compile, to_polish, Constant
# from joblib import Parallel, delayed
from .cgp import point_mutation, compile, to_polish, Constant
def return_opt_result(f, individual):

@@ -17,5 +18,6 @@ """

:param f: `callable(individual`
:param f: callable(individual)
:param individual: instance of cartesian.cgp.Base
:type individual: instance of cartesian.cgp.Cartesian
:return: OptimizeResult

@@ -30,14 +32,6 @@ """

def oneplus(
fun,
random_state=None,
cls=None,
lambda_=4,
max_iter=100,
max_nfev=None,
f_tol=0,
n_jobs=1,
seed=None,
fun, random_state=None, cls=None, lambda_=4, max_iter=100, max_nfev=None, f_tol=0, n_jobs=1, seed=None
):
"""
1 + lambda algorithm.
"""1 + lambda algorithm.
In each generation, create lambda offspring and compare their fitness to the parent individual.

@@ -47,3 +41,3 @@ The fittest individual carries over to the next generation. In case of a draw, the offspring is prefered.

:param fun: `callable(individual)`, function to be optimized
:param fun: callable(individual), function to be optimized
:param random_state: an instance of np.random.RandomState, a seed integer or None

@@ -59,6 +53,3 @@ :param cls: The base class for individuals

:return: scipy.optimize.OptimizeResult with non-standard attributes
res.x = values for constants
res.expr = expression
res.fun = best value for the function
:return: scipy.optimize.OptimizeResult with non-standard attributes res.x = values for constants res.expr = expression res.fun = best value for the function
"""

@@ -71,5 +62,3 @@ max_iter = max_nfev if max_nfev else max_iter

nfev = best_res.nfev
res = OptimizeResult(
expr=best, x=best_res.x, fun=best_res.fun, nit=0, nfev=nfev, success=False
)
res = OptimizeResult(expr=best, x=best_res.x, fun=best_res.fun, nit=0, nfev=nfev, success=False)
if best_res.fun <= f_tol:

@@ -80,16 +69,9 @@ res["success"] = True

for i in range(1, max_iter):
offspring = [
point_mutation(best, random_state=random_state) for _ in range(lambda_)
]
offspring = [point_mutation(best, random_state=random_state) for _ in range(lambda_)]
# with Parallel(n_jobs=n_jobs) as parallel:
# offspring_fitness = parallel(delayed(return_opt_result)(fun, o) for o in offspring)
offspring_fitness = [return_opt_result(fun, o) for o in offspring]
best, best_res = min(
zip(offspring + [best], offspring_fitness + [best_res]),
key=lambda x: x[1].fun,
)
best, best_res = min(zip(offspring + [best], offspring_fitness + [best_res]), key=lambda x: x[1].fun)
nfev += sum(of.nfev for of in offspring_fitness)
res = OptimizeResult(
expr=best, x=best_res.x, fun=best_res.fun, nit=i, nfev=nfev, success=False
)
res = OptimizeResult(expr=best, x=best_res.x, fun=best_res.fun, nit=i, nfev=nfev, success=False)
if res.fun <= f_tol:

@@ -130,4 +112,3 @@ res["success"] = True

def optimize_constants(fun):
"""Wrap a measure with constant optimization.
"""
"""Wrap a measure with constant optimization."""

@@ -134,0 +115,0 @@ @wraps(fun)

@@ -6,4 +6,4 @@ import itertools

from operator import attrgetter
from collections import namedtuple
from dataclasses import dataclass
from sklearn.base import TransformerMixin

@@ -16,6 +16,5 @@ from sklearn.utils.validation import check_random_state

class Primitive(object):
"""Base class"""
def __init__(self, name, function, arity):
"""Basic build block for cartesian programs.
def __init__(self, name, function, arity):
"""
:param name: for text representation

@@ -31,69 +30,71 @@ :param function:

class Symbol(Primitive):
"""
Base class for variables.
Will always be used in the boilerplate ensuring a uniform signature, even if variable is not used in the genotype.
"""
arity = 0
def __init__(self, name):
"""Base class for variables.
def __init__(self, name):
Will always be used in the boilerplate ensuring a uniform signature.
Even if variable is not used in the genotype.
Args:
name: name of the primitive
"""
self.name = name
self.arity = 0
class Constant(Symbol):
"""
Base class for symbolic constants.
"""Base class for symbolic constants.
Will be used for constant optimization.
Boilerplate: will only appear when used.
"""
pass
class Ephemeral(Primitive):
"""
Base class for ERC's.
ERC's are terminals, but they are implemented as zero arity functions, because they do not need to appear in the
argument list of the lambda expression.
def __init__(self, name, fun):
"""Base class for ERC's.
.. Note ::
ERC's are terminals, but they are implemented as zero arity functions, as they do not need to appear in the
argument list of the lambda expression.
Compilation behaviour: Each individual has a dict to store its numeric values. Each position in the code block will
only execute the function once. Values are lost during copying.
Note:
Compilation behaviour: Each individual has a dict to store its numeric values.
Each position in the code block will only execute the function once.
Values are lost during copying.
"""
def __init__(self, name, function):
Args:
name: for text representation
fun: callback, should return a random numeric values.
"""
:param name: for text representation
:param function: callback(), should return a random numeric values.
"""
super().__init__(name, function, 0)
super().__init__(name, fun, 0)
class Structural(Primitive):
"""
Structural constants are operators which take the graph representation of its arguments
and convert it to a numeric value.
"""
def __init__(self, name, fun, arity):
"""Structural constants are operators which take the graph representation of its arguments
and convert it to a numeric value.
def __init__(self, name, function, arity):
Args:
name: for text representation
fun:
arity:
"""
:param name: for text representation
:param function:
:param arity:
"""
self.name = name
self._function = function
self._function = fun
self.arity = arity
def function(self, *args):
return self._function(* map(self.get_len, args))
return self._function(*map(self.get_len, args))
@staticmethod
def get_len(expr, tokens="(,"):
""" Get the length of a tree by parsing its polish notation representation
Args:
expr: a formula in polish notation
tokens: symbols to split the expression at
Returns:
length of expr
"""
Get the length of a tree by parsing its polish notation representation
:param expr:
:param tokens: to split at
:return: length of expr
"""
regex = "|".join("\\{}".format(t) for t in tokens)

@@ -103,36 +104,54 @@ return len(re.split(regex, expr))

PrimitiveSet = namedtuple(
"PrimitiveSet", "operators terminals max_arity mapping imapping context symbols"
)
@dataclass
class PrimitiveSet:
"""A container holding the primitives and pre-compiled helper attributes.
Args:
operators: all non-terminal primitives (arity > 0)
terminals: all terminals
max_arity: maximum arity of all terminals. Determines the number of links for each register
mapping: sorted and indexed list of the primitive set
imapping: inverse of mapping
context: links names of primitives to their functions
symbols: all sybolic constants
def create_pset(primitives):
"""Create immutable PrimitiveSet with some attributes for quick lookups"""
terminals = [p for p in primitives if p.arity == 0]
symbols = [p for p in primitives if isinstance(p, Symbol)]
non_symbols = [p for p in terminals if not isinstance(p, Symbol)]
operators = [p for p in primitives if p.arity > 0]
if operators:
max_arity = max(operators, key=attrgetter("arity")).arity
else:
max_arity = 0
mapping = {
i: prim
for i, prim in enumerate(
sorted(symbols, key=attrgetter("name")) +
sorted(non_symbols, key=attrgetter("name")) +
sorted(operators, key=attrgetter("name"))
"""
operators: list
terminals: list
mapping: dict
imapping: dict
context: dict
symbols: list
max_arity: int
@classmethod
def create(cls, primitives):
"""Create immutable PrimitiveSet with some attributes for quick lookups"""
terminals = [p for p in primitives if p.arity == 0]
symbols = [p for p in primitives if isinstance(p, Symbol)]
non_symbols = [p for p in terminals if not isinstance(p, Symbol)]
operators = [p for p in primitives if p.arity > 0]
if operators:
max_arity = max(operators, key=attrgetter("arity")).arity
else:
max_arity = 0
mapping = {
i: prim
for i, prim in enumerate(
sorted(symbols, key=attrgetter("name"))
+ sorted(non_symbols, key=attrgetter("name"))
+ sorted(operators, key=attrgetter("name"))
)
}
imapping = {v: k for k, v in mapping.items()}
context = {f.name: f.function for f in operators}
return cls(
operators=operators,
terminals=terminals,
imapping=imapping,
max_arity=max_arity,
mapping=mapping,
context=context,
symbols=symbols,
)
}
imapping = {v: k for k, v in mapping.items()}
context = {f.name: f.function for f in operators}
return PrimitiveSet(
operators=operators,
terminals=terminals,
imapping=imapping,
max_arity=max_arity,
mapping=mapping,
context=context,
symbols=symbols,
)

@@ -179,7 +198,6 @@

class Base(TransformerMixin):
def __init__(self, code, outputs):
self.n_inputs = len(self.pset.terminals)
self.inputs = list(range(self.n_inputs))
self.symbols = self.inputs[:len(self.pset.symbols)]
self.symbols = self.inputs[: len(self.pset.symbols)]
self.code = code

@@ -192,6 +210,4 @@ self.outputs = outputs

def mapping(self):
return {
i: (el, c, r, l)
for i, el, c, r, l in _make_map(self.inputs, * self.code, self.outputs)
}
"""Helper dictionary to index the cartesian registers."""
return {i: (el, c, r, l) for i, el, c, r, l in _make_map(self.inputs, *self.code, self.outputs)}

@@ -202,6 +218,7 @@ def __getitem__(self, index):

def __setitem__(self, index, item):
el, c, r, l = self.mapping[index]
l[r] = item
el, c, r, lst = self.mapping[index]
lst[r] = item
def __len__(self):
"""Returs the number of registers in self."""
return self.n_columns * self.n_rows + self.n_out + self.n_inputs

@@ -228,3 +245,4 @@

def format(self, x):
@staticmethod
def format(x):
return "{}".format(x)

@@ -238,10 +256,16 @@

def transform(self, x, y=None):
return self._transform(* x.T)
return self._transform(*x.T)
@classmethod
def create(cls, random_state=None):
"""
"""Creates a new individual.
Each gene is picked with a uniform distribution from all allowed inputs or functions.
:param random_state: an instance of np.random.RandomState, a seed integer or None
:return: A random new class instance.
Args:
random_state: an instance of np.random.RandomState, a seed integer or None
Returns:
a new (random) individual
"""

@@ -263,5 +287,3 @@ random_state = check_random_state(random_state)

outputs = [
random_state.choice(
cls._valid_inputs[_out_index(cls.n_rows, cls.n_columns, n_in, o)]
)
random_state.choice(cls._valid_inputs[_out_index(cls.n_rows, cls.n_columns, n_in, o)])
for o in range(cls.n_out)

@@ -273,10 +295,6 @@ ]

class Cartesian(type):
"""
Meta class to set class parameters and primitive set.
"""
"""Meta class to set class parameters and primitive set."""
def __new__(mcs, name, primitive_set, n_columns=3, n_rows=1, n_back=1, n_out=1):
valid_inputs = _get_valid_inputs(
n_rows, n_columns, n_back, len(primitive_set.terminals), n_out
)
valid_inputs = _get_valid_inputs(n_rows, n_columns, n_back, len(primitive_set.terminals), n_out)
dct = dict(

@@ -295,5 +313,3 @@ pset=primitive_set,

def __init__(cls, name, primitive_set, n_columns=3, n_rows=1, n_back=1, n_out=1):
valid_inputs = _get_valid_inputs(
n_rows, n_columns, n_back, len(primitive_set.terminals), n_out
)
valid_inputs = _get_valid_inputs(n_rows, n_columns, n_back, len(primitive_set.terminals), n_out)
dct = dict(

@@ -311,10 +327,14 @@ pset=primitive_set,

def point_mutation(individual, random_state=None):
"""Picks a gene at random and mutates it.
The mutation is either rewiring, i.e. changing the inputs, or changing the operator (head of gene).
Args:
individual: instance of Base
random_state: an instance of np.random.RandomState, a seed integer or None
Returns:
mutated individual
"""
Randomly pick a gene in individual and mutate it.
The mutation is either rewiring, i.e. changing the inputs, or changing the operator (head of gene)
:param individual: instance of Base
:type individual: instance of Cartesian
:param random_state: an instance of np.random.RandomState, a seed integer or None
:return: new instance of Base
"""
random_state = check_random_state(random_state)

@@ -329,5 +349,3 @@ n_terminals = len(individual.pset.terminals)

if j == 0: # function
new_j = individual.pset.imapping[
random_state.choice(individual.pset.operators)
]
new_j = individual.pset.imapping[random_state.choice(individual.pset.operators)]
else: # input

@@ -344,14 +362,16 @@ new_j = random_state.choice(individual._valid_inputs[i])

def to_polish(c, return_args=True):
"""
Return polish notation of expression encoded by c.
Optionally return the used arguments.
"""Generates the polish notation of expression encoded by c.
Resolve the outputs recursively.
Resolves the outputs recursively.
.. Note ::
Note:
Function has side-effects on the individual c.
See Symbols for details
:param c: instance of Base
:type c: instance of Cartesian
Args:
c: instance of base
return_args: optionally return the used arguments too
Returns:
polish notation of expression encoded by c
"""

@@ -380,12 +400,7 @@ primitives = c.pset.mapping

elif isinstance(primitive, Structural):
return c.format(
primitive.function(
* [h(a) for a, _ in zip(gene, range(primitive.arity))]
)
)
return c.format(primitive.function(*[h(a) for a, _ in zip(gene, range(primitive.arity))]))
else:
return "{}({})".format(
primitive.name,
", ".join(h(a) for a, _ in zip(gene, range(primitive.arity))),
primitive.name, ", ".join(h(a) for a, _ in zip(gene, range(primitive.arity)))
)

@@ -401,5 +416,4 @@

def boilerplate(c, used_arguments=()):
"""
Return the overhead needed to compile the polish notation.
def _boilerplate(c, used_arguments=()):
"""Generates the overhead needed to compile the polish notation.

@@ -409,5 +423,8 @@ If used_arguments are provided, the boilerplate will only include

:param c: instance of Base
:type c: instance of Cartesian
:param used_arguments: list of terminals actually used in c.
Args:
c: instance of Base
used_arguments: list of terminals actually used in c.
Returns: overhead needed to compile the polish notation.
"""

@@ -426,7 +443,10 @@ mapping = c.pset.mapping

def compile(c):
"""Transform an individual into a lambda function
Args:
c: instance of Base
Returns:lambda function
"""
:param c: instance of Base
:type c: instance of Cartesian
:return: lambda function
"""
polish, args = to_polish(c, return_args=True)

@@ -436,4 +456,4 @@ for t in c.pset.symbols:

args.add(t)
bp = boilerplate(c, used_arguments=args)
bp = _boilerplate(c, used_arguments=args)
code = "({})".format(", ".join(polish)) if len(polish) > 1 else polish[0]
return eval(bp + code, c.pset.context)

@@ -6,3 +6,3 @@ import numpy as np

from .cgp import create_pset, Symbol, Primitive, Constant, compile, Cartesian
from .cgp import PrimitiveSet, Symbol, Primitive, Constant, compile, Cartesian
from .algorithm import oneplus, optimize

@@ -18,9 +18,9 @@

except:
except (AttributeError, TypeError, IndexError):
return np.ones(shape) * yhat
class evaluate: # ugly construct s.th. you can pickle it and use joblib
class _Evaluate: # ugly construct s.th. you can pickle it and use joblib
def __init__(self, x, y, metric):
"""Wraps metric for optimization"""
self.n_samples, *out = y.shape

@@ -34,7 +34,5 @@ self.multi_output = True if out else False

if self.multi_output:
yhat = np.array(
[_ensure_1d(i, self.n_samples) for i in f(* self.x.T, *consts)]
).T
yhat = np.array([_ensure_1d(i, self.n_samples) for i in f(*self.x.T, *consts)]).T
else:
yhat = _ensure_1d(f(* self.x.T, *consts), self.n_samples)
yhat = _ensure_1d(f(*self.x.T, *consts), self.n_samples)
return self.metric(self.y, yhat)

@@ -47,4 +45,2 @@

class Symbolic(BaseEstimator, RegressorMixin):
"""Wraps the 1 + lambda algorithm in sklearn api"""
def __init__(

@@ -61,25 +57,28 @@ self,

f_tol=0,
seed=None,
seeded_individual=None,
random_state=None,
n_jobs=1,
metric=mean_squared_error,
metric=None,
):
"""Wraps the 1 + lambda algorithm in sklearn api.
Note:
n_costs provides a convenience method to create Symbols.
All constants can be directly passed via the operators.
Args:
operators: list of primitives
n_const: number of symbolic constants
n_rows: number of rows in the code block
n_columns: number of columns in the code block
n_back: number of rows to look back for connections
max_iter: maximum number of generations
max_nfev: maximum number of function evaluations. Important, if fun is another optimizer
lambda_: number of offspring per generation
f_tol: Absolute error in metric(ind) between iterations that is acceptable for convergence
seed: an individual used to hot-start the optimization
random_state: an instance of np.random.RandomState, an integer used as seed, or None
n_jobs: number of jobs for joblib embarrassingly easy parallel
metric: callable(individual), function to be optimized
"""
:param operators: list of primitive excluding terminals
:param n_const: number of symbolic constants
:param n_rows: number of rows in the code block
:param n_columns: number of columns in the code block
:param n_back: number of rows to look back for connections
:param metric: what to optimize for
:param fun: `callable(individual)`, function to be optimized
:param random_state: an instance of np.random.RandomState, a seed integer or None
:param cls: The base class for individuals
:type cls: (optional) instance of cartesian.cgp.Cartesian
:param seed: (optional) can be passed instead of cls.
:param lambda_: number of offspring per generation
:param max_iter: maximum number of generations
:param max_nfev: maximum number of function evaluations. Important, if fun is another optimizer
:param f_tol: threshold for precision
:param n_jobs: number of jobs for joblib embarrassingly easy parallel
"""
self.operators = DEFAULT_PRIMITIVES or operators

@@ -99,8 +98,17 @@ self.constants = [Constant("c_{}".format(i)) for i in range(n_const)]

self.f_tol = f_tol
self.metric = metric
self.metric = metric if metric is not None else mean_squared_error
self.random_state = check_random_state(random_state)
self.n_jobs = n_jobs
self.seed = seed
self.seeded_individual = seeded_individual
def fit(self, x, y):
"""Trains the model given the regression task.
Args:
x (np.ndarray): input data matrix for fitting of size (number_of_input_points, number_of_features)
y (np.ndarray): target data vector for fitting of size (number_of_input_points)
Returns: self
"""
x = check_array(x)

@@ -110,3 +118,3 @@ _, self.n_out = y.reshape(y.shape[0], -1).shape

terminals = [Symbol("x_{}".format(i)) for i in range(n_features)]
self.pset = create_pset(self.operators + terminals + self.constants)
self.pset = PrimitiveSet.create(self.operators + terminals + self.constants)
cls = Cartesian(

@@ -121,3 +129,3 @@ str(hash(self)),

self.res = oneplus(
evaluate(x, y, self.metric),
_Evaluate(x, y, self.metric),
random_state=self.random_state,

@@ -130,3 +138,3 @@ cls=cls,

n_jobs=self.n_jobs,
seed=self.seed,
seed=self.seeded_individual,
)

@@ -137,8 +145,14 @@ self.model = compile(self.res.expr)

def predict(self, x):
"""Use the fitted model f to make a prediction.
Args:
x: input data matrix for scoring
Returns: predicted target data vector
"""
if self.n_out > 1:
yhat = np.array(
[_ensure_1d(i, x.shape[0]) for i in self.model(* x.T, * self.res.x)]
).T
yhat = np.array([_ensure_1d(i, x.shape[0]) for i in self.model(*x.T, *self.res.x)]).T
else:
yhat = _ensure_1d(self.model(* x.T, * self.res.x), x.shape[0])
yhat = _ensure_1d(self.model(*x.T, *self.res.x), x.shape[0])
return yhat
def make_it(x):
"""
Ensure that x is an iterator.
"""Ensures that x is an iterator.
If x is not iterable, wrap it as a one-elemened tuple.

@@ -10,3 +10,3 @@ """

except TypeError:
x = x,
x = (x,)
return iter(x)

@@ -13,3 +13,3 @@ import numpy as np

]
pset = create_pset(primitives)
pset = PrimitiveSet.create(primitives)
rng = check_random_state(42)

@@ -16,0 +16,0 @@ x = rng.normal(size=(100, 2))

@@ -15,3 +15,3 @@ import numpy as np

]
pset = create_pset(primitives)
pset = PrimitiveSet.create(primitives)
x = rng.normal(size=(100, 2))

@@ -18,0 +18,0 @@ y = x[:, 1] * x[:, 0] + 0.3

@@ -15,3 +15,3 @@ import numpy as np

]
pset = create_pset(primitives)
pset = PrimitiveSet.create(primitives)
x = rng.normal(size=(100, 2))

@@ -18,0 +18,0 @@ y = x[:, 1] * x[:, 0] + 0.3

@@ -15,3 +15,3 @@ import numpy as np

]
pset = create_pset(primitives)
pset = PrimitiveSet.create(primitives)
rng = check_random_state(42)

@@ -18,0 +18,0 @@ x = rng.normal(size=(100, 2))

+30
-15

@@ -1,4 +0,4 @@

Metadata-Version: 2.1
Metadata-Version: 1.2
Name: cartesian
Version: 0.1.7
Version: 0.1.8
Summary: Minimal cartesian genetic programming for symbolic regression.

@@ -9,23 +9,39 @@ Home-page: https://github.com/ohjeah/cartesian

License: MIT
Description: **cartesian**: is a lightweight implementation of Cartesian genetic programming with symbolic regression in mind.
Description: **cartesian**: is a lightweight implementation of Cartesian genetic
programming with symbolic regression in mind.
[![](https://travis-ci.org/Ohjeah/cartesian.svg?branch=master)](https://travis-ci.org/Ohjeah/cartesian) [![](https://codecov.io/gh/Ohjeah/cartesian/branch/master/graph/badge.svg)](https://codecov.io/gh/Ohjeah/cartesian) [![PyPI](https://img.shields.io/pypi/v/cartesian.svg)](https://pypi.python.org/pypi/cartesian) [![DOI](https://zenodo.org/badge/79949716.svg)](https://zenodo.org/badge/latestdoi/79949716)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)
|image0| |image1| |PyPI| |DOI| |Documentation Status| |Code style:
black|
***
--------------
It is meant to be used in conjunction with [deap](https://github.com/DEAP/deap) or [glyph](https://github.com/Ambrosys/glyph).
It is meant to be used in conjunction with
`deap <https://github.com/DEAP/deap>`__ or
`glyph <https://github.com/Ambrosys/glyph>`__.
The basic components are provided:
- data structure
- 1+4 Algorithm
- symbolic, ephemeral random and structure-based constants
- data structure
- 1+4 Algorithm
- symbolic, ephemeral random and structure-based constants
Installation
------------
## Installation
cartesian is available on PyPI
`pip install cartesian`
``pip install cartesian``
.. |image0| image:: https://travis-ci.org/Ohjeah/cartesian.svg?branch=master
:target: https://travis-ci.org/Ohjeah/cartesian
.. |image1| image:: https://codecov.io/gh/Ohjeah/cartesian/branch/master/graph/badge.svg
:target: https://codecov.io/gh/Ohjeah/cartesian
.. |PyPI| image:: https://img.shields.io/pypi/v/cartesian.svg
:target: https://pypi.python.org/pypi/cartesian
.. |DOI| image:: https://zenodo.org/badge/79949716.svg
:target: https://zenodo.org/badge/latestdoi/79949716
.. |Documentation Status| image:: https://readthedocs.org/projects/cartesian/badge/?version=latest
:target: https://cartesian.readthedocs.io/en/latest/?badge=latest
.. |Code style: black| image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/ambv/black
Platform: UNKNOWN

@@ -36,5 +52,4 @@ Classifier: Programming Language :: Python

Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
Classifier: License :: OSI Approved :: MIT License
Classifier: Topic :: Scientific/Engineering :: Mathematics
Requires-Python: >=3.6
Description-Content-Type: text/markdown

@@ -9,2 +9,6 @@ -e .

twine>=1.11.0rc1
setuptools>=38.6.0
setuptools>=38.6.0
sphinx
#alabaster
sphinx_rtd_theme
sphinxcontrib-apidoc

@@ -5,1 +5,2 @@ scikit-learn[alldeps]

numpy
dataclasses

@@ -17,3 +17,3 @@ from pathlib import Path

"Intended Audience :: Science/Research",
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
"License :: OSI Approved :: MIT License",
"Topic :: Scientific/Engineering :: Mathematics",

@@ -23,3 +23,3 @@ ]

REQUIRED = f.readlines()
with open(CURRENT_DIR / "README.md", "r", encoding="utf8") as f:
with open(CURRENT_DIR / "README.rst", "r", encoding="utf8") as f:
LONG_DESCRIPTION = f.read()

@@ -30,3 +30,2 @@ setup(

long_description=LONG_DESCRIPTION,
long_description_content_type="text/markdown",
author=AUTHOR,

@@ -33,0 +32,0 @@ author_email=EMAIL,

@@ -12,3 +12,3 @@ import operator

operators = [Primitive("neg", operator.neg, 1)]
pset = create_pset(terminals + operators)
pset = PrimitiveSet.create(terminals + operators)
return pset

@@ -15,0 +15,0 @@

@@ -12,7 +12,7 @@ from sklearn.utils.validation import check_random_state

res = oneplus(fun, random_state=rng, lambda_=4, max_iter=2, f_tol=-1, cls=cls)
assert res.success == False
assert not res.success
res = oneplus(fun, random_state=rng, lambda_=4, max_iter=0, f_tol=0, cls=cls)
assert res.success == True
assert res.success
res = oneplus(fun, random_state=rng, lambda_=4, max_nfev=1, f_tol=-1, cls=cls)
assert res.success == False
assert not res.success

@@ -27,3 +27,3 @@

def fun(f, consts=()):
return np.sum((y - f(* x.T, *consts)))
return np.sum((y - f(*x.T, *consts)))

@@ -43,5 +43,5 @@ res = oneplus(fun, seed=individual)

def fun(f, consts=()):
return np.sum((f(* x.T, consts)) ** 2)
return np.sum((f(*x.T, consts)) ** 2)
res = fun(ind)
assert res.x < 1e-6

@@ -10,3 +10,3 @@ import operator

from cartesian.cgp import *
from cartesian.cgp import _get_valid_inputs
from cartesian.cgp import _get_valid_inputs, _boilerplate

@@ -49,6 +49,4 @@

def test_boilerplate(individual):
assert boilerplate(individual) == "lambda x_0, x_1, c:"
assert boilerplate(
individual, used_arguments=[individual.pset.terminals[0]]
) == "lambda x_0:"
assert _boilerplate(individual) == "lambda x_0, x_1, c:"
assert _boilerplate(individual, used_arguments=[individual.pset.terminals[0]]) == "lambda x_0:"

@@ -100,3 +98,3 @@

operators = [Ephemeral("c", random.random)]
pset = create_pset(terminals + operators)
pset = PrimitiveSet.create(terminals + operators)
MyClass = Cartesian("MyClass", pset)

@@ -118,3 +116,3 @@ ind1 = MyClass([[2, 0]], [2])

primitives = [Symbol("x_0"), sc]
pset = create_pset(primitives)
pset = PrimitiveSet.create(primitives)
MyClass = Cartesian("MyClass", pset)

@@ -121,0 +119,0 @@ ind = MyClass([[[1, 0, 0]], [[1, 0, 0]], [[1, 0, 0]]], [2])

**cartesian**: is a lightweight implementation of Cartesian genetic programming with symbolic regression in mind.
[![](https://travis-ci.org/Ohjeah/cartesian.svg?branch=master)](https://travis-ci.org/Ohjeah/cartesian) [![](https://codecov.io/gh/Ohjeah/cartesian/branch/master/graph/badge.svg)](https://codecov.io/gh/Ohjeah/cartesian) [![PyPI](https://img.shields.io/pypi/v/cartesian.svg)](https://pypi.python.org/pypi/cartesian) [![DOI](https://zenodo.org/badge/79949716.svg)](https://zenodo.org/badge/latestdoi/79949716)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)
***
It is meant to be used in conjunction with [deap](https://github.com/DEAP/deap) or [glyph](https://github.com/Ambrosys/glyph).
The basic components are provided:
- data structure
- 1+4 Algorithm
- symbolic, ephemeral random and structure-based constants
## Installation
cartesian is available on PyPI
`pip install cartesian`