Table of Contents

Dealing with Data Model Changes

Data model in polymake evolves constantly: new big object types, subobjects, and properties show up virtually in every release. As long as only new stuff is being added, the forward compatibility is preserved, so that an old data file can safely be loaded into an arbitrary version of polymake released later. However, sometimes we have to revise old design decisions and change the existing data model in an incompatible way. A non-exhaustive list of compatibility breaking change examples:

Whatever the reasons for a data model change, we have to ensure a lossless automatic data transition for users upgrading their installation. The mechanism is based on a strict versioning scheme and so called upgrade rules. The rest of this page describes the steps you as a developer must execute every time you introduce an incompatible data model change. The procedure slightly differs depending on whether the data model change is the first one after the most recent polymake release. Just for illustrative purposes we will assume in the following examples the most recently released version to be 4.1.

Introducing the first change after a release

This situation can be recognized by the current polymake version (stored in a global variable $Version in Polymake.pm) being equal to the last release version, and consisting of exactly two numbers, e.g. 4.1 .

Introducing a subsequent change

This situation can be recognized by the current version consisting of three numbers, e.g. 4.1.2 .

Finishing the change

The remaining steps are the same in both scenarios.

Resolving conflicts

It can happen that two developers decide to introduce (different) model changes at the same time. If you are first ready with your work, you can merge it into the master branch as usual. However, if the second turn is yours, you should take particular precautions in order to prevent broken data files:

Upgrade rules

Upgrade rules are perl subroutines operating on polymake data in serialized form, that is, on pure perl structures like numbers, strings, anonymous lists and hashes, exactly how you see them in a JSON file. All upgrade rules applicable to data with source version M.N are stored in a file named upgrades/M.(N+1), that is, named after the next release version. An upgrade rule file may only contain upgrade rules and generic perl code like subroutines, lexical variables, use or require statements, but no other kinds of rules or declarations.

By convention, an upgrade rulefile should start with a comment block briefly describing all transformations defined there. Please refer to the existing rules for real life examples.

The upgrade rules are applied to matching objects in the increasing order of target versions; the rules with equal target versions are applied in the order of definition in the rulefile. If a rule can be applied to a big object and to some of its subobjects, the parent object will be processed first, while the order of processing of its properties is unpredictable.

An upgrade rule can have one of the following forms (M.N.P is the intermediate target version as described in the examples above):

upgrade M.N.P APP_NAME::BIG_OBJECT_TYPE {
  my ($obj) = @_;
  # some transformations
  return BOOLEAN;
}

This rule will be called for every big object of the specified type or derived thereof, regardless whether it's a top-level standalone object, a subobject of another big object, or an element of a big object array. The rule may do whatever is necessary, including modifying its type, any properties and their optional attributes, accessible as $obj->{_type} resp. $obj->{PROPERTY_NAME} and $obj->{_attrs}->{PROPERTY_NAME}. Please be aware that the explicit _type element might be absent in subobjects when their type exactly matches the property declaration.

upgrade M.N.P APP_NAME::BIG_OBJECT_TYPE.PROPERTY {
  my ($obj, $prop_name) = @_;
  # some transformations
  return BOOLEAN;
}

This rule will be called for every occurrence of the specified property in a big object of specified type or derived thereof. The PROPERTY part can in fact be a path descending into subobjects: SUBOBJECT1.SUBOBJECT2.PROPERTY. The $obj parameter will point to the direct parent object of the property of interest, not to the object at the top of the hierarchy. The $prop_name parameter will contain the name of the bottom-most property. The same rule can be reused for several different properties by listing several property paths separated by bars: PROPERTY1 | PROPERTY2 .

When writing transformations of property values, please keep in mind that they can happen to be undef.

All big object types appearing in an upgrade rule must always be qualified with the application name, including new type names assigned to the _type element. Big object types in the header may never be written with type parameters, a rule is always applicable to all instances of a parametrized type.

The return value of an upgrade rule should be true if something has been changed or false if everything has stayed as before.

When renaming or moving a property into a different place in the object tree, don't forget to move and/or rename its optional attribute too. Because this is a quite frequent operation, there are convenience functions rename_property and move_property which can be called from the rule body. Moreover, there are two shortcut forms for rules where the renaming or deleting a property is the only action to be performed:

upgrade M.N.P APP_NAME::BIG_OBJECT_TYPE.PROPERTY = rename NEW_PROPERTY;
upgrade M.N.P APP_NAME::BIG_OBJECT_TYPE.PROPERTY = delete;