a field-theory motivated approach to computer algebra

# Using multiple files and notebooks

At some point, you will encounter computations which are best separated out into their own notebook. Or you will do a computation which takes a long time, and you want to write an intermediate result into a file so that you can read it back later easily. There are two options for this in Cadabra: importing notebooks into other notebooks, or writing individual expressions to a file and reading them back.

## Importing a notebook into another one

The simplest way to separate functionality is to simply write a separate notebook with the properties and expressions which you want to re-use elsewhere. In this way, writing a 'package' for Cadabra is nothing else but writing a separate notebook. You can import any notebook into another one by using the standard Python import logic.

### Example

Let us say we have a notebook library.cnb, which contains a single cell with the following content:
   {m,n,p,q,r}::Indices;
ex:=A_{q r} A_{q r};

You can now import this into another notebook by simply using
from library import *
Cadabra looks for the library.cnb notebook in your PYTHONPATH (just as in ordinary Python programs), as well as in the current directory. You can see that this worked by e.g. the following:
ex; rename_dummies(ex);
$$\displaystyle{}A_{q r} A_{q r}$$
A_{q r} A_{q r}
$$\displaystyle{}A_{m n} A_{m n}$$
A_{m n} A_{m n}
Note that the import has thus not only imported the ex expression, but also the property information about the index set, which enabled the rename_dummies to work.
Behind the scenes, what happens is that the import statement looks for a file library.cnb. If it finds this, it will first convert that file to a proper Python file (remember the library.cnb file is a Cadabra notebook, not a Python file). It then uses the standard Python logic to do the import.

## Writing expressions to a file and reading them back

A somewhat more difficult way to re-use expressions is to write them to a file using standard Python methods, and then read them back elsewhere. This method is best used for long computations of which you want to write an intermediate result out to disk, to be read in later (instead of doing a re-computation). Be aware that if you write an expression to disk, you do not write the property information of any of the symbols in that expression to disk.

### Example

The following example declares two expressions and writes them to disk. It then reads the expressions back in again and assigns them to different Python names.
ex1:= A_{m n} \sin{x}; ex2:= B_{m n}; with open("output.cdb", "w") as file: file.write( ex1.input_form()+"\n" ) file.write( ex2.input_form()+"\n" )
$$\displaystyle{}A_{m n} \sin{x}$$
A_{m n} \sin(x)
$$\displaystyle{}B_{m n}$$
B_{m n}
ex3; ex4;
$$\displaystyle{}A_{m n} \sin{x}$$
A_{m n} \sin(x)
$$\displaystyle{}B_{m n}$$
B_{m n}
Note that when written in this way, the file output.cdb only contains the expressions, not their names (ex1 and ex2 in the example above).
Cadabra's expressions can also be written to disk using Python's pickle functionality. This makes the code slightly less messy, but note that the file will no longer be human-readable. If you use the pickle module, the example above would read:
import pickle ex1:= A_{m n} \sin{x}; ex2:= B_{m n}; with open("output.pkl", "wb") as file: pickle.dump(ex1, file) pickle.dump(ex2, file)
$$\displaystyle{}A_{m n} \sin{x}$$
A_{m n} \sin(x)
$$\displaystyle{}B_{m n}$$
B_{m n}
$$\displaystyle{}A_{m n} \sin{x}$$
$$\displaystyle{}B_{m n}$$