user_guide:extend:extensions

This is an old revision of the document!


polymake Extensions

A polymake extension is a collection of various bits and pieces of software that can be used together with the core stuff obtained from the distribution. An extension may enhance existing applications and/or define fully new, independent applications. In detail, an extension may contain any mix of:

  • rule files, thus allowing to define new properties, object types, all sorts or rules, methods, etc.
  • scripts and perl modules
  • C++ clients and class libraries

Note
Extension management has been completely reworked prior to polymake snapshot version 2.12.4. All commands and procedures depicted below are only applicable to this snapshot or later releases. Please refer to the older version of this page for description pertaining to polymake 2.12 or earlier.

  1. Choose a location on your computer (or a network share) where you have write permissions; let's name it my_ext in the examples below.
    If you are working with an SVN working copy of polymake, please make sure that your new directory is outside the source tree.
  2. In an interactive polymake session, execute the commands:
    found_extension "~/my_ext";
    extend_application "~/my_ext", "APP_NAME";
    where APP_NAME is the name of an existing application you are going to enhance.

What has happened? polymake has created a folder my_ext (if it did not exist before) and within it a whole hierarchy of subfolders, having the same structure as the core applications:
apps/APP_NAME/rules
apps/APP_NAME/scripts
apps/APP_NAME/src
and so on. Now it's upon you to populate it with new stuff. polymake has also created two directories
include and
build.<architecture>
in my_ext. The first contains links to the header directories in apps/polytope/include, the second will later contain the compiled libraries. You should not put any stuff there yourself. The absolute path to the top directory my_ext is stored in your custom variable @extensions, so that from now on everything you put in this extension is automatically available as if it were defined in the core distribution.

If you are going to define new rules, please remember that one of the rule files should be called main.rules, which will be loaded by polymake at the very start of the session. For instance, if you want to use a new rule file called my_rules.rules, the file my_ext/apps/APP_NAME/rules/main.rules should contain the following lines:

INCLUDE
   my_rules.rules

If you have written some C++ clients, they will be automatically compiled at the beginning of the next interactive session; however, later changes must be compiled manually by invoking
make -C ~/my_ext.

You repeat the same command extend_application as described above, specifying the same extension directory.

To create a really new application from scratch, execute the command
found_application "~/my_ext", "APP_NAME";
Again, it will create a folder hierarchy rooting at my_ext/apps/APP_NAME. After having composed the rules and/or clients, you may include the APP_NAME in the custom variable @start_applications stored in prefer.pl in your polymake settings directory (usually ~/.polymake) so that you'll have your new application at hand in every interactive session.

If your extension depends on third-party software packages which need to be installed separately, you'll have to provide some auto-configuration routines in the rules. To resolve dependencies on autonomous programs, you can use all the fancy tools available in the “standard” rules: custom variables, CONFIGURE clauses, utilities like find_location, find_program, etc.

In the case your extension needs the third-party software already in the initial build phase, because you are using it in your clients as a callable library, you should provide a pre-build configuration procedure performing some preparations and sanity checks like adding compiler and linker flags necessary to find the library, asserting that the version of the library is not too old for you, etc.

All this is done in a script configure.pl located in the top directory of your extension. For this purpose, every extension gets at its birth a personal copy of a script template configure.pl.template. You should edit it, filling the stubs of the functions with appropriate actions, introduce configuration options, if needed, and finally rename the script into configure.pl. Then this script will be executed immediately during the extension import (see below) as well as each time one runs the interactive command reconfigure_extension. All clients in the extension are recompiled after each reconfiguration, at the latest at the beginning of the next polymake session.

The script template contains comments describing the purpose and signature of each mandatory function; you may also want to look for the examples into the configuration scripts of extensions bundled with polymake. At your disposal are all utilities from the module perllib/Polymake/Configure.pm and all core configuration variables, both defined in the package Polymake::Configure. The extension configuration script is interpreted in a separate package; please, don't change into other package within the script. Also be aware that the extended perl syntax (like namespace mode) is not allowed for the configure script.

The ruleset of your extension must contain a CONFIGURE_BUILD clause. Its purpose is to determine all necessary compiler and linker options (by querying the user, examining pkg-info, whatever else) and write them into the configuration makefile. The CONFIGURE_BUILD clause shouldn't manipulate the file on its own; instead, it must return a list of pairs ( VarName => "value" ). Returning an empty list is interpreted as a configuration failure.

Then you must create a file apps/appname/src/Makefile.inc where you can insert the values gathered in CONFIGURE_BUILD to the relevant make variables like CXXFLAGS, LDFLAGS, LIBS, etc. The configuration makefile is always automatically included.

Each time you (or any user of the extension) changes the configuration makefile (e.g. by calling reconfigure with the rulefile containing the configuration clause), all clients will be recompiled at the next polymake start.

There are three possible ways to make your extension available to other people, which may also be arbitrarily combined:

  1. If you have writing access to the polymake core installation (or can ask your sysadmin for assistance), that is available to other users on your computer or local network, you may install your extension right there:
    make -C ~/my_ext install ExtensionName=EXTNAME
    This will create a subdirectory extensions/EXTNAME under the top installation directory of polymake (which is stored in the variable $InstallTop, by the way). Omitting the ExtensionName argument in the make command will install your extension under extensions/my_ext.
  2. If you have collaborators developing your extension, you may keep it in a version-controlled repository. If you choose subversion, polymake will even automatically commit all automatically generated files and create svn:ignore attributes whenever needed. To fully enjoy the polymake support for subversion, you should register the top directory ~/my_ext prior to calling any found_extension or found_application commands.
  3. If you want to bring your extension to broader audience, you may create a tarball starting at ~/my_dir (but excluding the Makefile and any build.* folders) and make it available for download.

In any case people using your extension will eventually produce data files depending on it. Especially if you introduce new properties, object types, or applications, anybody not having access to your extension won't even be able to load a data file containing any of your specific features. To clearly distinguish them from the core features, each publicly available extension must have a unique identifier, also called URI. Although the form of the URI can't be strictly prescribed, we recommend a URL-like string roughly pointing in the direction of your website. e.g.:
"http://www.your.domain/polymake/extension/EXTNAME"

The URI of your choice must be stored in the file ~/my_ext/URI. Along with the entire sources, this file must be submitted into the repository and/or packed into the tarball. Each data file containing any of the extension-specific features will bear an additional ext XML attribute showing your URI.

As your extension keeps growing, you'll want to create the documentation HTML pages to have a better overview of all the new features at hand. This can be done very easily with the script generate_docs shipped with polymake. Just call it from the interactive session like this: script("generate_docs", "OUT_DIR"); Then you'll obtain the complete set of documentation pages describing the standard system and all loaded extensions, rooted at the given directory OUT_DIR, which you can load directly into your web browser or deploy to your local webserver.

Please note that the extensions are not described on separate pages; instead, the properties, functions, etc. introduced in extensions are listed together with the corresponding standard features, as usual arranged by applications and object types. This behavior is implemented purposely, as it fully matches the seamless style of integrating extensions in the standard system.

Put a credit note in one of your rule files (preferably in main.rules). It can contain your name, a Web URL, a copyright notice, a short description of the features implemented in your extension, a citation of your main article about it, or whatever else you'll find appropriate to mention. Then your name will be displayed in each session as soon as a rule from your extension is called; the abbreviated form of your credit note will be also stored in each data file handled with your rules.

The exact format of a credit note can be found in several core rule files, e.g. apps/graph/rules/comparing.rules .

In the course of time you may change the data representation or rename properties introduced in your extension. These changes may render your old data files useless, as polymake won't be able to load them any more. To be able to recover the old files automatically, you should make use of versioning. To this end, you adopt some numbering scheme and append the current version number to the URI of your extension, like this: http://www.your.domain/polymake/extension/EXTNAME#1.0 (recall that this is stored in the URI file in the top directory of your extension). Then, each time you are introducing an incompatible change in your extension, you bump the version number (for example up to 1.1) and create a transformation stylesheet (XSLT) xml/upgrade-1.1 . There are some lines that need to be present in any transformation sheet. Here is an example

<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                             xmlns:p="http://www.math.tu-berlin.de/polymake/#3">
<xsl:output method="xml" encoding="utf-8" cdata-section-elements="p:description" indent="yes" />

[...]

<xsl:include href="trivial-copy.xslt" />
</xsl:transform>

Replace […] by the conversion rules for your extension. A simple conversion rule could be the following:

<xsl:template match="p:property[@name='OLD_PROPERTY']">
  <xsl:element name="property" namespace="{namespace-uri()}">
    <xsl:attribute name="name">NEW_PROPERTY</xsl:attribute>
    <xsl:attribute name="value">
      <xsl:value-of select="@value" />
    </xsl:attribute>
  </xsl:element>
</xsl:template>

This code just replaces the property name OLD_PROPERTY by NEW_PROPERTY, and leaves everything else invariant. Note however that this applies to any occurrence of OLD_PROPERTY, so if your property name also occurs somewhere else (e.g. in another application, or as a property of some other object) then those will be changed as well. So in this case make sure that your rule only matches the occurrence in your extension.

The standard polymake distribution already contains several transformation stylesheets which can be used as a source of inspiration.

When polymake loads a very old data file lying behind several version bumps, all transformations between its version and the current version are applied in the proper (ascending) order; thus each transformation stylesheet should only contain converting operations specific for a single version bump.

You may, for whatever reason, completely rename the URI of the extension, by manual editing the URI file. Later, when you load a data file still containing the old URI, polymake won't initially know about this renaming and will ask you, as usual, to enter the installation directory of this apparently new extension. Now you simply enter the directory of the existing extension, polymake compares the URIs, recognizes the renaming, and stores this fact persistently in the custom hash %renamed_extensions, just to avoid asking you repeatingly.

Depending on the way of distribution (as described above), you may have to check out the extension from a repository or download a tarball and unpack it. In any case the concluding step will be
import_extension "~/my_ext";
called in a interactive session.

Some extensions may ask for prerequisite libraries provided by third parties, necessary to compile the client functions. Such an extension will try to locate the required libraries automatically and prepare the compilation process to use them. If the automatic recognition fails, the extension won't be imported. Instead, you will see a (hopefully intelligible) error message explaining what exactly has been missing and how you can remedy the problem. In the case you have installed the required third-party libraries at some non-standard location, or want to disable some optional part of the extension functionality, you can tell it to the extension by passing appropriate options as string arguments to the import_extension command. The exact wording of these options should be conceivable from the error message; otherwise, you are invited to complain by the author of the extension. The TAB completion and context-sensitive help to import_extension will try to assist you as well.

An extension can also be imported on demand, in the course of loading a data file containing an unknown extension URI. As soon as polymake encounters such a URI in the data file, it stops the loading procedure and asks you for the location where the extension resides. If you have no idea where to obtain the extension right now or simply don't want to bother installing it, you should type in stop (thus interrupting the loading process) or skip (loading only standard properties). In the latter case a backup copy of the data file is created. Your decision to despise this particular extension is remembered until the end of the interactive session; should you change your mind later, you'll have to restart polymake.

You can mix pieces from several extensions, written by yourselves as well as imported from elsewhere. In the ideal case, the extensions should not depend on each other. But if they do, polymake can cope with it very well, provided you have listed them in the right order in your custom variable @lookup_applications. Data files containing features from several extensions are allowed; they will contain the ext attributes with all relevant URIs, but not necessarily grouped at one spot.

Instances of parameterized C++ types and functions (templates) with argument types stemming from different extensions will be generated as if belonging to the rightmost extensions from all involved ones (that is, the one loaded last.)

One nice day you might suddenly want to get rid of an extension. The reason may be that you aren't interested in it any more, or that its functionality has been merged into the standard distribution or another extension. The most comfortable way is to use the command forget_extension . It deletes all traces of the extension in the long-term memory of polymake. Be aware, however, that in the current interactive session you still have the pieces from the discarded extension loaded and ready-to-use. Thus, to avoid confusion, you should quit the session as soon as possible after using this command.

If you later try to load a data file containing some properties or objects defined in the discarded extension, polymake will ask you, as usual, to enter its installation directory. If you are sure that in the meanwhile all the stuff has migrated into the standard distribution and/or other (already loaded) extensions, you should response with the magic word ignore .

  • user_guide/extend/extensions.1370300570.txt.gz
  • Last modified: 2014/01/03 15:45
  • (external edit)