Cadabra
Computer algebra system for field theory problems
Files | Functions
Python Core

Module Description

Python wrapper around the C++ core module, making 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
 

Functions

void pull_in (std::shared_ptr< cadabra::Ex > ex, cadabra::Kernel *)
 
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)
 
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)
 
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)
 
bool cadabra::Ex_compare (Ex_ptr one, Ex_ptr other)
 
Ex_ptr cadabra::Ex_add (const Ex_ptr ex1, const ExNode ex2)
 
Ex_ptr cadabra::Ex_mul (const Ex_ptr ex1, const Ex_ptr ex2)
 
Ex_ptr cadabra::Ex_sub (const Ex_ptr ex1, const ExNode ex2)
 
Ex_ptr cadabra::fetch_from_python (const std::string &nm)
 
std::string cadabra::Ex_as_str (Ex_ptr ex)
 
std::string cadabra::Ex_as_latex (Ex_ptr ex)
 
Kernelcadabra::create_scope ()
 
void cadabra::inject_defaults (Kernel *k)
 
Kernelcadabra::get_kernel_from_scope ()
 

Function Documentation

◆ apply_algo_base()

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. This gets called by the various apply_algo functions below, which in turn get called by the def_algo functions.

◆ create_scope()

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.\footnote{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 \verb|__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 \emph{global} property list by default. If you want to create a local scope for your computations, create a new \verb|__cdbkernel__| as in \begin{verbatim} def fun(): cdbkernel = cadabra.create_scope(); [your code here] \end{verbatim} Now computations will not see the global properties at all. If you want to import the global properties, use instead \begin{verbatim} def fun(): cdbkernel = cadabra.create_scope_from_global() [your code here] \end{verbatim} It is crucial that the \verb|__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 \verb|__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 \begin{verbatim} def fun(): cdbkernel = cadabra.create_empty_scope() [your code here] \end{verbatim} 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 \verb|locals()| produces). If there is no kernel available locally, they will then revert to using the global kernel.

◆ def_algo()

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. 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.

◆ def_algo_preorder()

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. 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.

◆ Ex_add()

Ex_ptr cadabra::Ex_add ( const Ex_ptr  ex1,
const ExNode  ex2 
)

Add two expressions, adding a top-level \sum node if required.

◆ Ex_as_latex()

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.

◆ Ex_as_str()

std::string cadabra::Ex_as_str ( Ex_ptr  )

Generate the Python str() and repr() representation of the Ex object.

◆ Ex_compare()

bool cadabra::Ex_compare ( Ex_ptr  ,
Ex_ptr   
)

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.

◆ Ex_mul()

Ex_ptr cadabra::Ex_mul ( const Ex_ptr  ex1,
const Ex_ptr  ex2 
)

Multiply two expressions, adding a top-level \prod node if required.

◆ Ex_sub()

Ex_ptr cadabra::Ex_sub ( const Ex_ptr  ex1,
const ExNode  ex2 
)

Subtract two expressions, adding a top-level \sum node if required.

◆ fetch_from_python()

Ex_ptr cadabra::fetch_from_python ( const std::string &  nm)

Fetch an Ex object from the Python side using its Python identifier.

◆ get_kernel_from_scope()

Kernel * cadabra::get_kernel_from_scope ( )

Get a pointer to the currently visible kernel.

◆ inject_defaults()

void cadabra::inject_defaults ( Kernel )

Inject properties directly into the Kernel, even if the kernel is not yet on the Python stack (needed when we create a new local scope: in this case we create the kernel and pass it back to be turned into local cdbkernel by Python, but we want to populate the kernel with defaults before we hand it back).

◆ pull_in()

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. Rename dummies to avoid clashes.