Package: python-moa
Mathematics of Arrays (MOA)MOA is a mathematically rigorous approach to dealing with arrays that
was developed byLenore
Mullins. MOA is guided
by the following principles.Everything is an array and has a shape. Scalars. Vectors. NDArray.What is the shape of the computation at each step of the calculation?Answering this guarentees no out of bounds indexing and a valid
running program.What are the indicies and operations required to produce a given
index in the result?Once we have solved this step we have a minimal representation of the
computation that has theChurch
Rosserproperty. Allowing us to truely compare algorithms, analyze
algorithms, and finally map to algorithm to a low level
implementation. For further questions see thedocumentation. The
documentation provides the theory, implementation details, and a
guide.Important questions that will guide development:Is a simple implementation of moa possible with only knowing the dimension?Can we represent complex operations and einsum math: requires+red, transpose?What is the interface for arrays? (shape, indexing function)How does one wrap pre-existing numerical routines?Installationpipinstallpython-moaDocumentationDocumentation is available onpython-moa.readthedocs.org. The
documentation provides the theory, implementation details, and a
guide for development and usage ofpython-moa.ExampleA few well maintained jupyter notebooks are available for
experimentation withbinderPython Frontend AST Generationfrommoa.frontendimportLazyArrayA=LazyArray(name='A',shape=(2,3))B=LazyArray(name='B',shape=(2,3))expression=((A+B).T)[0]expression.visualize(as_text=True)psi(Ψ)
├── Array _a2: <1> (0)
└── transpose(Ø)
    └── +
        ├── Array A: <2 3>
        └── Array B: <2 3>Shape Calculationexpression.visualize(stage='shape',as_text=True)psi(Ψ): <2>
├── Array _a2: <1> (0)
└── transpose(Ø): <3 2>
    └── +: <2 3>
        ├── Array A: <2 3>
        └── Array B: <2 3>Reduction to DNFexpression.visualize(stage='dnf',as_text=True)+: <2>
├── psi(Ψ): <2>
│   ├── Array _a6: <2> (_i3 0)
│   └── Array A: <2 3>
└── psi(Ψ): <2>
    ├── Array _a6: <2> (_i3 0)
    └── Array B: <2 3>Reduction to ONFexpression.visualize(stage='onf',as_text=True)function: <2> (A B) -> _a17
├── if (not ((len(B.shape) == 2) and (len(A.shape) == 2)))
│   └── error arguments have invalid dimension
├── if (not ((3 == B.shape[1]) and ((2 == B.shape[0]) and ((3 == A.shape[1]) and (2 == A.shape[0])))))
│   └── error arguments have invalid shape
├── initialize: <2> _a17
└── loop: <2> _i3
    └── assign: <2>
        ├── psi(Ψ): <2>
        │   ├── Array _a18: <1> (_i3)
        │   └── Array _a17: <2>
        └── +: <2>
            ├── psi(Ψ): <2>
            │   ├── Array _a6: <2> (_i3 0)
            │   └── Array A: <2 3>
            └── psi(Ψ): <2>
                ├── Array _a6: <2> (_i3 0)
                └── Array B: <2 3>Generate Python Sourceprint(expression.compile(backend='python',use_numba=True))@numba.jitdeff(A,B):if(not((len(B.shape)==2)and(len(A.shape)==2))):raiseException('arguments have invalid dimension')if(not((3==B.shape[1])and((2==B.shape[0])and((3==A.shape[1])and(2==A.shape[0]))))):raiseException('arguments have invalid shape')_a17=numpy.zeros((2,))for_i3inrange(0,2):_a17[(_i3,)]=(A[(_i3,0)]+B[(_i3,0)])return_a17DevelopmentDownloadnix. No other
dependencies and all builds will be identical on Linux and OSX.Demoingjupyterenvironmentnix-shell dev.nix -A jupyter-shellipythonenvironmentnix-shell dev.nix -A ipython-shellTestingnix-build dev.nix -A python-moaTo include benchmarks (numba, numpy, pytorch, tensorflow)nix-build dev.nix -A python-moa --arg benchmark trueDocumentationnix-build dev.nix -A docs
firefox result/index.htmlDockernix-build moa.nix -A docker
docker load < resultDevelopment PhilosophyThis is a proof of concept which should be guided by assumptions and
goals.Assumes that dimension is each operation is known. This condition
with not much work can be relaxed to knowing an upper bound.The MOA compiler is designed to be modular with clear separations:
parsing, shape calculation, dnf reduction, onf reduction, and code
generation.All code is written with the idea that the logic can ported to any
low level language (C for example). This means no object oriented
design and using simple data structures. Dictionaries should be the
highest level data structure used.Performance is not a huge concern instead readability should be
preferred. The goal of this code is to serve as documentation for
beginners in MOA. Remember that tests are often great forms of
documentation as well.Runtime dependencies should be avoided. Testing (pytest, hypothesis)
and Visualization (graphviz) are examples of suitable exceptions.ContributingContributions are welcome! For bug reports or requests please submit an issue.AuthorsThe original author isChristopher
Ostrouchov. The funding that made this
project possible came fromQuansight
LLC.