Regina 7.0 Calculation Engine
Python users

Regina's calculation engine is provided as a shared C++ library, and this API documentation is written to describe Regina's native C++ interface.

However, Regina also makes this library accessible through a Python module. If you are using Python, the notes below explain (briefly) how you should read this API documentation.

Python vs C++ types

  • Standard C++ types become native Python types. For example, the C++ type std::string becomes the native Python string type, the C++ type std::vector<T> becomes a native Python list holding objects of type T, and the C++ type std::optional<T> will either become a Python object of type T or the Python value None.
  • Everything within the C++ namespace regina becomes part of the Python module regina. For example, the C++ class regina::Link becomes the Python class regina.Link.
  • Regina has many templated classes, and Python does not support templates. Typically Regina will replace the template arguments with an appropriate suffix in the Python class name. For example, the C++ class Triangulation<3> becomes the Python class Triangulation3, and the C++ class Matrix<regina::Integer> becomes the Python class MatrixInt. See the individual class notes for how the Python class names are constructed.

Python vs C++ APIs

  • Since Regina 7.0, almost all of Regina's C++ classes and functions are wrapped in Python - even the low-level and/or highly specialised classes - wherever it is meaningful to do so. However, sometimes there is reason why a class or function cannot or should not be wrapped. If a class or function is not available in Python then you will see a bold Python: note indicating this. See for instance the class MarkedVector, or the function valueOf().
  • Most of Regina's classes and functions use the same interface in both C++ and Python, but occasionally there are differences in how the classes or functions are used. Again, you will see a bold Python: note indicating this. See for instance the method Link::rewrite(), or the global function writeResUsage().

Testing equality

It is important to understand how the comparisons x == y and x is y operate under Python. As of Regina 7.0, this behaviour has changed significantly: many more classes now compare by value, and a few now have their comparisons disabled.

In general, you do not want to use the Python test x is y. This is because each of Regina's Python objects is typically a "wrapper" that points to one of Regina's native C++ objects. Importantly, the same native C++ object could have many Python wrappers, and so x is y could return False even if both x and y wrap the same native C++ object.

Instead, you should always use the tests x == y and/or x != y. Regina implements this in different ways, depending on the type of class:

  • Most of Regina's classes use comparison by value. Here x == y tests whether the contents of x and y are the same. What "the same " means will depend on the particular class; for example, GroupPresentation tests for identical presentations (not group isomorphism), Triangulation<3> tests for the same tetrahedron and vertex labellings (not just combinatorial isomorphism), and Attachment compares the attached file contents (ignoring the associated filenames). For the core numeric classes such as Integer, Rational, Polynomial, VectorInt and MatrixInt, this tests the usual mathematical equality.

    For each such class, you can find out what is being compared by reading the documentation for the C++ class operators == and !=. See for example Link::operator==().

  • Some selected classes use comparison by reference. Here x == y tests whether x and y refer to the same underlying C++ object (analogous to how x is y would normally behave in a native Python application). This is typically used for the few classes that are passed around by pointer in C++, and whose location in memory is what defines them; the most common examples you will see are crossings within links (Crossing), and skeletal objects within triangulations (e.g., Tetrahedron<3>, Vertex<4>, BoundaryComponent<2>). This is also used with objects that manage or track long computations (e.g., ProgressTracker, GluingPermSearcher4, or TreeEnumeration).

    These classes do not provide C++ class operators == or !=.

  • A few classes have explicitly disabled their comparison operators, since they are designed to be moved and/or copied (which makes it inappropriate to compare by reference), but they do not yet have their own customised comparisons implemented (often because such a test would be expensive and/or would be difficult to define cleanly).

    These classes do not provide C++ class operators == or !=. If you attempt to compare two Python objects of such a class, you will receive a Python error with a message explain essentially what is written here.

  • For some classes, comparisons are irrelevant because they only contain static methods, and you cannot instantiate them. Examples of such classes are Example<3> and Locale.

If you wish to find out how a particular class C behaves, you can examine the attribute C.equalityType. This will return one of the values BY_VALUE, BY_REFERENCE, DISABLED or NEVER_INSTANTIATED respctively:

>>> print Triangulation3.equalityType
BY_VALUE

Packet subclasses are a special case: it is often meaningful to compare packets by value (e.g., testing whether two triangulations are combinatorially identical), but it is also useful to know whether two Python wrappers identify the same underlying C++ packet (e.g., when traversing the packet tree). To resolve this, you can compare two packets of the same type by value using the operators x == y and x != y, and you can test whether two packets of any types reference the same underlying object by calling Packet::samePacket().

International and special characters

If you use special characters (such as accented letters, other international characters, exotic punctuation, mathematical symbols and so on), you may need to think about text encodings when passing strings between Python and Regina.

For Python 3 users, this is simple: all strings in Python are unicode, and these are converted seamlessly and transparently when moving between Regina and Python.

For Python 2 users, you need to take some care. All unicode objects will be converted correctly and transparently. If you have a Python string, however, you will need to ensure it is encoded in UTF-8 when passing it to Regina. Conversely, you should assume that all strings that Regina sends back to Python will be UTF-8-encoded. See https://docs.python.org/2.7/howto/unicode.html for more information on how to work with UTF-8 strings in Python 2.

See the page on encodings for international strings for further discussion on text encodings within Regina, including an important note regarding filenames.


Copyright © 1999-2021, The Regina development team
This software is released under the GNU General Public License, with some additional permissions; see the source code for details.
For further information, or to submit a bug or other problem, please contact Ben Burton (bab@maths.uq.edu.au).