Cadabra
Computer algebra system for field theory problems
|
Python wrapper around the C++ core module.
This wrapper makes the entire functionality of Cadabra accessible from Python. This consists of two parts. One is core/cadabra2_defaults.py, which is a pure-python file. It contains the display function to show Cadabra objects to the user in a UI-independent way (e.g. switching between a text representation on the command line and a LaTeX representation when running in a notebook). The other part are the various files in core/pythoncdb, which build the cadabra2 module for python, to be imported with 'from cadabra2 import *'.
The Python module has functionality to import Cadabra notebooks using standard Python import syntax. This functionality is part of the Notebooks and packages module and described there.
Files | |
file | cadabra2_defaults.py |
Cadabra2 pure Python functionality. | |
Functions | |
void | pull_in (std::shared_ptr< cadabra::Ex > ex, cadabra::Kernel *) |
Replace any objects of the form '@(...)' in the expression tree by the python expression '...' if it exists. More... | |
void | run_python_functions (std::shared_ptr< cadabra::Ex > ex, cadabra::Kernel *) |
Run all functions in the given expression which are available in the Python scope. More... | |
template<class Algo > | |
Ex_ptr | cadabra::apply_algo_base (Algo &algo, Ex_ptr ex, bool deep, bool repeat, unsigned int depth, bool pre_order=false) |
Generic internal entry point for the Python side to execute a C++ algorithm. More... | |
template<class Algo , typename... Args, typename... PyArgs> | |
void | cadabra::def_algo (pybind11::module &m, const char *name, bool deep, bool repeat, unsigned int depth, PyArgs... pyargs) |
Method to declare a Python function with variable number of arguments, and make that call a C++ algorithm as specified in the Algo template parameter. More... | |
template<class Algo , typename... Args, typename... PyArgs> | |
void | cadabra::def_algo_preorder (pybind11::module &m, const char *name, bool deep, bool repeat, unsigned int depth, PyArgs... pyargs) |
Method to declare a Python function with variable number of arguments, and make that call a C++ algorithm as specified in the Algo template parameter. More... | |
bool | cadabra::Ex_compare (Ex_ptr, Ex_ptr) |
Comparison operator for Ex objects in Python. More... | |
Ex_ptr | cadabra::Ex_add (const Ex_ptr ex1, const ExNode ex2) |
Add two expressions, adding a top-level '\sum' node if required. More... | |
Ex_ptr | cadabra::Ex_mul (const Ex_ptr ex1, const Ex_ptr ex2) |
Multiply two expressions, adding a top-level '\prod' node if required. More... | |
Ex_ptr | cadabra::Ex_sub (const Ex_ptr ex1, const ExNode ex2) |
Subtract two expressions, adding a top-level '\sum' node if required. More... | |
Ex_ptr | cadabra::fetch_from_python (const std::string &nm) |
Fetch an Ex object from the Python side using its Python identifier. More... | |
std::string | cadabra::Ex_as_str (Ex_ptr) |
Generate the Python str() and repr() representation of the Ex object. More... | |
std::string | cadabra::Ex_as_latex (Ex_ptr) |
The Python 'print' function always calls the 'str' member on objects to be printed. More... | |
Kernel * | cadabra::create_scope () |
Setup of kernels in current scope, callable from Python. More... | |
Kernel * | cadabra::get_kernel_from_scope () |
Get a pointer to the currently visible kernel. More... | |
Ex_ptr cadabra::apply_algo_base | ( | Algo & | algo, |
Ex_ptr | ex, | ||
bool | deep, | ||
bool | repeat, | ||
unsigned int | depth, | ||
bool | pre_order = false |
||
) |
Generic internal entry point for the Python side to execute a C++ algorithm.
This gets called by the various apply_algo functions below, which in turn get called by the def_algo functions.
Kernel * cadabra::create_scope | ( | ) |
Setup of kernels in current scope, callable from Python.
When the decision was made to graft Cadabra onto Python, a choice had to be made about how Python variable scope would influence the visibility of Cadabra properties. It clearly makes sense to be able to declare properties which only hold inside a particular function. However Cadabra expressions and properties do not directly correspond to Python objects. Rather, declaring a property is more like a function call into the Cadabra module, which leaves its imprint on the state of the C++ part but does not change anything on the Python side, as you typically do not assign the created property to a Python symbol. Therefore, properties do not naturally inherit Python's scoping rules (this is different from e.g.~SymPy, in which mathematical objects are always in one-to-one correspondence with a Python object). A more fundamental problem is that properties can be attached to patterns, and those patterns can involve more than just the symbols which one passes into a function.
In order to not burden the user, properties are therefore by default global variables, stored in a single global Cadabra object __cdbkernel__
which is initialised at import of the Cadabra module. If you add new properties inside a function scope, these will go into this already existing global property list by default. If you want to create a local scope for your computations, create a new __cdbkernel__
as in
Now computations will not see the global properties at all. If you want to import the global properties, use instead
It is crucial that the __cdbkernel__
symbol is referenced from within Python and visible to the bytecompiler, because it is not possible to create new variables on the local stack at runtime. Internally, the second version above fetches, at runtime, the __cdbkernel__
from the globals stack, copies all properties in there into a new kernel, and returns the latter.
Both versions above do populate the newly created kernel with Cadabra's default properties. If you want a completely clean slate (for e.g.~testing purposes, or because you really do not want default rules for sums and products), use
Note that in all these cases, changes to properties remain local and do not leak into the global property list.
All Cadabra algorithms, when called from Python, will first look for a kernel on the locals stack (i.e.~what locals()
produces). If there is no kernel available locally, they will then revert to using the global kernel.
void cadabra::def_algo | ( | pybind11::module & | m, |
const char * | name, | ||
bool | deep, | ||
bool | repeat, | ||
unsigned int | depth, | ||
PyArgs... | pyargs | ||
) |
Method to declare a Python function with variable number of arguments, and make that call a C++ algorithm as specified in the Algo template parameter.
This will make the algorithm traverse post-order, that is to say, first on the innermost child (or leaf) of an expression tree, and then, if that fails, on parent nodes, and so on.
void cadabra::def_algo_preorder | ( | pybind11::module & | m, |
const char * | name, | ||
bool | deep, | ||
bool | repeat, | ||
unsigned int | depth, | ||
PyArgs... | pyargs | ||
) |
Method to declare a Python function with variable number of arguments, and make that call a C++ algorithm as specified in the Algo template parameter.
In contrast to def_algo, this one will apply the algorithm in pre-order traversal style, that is, it will first attempt to apply on a node itself before traversing further down the child nodes and attempting there.
Add two expressions, adding a top-level '\sum' node if required.
std::string cadabra::Ex_as_latex | ( | Ex_ptr | ) |
The Python 'print' function always calls the 'str' member on objects to be printed.
This one is required to produce output which looks readable but is also still valid input. In order to produce proper LaTeX output, this is therefore not the right function to use, because Cadabra only reads a restricted subset of LaTeX (for instance, we output spacing commands like '\,' but do not accept it on input). So we have a separate latex() member on each object, which internally uses DisplayTeX to do the actual printing.
std::string cadabra::Ex_as_str | ( | Ex_ptr | ex | ) |
Generate the Python str() and repr() representation of the Ex object.
Comparison operator for Ex objects in Python.
Since comparison operators need a Properties object, we cannot have such operator== things in C++, but we can in Python since we can get the kernel in the current scope.
Multiply two expressions, adding a top-level '\prod' node if required.
Subtract two expressions, adding a top-level '\sum' node if required.
Ex_ptr cadabra::fetch_from_python | ( | const std::string & | nm | ) |
Fetch an Ex object from the Python side using its Python identifier.
Kernel * cadabra::get_kernel_from_scope | ( | ) |
Get a pointer to the currently visible kernel.
void pull_in | ( | std::shared_ptr< cadabra::Ex > | ex, |
cadabra::Kernel * | kernel | ||
) |
Replace any objects of the form '@(...)' in the expression tree by the python expression '...' if it exists.
Rename dummies to avoid clashes.
void run_python_functions | ( | std::shared_ptr< cadabra::Ex > | ex, |
cadabra::Kernel * | kernel | ||
) |
Run all functions in the given expression which are available in the Python scope.