Important Changes in Regina 7.0 |
Prev | Introduction | Next |
Regina 7.0 brought an enormous overhaul across the entire codebase—possibly the largest overhaul in almost two decades. There has been signficant work to insulate users from these changes: the bulk of these changes should only be visible to C++ programmers, but there are important behavioural changes that will affect everybody.
Some of these changes break backward compatibility.
If you are migrating from Regina ≤ 6.0.1, you should read the brief summary below so you understand the most important changes.
C++ and Python programmers can find a more fine-grained explanation of the API changes on the Regina website.
Regina's data file format has changed. Regina 7.0 and above can read your old data files, but Regina 6.0.1 and earlier will not be able to read files from newer versions of Regina.
If you need to export a file so that Regina ≤ 6.0.1 can read it, you use the command-line regconvert utility, or the → menu in the user interface.
A major advantage of the new file format is that different packets no longer depend on each other. In particular, if you create a normal surface, hypersurface or angle structure list from a triangulation, you can later change the triangulation, or move it to a separate location in the tree, or even delete it. The list will make its own copy of the original triangulation if this becomes necessary (which you can access through the header of the normal surface, hypersurface or angle structure viewer). Likewise, the list will bundle this copy of the original triangulation into the data file if necessary.
For several years, Regina has supported triangulations of dimensions 2–15. However, these higher dimensions add significant overhead (even if you are not using them), particularly for Python users.
For this reason, Regina 7.0 and above now only includes dimensions 2–8 by default. In particular, if you open a data file containing triangulations of dimension 9–15 and then save the file again, these triangulations will be lost.
If you need to work with dimensions 9–15, you can make your own
custom
build of Regina; be sure to pass the option
-DHIGHDIM=1
to cmake.
Also perhaps drop Ben an email so he knows that there are users who
want these features.
For the first time, Python users now have access to essentially everything inside Regina's C++ calculation engine. You can use functions that take callbacks (e.g., the exhaustive retriangulation code, census generation, and subgroup enumeration), and you can access low-level algorithms (e.g., the linear programming code, or the double description method and Hilbert basis enumeration).
Python now supports iteration wherever C++ does, using lightweight iterator objects where possible:
>>> for e in Example3.lens(8,3).edges(): ... print(e) ... Edge 0, internal, degree 4: 0 (01), 0 (20), 1 (10), 0 (13) Edge 1, internal, degree 4: 0 (03), 1 (02), 1 (31), 0 (21) Edge 2, internal, degree 4: 0 (23), 1 (30), 1 (23), 1 (12)
Almost all classes now provide a more informative Python representation:
>>> ExampleLink.trefoil().group() <regina.GroupPresentation: < a b | a^-2 b a b >>
The equality comparisons (==
and !=
)
now compare their contents by value for most classes.
The main exceptions are objects whose location in memory defines them
(e.g., faces and simplices in triangulations, or crossings in links),
and objects whose purpose is to manage an expensive computation
(e.g., progress trackers or census managers); these still compare by
reference. Each class has an equalityType
constant that tells you how its objects are compared.
>>> Example3.lens(8,3).homology() == AbelianGroup(0, [8]) True >>> AbelianGroup.equalityType <EqualityType.BY_VALUE: 1>
In line with the C++ changes described below, Regina now throws
exceptions upon error in some settings instead of returning
None
(e.g., Triangulation3.fromIsoSig()
);
see the API documentation for details on which exceptions
each function might throw (if any).
Mathematical objects such as triangulations and links are no longer
packets (i.e., they do not live in a packet tree or belong to a
data file by default); this is for performance reasons.
If you just want to work with a triangulation or link, you can
use Triangulation3
or Link
as before;
however, if you want to insert one of these objects into a packet tree
then you will need to use the corresponding classes
PacketOfTriangulation3
or PacketOfLink
(and so on for other types of object).
These packet classes inherit from Triangulation3
,
Link
, etc., and can be used in much the same way.
You can use the new make_packet()
functions
to help you convert between the classes.
>>> ExampleLink.figureEight() <regina.Link: 4-crossing knot: ++-- ( _0 ^1 _2 ^3 _1 ^0 _3 ^2 )> >>> make_packet(ExampleLink.figureEight()) <regina.PacketOfLink: 4-crossing knot: ++-- ( _0 ^1 _2 ^3 _1 ^0 _3 ^2 )>
Finally, although there are far fewer changes to the Python API
than for C++, there is one change that will likely affect most people:
to enumerate normal surfaces or angle structures, you no longer
use the old enumerate()
functions. Instead,
just create a new NormalSurfaces
or
AngleStructures
object:
>>> t = Example3.poincare() >>> s = NormalSurfaces(t, NS_STANDARD) >>> print(s) 7 embedded, vertex surfaces (Standard normal (tri-quad))
Regina began in the late 1990s, before C++ was ever standardised. Since then, Regina's API has slowly evolved as the language changed, incrementally making use of new language features, and removing old workarounds as they became no longer necessary.
One of the most important changes to the C++ language was the much improved value semantics that came with C++11. When used with the new C++11 move operations, this made it both easy and efficient to pass large objects around by value, not by pointer. The resulting code reads more naturally, is typically less error-prone, avoids the need for manual memory management, and still retains the performance of the old pointer-based code.
In Regina 7.0, the C++ API underwent a complete overhaul from head to toe. The API now uses the C++17 standard. Widespread changes include:
Regina now uses value semantics across the board. So, for example,
Triangulation<3>::fromIsoSig()
now returns aTriangulation<3>
by value. Most of your objects should now be able to live on the stack; in general there should no need for manual memory management vianew
anddelete
. The main exceptions are objects that are defined by their locations in memory, such as faces and simplices in triangulations, or crossings in links: these are still passed by pointer, but their memory is safely managed by their enclosing triangulations or links.Likewise, functions that used to return newly-allocated pointers now return by value. If they used to return
null
when unexpected errors occurred, they typically now throw exceptions; if they used to returnnull
in ordinary scenarios where there is no solution, they typically now return astd::optional
.When returning polymorphic objects (such as
Packet
orStandardTriangulation
), you cannot avoid returning by pointer since the exact type is not known at compile time. In such cases, Regina now returns a smart pointer (typicallystd::shared_ptr
for packets andstd::unique_ptr
for other types of object).Functions that used to take arguments by pointer now typically take them either by value or by const reference. Many functions that used to return multiple values via reference arguments now return a
std::tuple
instead.The class hierarchies have been simplified considerably. Hopefully one side-effect of this is that the API documentation is easier to navigate.
Functions that take callbacks (such as census generation or exhaustive retriangulation) are now more flexible, and can work with lambdas and arbitrary lists of properly-typed arguments. They no longer take function pointers with untyped
(void*)
arguments.Packets are now managed exclusively by shared pointers. You should never be holding on to to a raw pointer to a packet type. The large mathematical classes such as
Triangulation<dim>
andLink
are no longer packet types, since this frees them from considerable overhead; if you need to insert them into a packet tree then you should usePacketOf<Triangulation<3>>
,PacketOf<Link>
, and so on. There is a new suite ofmake_packet()
functions to help you with this.
Since Regina 7.0 was a “big release” that broke backward
compatibility, this was a good time to clean up and simplify many other
unwieldy parts of the API. These changes range from simple renamings
(e.g., StandardTriangulation::isStandardTriangulation
becomes StandardTriangulation::recognise
) through to
major semantic changes (e.g., each normal surface now stores an
encoding, which is to some degree independent
of the coordinate system that was used to create it).
If you are writing C++ code that links against Regina, you will need to change your code. Generally the issues should be flagged by the compiler (not discovered at runtime), and the necesssary changes should be obvious. Some old functions have been kept but marked as deprecated to ease the transition; your compiler should warn you also if you are still using these.
For a long time, Regina has offered “experimental” support for transversely oriented normal surfaces (TONS). This always came with large caveats and promises that things would break, and needed to be explicitly enabled before it could be used.
Now that the normal surface classes have undergone a major redesign, TONS no longer fits cleanly into the normal surface model (since in some fundamental sense they are not normal surfaces), and so this support has been removed completely from Regina.
The intention is to reimplement TONS “properly” in a future release, using their own separate suite of classes that more accurately reflect what they are and how they behave.
Prev | Contents | Next |
What does Regina do? | Up | Genealogy |