# What is archery?¶

It is set of Mixins to use on MutableMapping giving the following features :

• Linear Algebrae;
• Vector like metrics;
• Searchable behaviour;

for convenience 3 concrete classes are provided :

• mdict (dict that follow the rules of linear algebrae based on dict);
• vdict (dict that have cos, abs, dot product);
• sdict (dict that are easily searchable);

following this inheritance graph of traits

# Basic Usage¶

Using the ready to use class derived from dict

## mdict¶

dict that supports consistently all the linear algebrae properties

Basically : dict that are vectors on arbitrary basis (recursively).

ex:

```>>> from archery import mdict
>>> point = mdict(x=1, y=1, z=1)
>>> point2 = mdict(x=1, y=-1)
>>> print( (2 * point + point2)/4)
>>> # OUT : {'y': 0.25, 'x': 0.75, 'z': 0.5}
>>> print(point - point2)
>>> # OUT : {'y': 2, 'x': 0, 'z': 1}
>>> b=mdict(x=2, z=-1)
>>> a=mdict(x=1, y=2.0)
>>> a+b
>>> # OUT: {'y': 2.0, 'x': 3, 'z': -1}
>>> b-a
>>> # OUT: {'y': -2.0, 'x': 1, 'z': -1}
>>> -(a-b)
>>> # OUT: {'y': -2.0, 'x': 1, 'z': -1}
>>> a+1
>>> # OUT: {'y': 3.0, 'x': 2}
>>> -1-a
>>> # OUT: {'y': -3.0, 'x': -2}
>>> a*b
>>> # OUT: {'x': 2}
>>> a/b
>>> # OUT: {'x': 0}
>>> 1.0*a/b
>>> # OUT: {'x': 0.5}
```

## vdict¶

dict that defines abs(), dot(), cos() in the euclidean meaning

ex::
```>>> from archery import vdict as Point
>>>
>>> u = Point(x=1, y=1)
>>> v = Point(x=1, y=0)
>>> u.cos(v)
>>> 0.7071067811865475
>>> u.dot(v)
>>> # OUT: 1
>>> u.cos(2*v)
>>> # OUT: 0.7071067811865475
>>> u.dot(2*v)
>>> #OUT: 2
>>> abs(u)
>>> #OUT: 1.4142135623730951
>>> u3 = Point(x=1, y=1, z=2)
>>> u4 = Point(x=1, y=3, z=4)
>>> u3 + u4
>>> #OUT: dict(x=2, y=4, z=6)
>>> assert u4 + u4 == 2*u4
>>> from archery import vdict
>>> from math import acos, pi
>>> point = vdict(x=1, y=1, z=1)
>>> point2 = vdict(x=1, y=-1)
>>> point2 = mdict(x=1, y=-1)
>>> print( (2 * point + point2)/4)
>>> # OUT : {'y': 0.25, 'x': 0.75, 'z': 0.5}
>>> print(acos(vdict(x=1,y=0).cos(vdict(x=1, y=1)))*360/2/pi)
>>> # OUT : 45.0
>>> print(abs(vdict(x=1, y=1)))
>>> # OUT : 1.41421356237
>>> print(vdict(x=1,y=0,z=3).dot(vdict(x=1, y=1, z=-1)))
>>> #OUT -2
```

## sdict¶

dict made for searching value/keys/Path with special interests.

Basically, it returns an iterator in the form of a tuple being all the keys and the value. It is a neat trick, if you combine it with make_from_path, it helps select exactly what you want in a dict:

```>>> from archery import sdict, make_from_path
>>> tree = sdict(
...      a = 1,
...      b = dict(
...          c = 3.0,
...          d = dict(e=True)
...      ),
...      point = dict( x=1, y=1, z=0),
... )
>>> list(tree.leaf_search(lambda x: type(x) is float ))
>>> #Out: [3.0]
>>> res = list(tree.search(lambda x: ("point") in x ))
>>> ## equivalent to list(tree.search(lambda x: Path(x).contains("point")))
>>> print(res)
>>> #Out: [('point', 'y', 1), ('point', 'x', 1), ('point', 'z', 0)]
>>> sum([ make_from_path(mdict, r) for r in  res])
>>> #Out:  {'point': {'x': 1, 'y': 1, 'z': 0}}
```

This library is a proof of the consistent use of Mixins on MutableMapping gives the property seen in the basic usage.

The Mixins do not require any specifics regarding the implementation and should work if I did my job properly with any kinds of MutableMapping.

Here is an example of a cosine similarities out of the box on the Collections.Counter

```>>> from collections import Counter
>>> from archery import VectorDict
>>> class CWCos(VectorDict, Counter):
...     pass
>>>
>>> CWCos(["mot", "wut", "wut", "bla"]).cos(CWCos(["mot","wut", "bla"]))
>>> # OUT: 0.942809041582
```

You can also inherit LinearAlgebrae

# API¶

## VectorDict / vdict¶

class `archery.trait.``Vector`
`__abs__`()

return the absolute value (hence >=0) aka the distance from origin as defined in Euclidean geometry. Keys of the dict are the dimension, values are the metrics https://en.wikipedia.org/wiki/Euclidean_distance

`cos`(v)

returns the cosine similarity of 2 mutable mappings (recursive) https://en.wikipedia.org/wiki/Cosine_similarity dict().cos(dict(x=….)) will logically yield division by 0 exception. http://math.stackexchange.com/a/932454

`dot`(v)

scalar product of two MappableMappings (recursive) https://en.wikipedia.org/wiki/Dot_product

## Searchable, sdict¶

class `archery.trait.``Searchable`

Return a generator all all values matching the predicates

`search`(predicate)

Return a generator of all tuples made of : - all keys leading to a value - and the value itself that match the predicate on the Path

## Path¶

Basically a class meant for making search in sdict more readable so that you have shortcuts that are more meaningfull than manipulating a tuple

class `archery.``Path`
`contains`(*a_tuple)

checks if the serie of keys is contained in a path

```>>> p = Path( [ 'a', 'b', 'c', 'd' ] )
>>> p.contains( 'b', 'c' )
>>> True
```
`endswith`(*a_tuple)

check if path ends with the consecutive given has argumenbts value

```>>> p = Path( [ 'a', 'b', 'c' ] )
>>> p.endswith( 'b', 'c' )
>>> True
>>> p.endswith( 'c', 'b' )
>>> False
```
`key`()

function provided for code readability: - returns all the keys in the Path

`startswith`(*a_tuple)

checks if a path starts with the value

```>>> p = Path( [ 'a', 'b', 'c', 'd' ] )
>>> p.startswith( 'a', 'b' )
>>> True
```
`value`()

function provided for code readability: - returns the left most value of the Path aka the value

## make_from_path¶

Making dict great vectors!

`archery.``make_from_path`(type_of_mapping, path)

Work in Progress create a mutable mapping from a Path (tuple made of a series of keys in a dict leading to a value followed by a value). The source is used a mapping factory and is reset in the process

```>>> make_from_path(dict, ("y", "z", 2))
>>> #Out[2]: {'y': {'z': 2}}
```

## mapping_row_iter¶

Making dict great vectors!

`archery.``mapping_row_iter`(tree, path=<object object>)

iterator on a tree that yield an iterator on a mapping in the form of a list of ordered key that leads to the element and the value

```>>> from archery import mapping_row_iter
>>> [ x for x in mapping_row_iter({
...        "john" : {'math':10.0, 'sport':1.0},~
...        "lily" : { 'math':20, 'sport':15.0}
...    })]
>>> #[['john', 'sport', 1.0], ['john', 'math', 10.0],~
>>> #['lily', 'sport', 15.0], ['lily', 'math', 20]]
```

Contents: