Rule files are the central part of an application. They describe the object
types, object properties, algorithms calculating the properties, and so on.
Standard rule files are always kept in the subdirectory rules of the
application they belong to. The user can add
own rule files and put them in private directories of his choice, specifying the
locations in his preference file ~/.polymake/prefer.pl.
General syntax
The general syntax of a rule file is the same as of a perl script. Formally
speaking, each perl script is a valid rule file too. However, the most crucial
declarations, such as property declarations or production rules, require
special header lines which do not obey the standard perl syntax rules. Other
rule file components, such as overloaded functions and methods, are introduced
in traditional perl syntax, but using additional, non-standard keywords.
To make the parsing process easier, the rule file is first divided into paragraphs
and sections. A paragraph is, as usual, a contiguous block of non-empty lines.
A section can consist of one or more paragraphs. A paragraph begins a new
section if its starting line is not indented (that is, without leading white
spaces), otherwise it is treated as a continuation of the previous section.
The rule-specific declarations are recognized by reserved keywords starting the sections.
The only exception are production rules, which use
a slightly more complicated syntax. If a section is not recognized as a
declaration, it is left unchanged and interpreted as normal perl code.
Whenever the documentation speaks about names (of applications, objects,
properties, etc.), the standard perl syntax for identifiers applies: the first
character is a letter, following characters are letters, digits, or underscore.
The rule files may contain comments in standard perl style. Comments put in
the middle of a section are ignored. However, paragraphs solely consisting of
comment lines can be treated as embedded documentation and stored by polymake along
with other meta-data produced from the declarations. There are two sorts of embedded
documentation:
a block of comments preceding a declaration is assumed to describe this
declaration. The text is used to generate the HTML documentation (which you
are reading now), the online help for the
interactive shell, and the user customization
file ~/.polymake/customize.pl.
Starting the comment block with a line
# Category: ...
will create an additional level in the documentation hierarchy, named after
the given category, and insert the documentation topic underneath.
Categories are widely used for the object properties, as they make the long
property lists more legible. Note that a category does
not effect the declaration semantics in any way, it is solely a
an aid for improving the documentation structure.
a free-standing block of comments starting with a line
# Topic: HELP/HIERARCHY/PATH
is inserted in the online help tree at the given location.
Directives are sections which don't contribute to the application description as such, but control the
process of parsing the rule files. To better distinguish the directives from the real
declarations, the keywords are written in capital letters.
Process further rule files of the current application. File names can be listed
after the keyword or on the following lines, one per line or several at
once, separated by whitespaces. The rule file names have traditionally the
suffix .rules, but this is not required.
When polymake loads an application, it reads a single rule file main.rules. Keeping all the declarations in a single file is not very
handy, however, therefore the main rule file usually consists of INCLUDE directives to a great extent.
INCLUDE can be nested arbitrarily deep. Each rule file in an application
is parsed only once, thus it is safe to put a rule file in the INCLUDE
directives of several other files.
Import the definitions from the given polymake modules into the current
application. Like in INCLUDE, the module names can be put on the same
line or on continuation lines.
A polymake module (not to confuse with perl modules) has the same structure
as a an application, but can't be used autonomously. Usually a polymake
module supplies functions, object types, etc. which are common for several
applications.
If a module specified in the directive is mentioned for the first time, the parsing of
the rule file is suspended and the module is loaded.
Define a subprogram which is called during the rule file
parsing. It must return a success code (whatever perl may convert to a boolean).
If it is true, the parsing procedure goes on. Otherwise the rule file
is discarded. If the CONFIGURE subroutine terminates with die, the
exception message is displayed in a warning on STDERR.
The main goal of this subroutine is to perform some auto-configuration,
e.g. to locate an external software package and check its version. To save
the execution time, the success code is stored in the custom hash array rulefiles.
Next time polymake just evaluates this stored value and either skips the
configuration call or discards the rule file from the very beginning.
Therefore if the auto-configuration collects important information
like program paths and command line options, it should store them in custom
variables too, otherwise these values will not be available in the next
polymake sessions.
Since the CONFIGURE subroutine is called immediately after being defined,
all custom variables used there must be declared prior to this section. To the contrary,
all rules or methods depending on the successful configuration should be
defined later in the rule file.
CONFIGURE : other_rulefile
This is a special form of auto-configuration, expressing the fact that the
current rule file depends on successful configuration of another rule file.
The rule file name can be specified in following way:
filename
another rule file of the current application
module::filename
a rule file in another module
(presumably imported by the current application)
module::
a rule file from the given module, with the same name as the
current one
These declarations may be placed everywhere in the rule file. Except for object and user_function definitions, they are
insensitive to the current package. The order is, however, important: an object type or a label can't be used before they are
properly defined.
Introduce a new object type. The perl package name of this object is Apps::APP_NAME::name
or Modules::MOD_NAME::name, depending on whether the current rule file
belongs to an application or to a polymake module.
The new object type may be derived from other ones, called basis or super
types. All super types must be already declared in the application or one
of the imported modules. The new object types inherits all properties and methods from the parents.
This declaration switches the context to the object's perl package, thus opening the object scope.
The object scope can be reopened later in this rule file or in other rule files using a package -like statement:
object name;
Please pay attention to the semicolon at the end of this statement.
Declare the specified object type name to be the default one for the
application. Without this declaration the chronologically first object type
declared in the rules is taken as default.
The default object type plays a role when polymake reads a data file
lacking an explicit type declaration.
Introduce a (possibly overloaded) function which should be available to the polymake user directly, without qualification or
importing. See the syntax of overloaded function definitions.
A user function may be defined in the application context only.
The leading comments can contain special subsections recognized when generating the online documentation:
Establish a persistent preference relation between the labeled production rules, functions, or methods.
Each prefer statement occuring in the rule files is copied into the user's private preference file
~/polymake/prefer.pl, where it may be edited by the user.
The preference relations comprise all labels with equal sublevels. For example, given the following production rule labels: cdd.convex_hull.primal, cdd.convex_hull.dual, lrs.convex_hull.primal, lrs.convex_hull.dual, and beneath_beyond.convex_hull.primal, the labels
*.convex_hull.primal make up a preference list, and the labels *.convex_hull.dual make up another list, independent of
the first one.
The first form of this statement declares the specified label and all its sublevels to be preferred over all corresponding
competitors. Going on with the example, a statement prefer cdd would make rules labeled with
cdd.convex_hull.primal and cdd.convex_hull.dual the preferred ones to compute the convex hull of a polyhedron. The
relation between lrs and beneath_beyond rules is undefined; each will have the equal chance to be chosen if the cdd rule
fails.
The second form establish a linear order between several rules or functions. For example, prefer *.convex_hull cdd, lrs,
beneath_beyond determines that the cdd convex hull rule will be always tried first, then, if it fails, comes the lrs 's
turn, and beneath_beyond stays the last resort.
These declarations are allowed only in the object scope.
property name
$type="type";
optional declarations ...
Declare a property. The only obligatory part of the declaration is the data type. The optional attributes are described
on a separate page.
Along with the new property the current object gets a method of the same name returning the value of this property, or, when
used in the lvalue context, creating this property. See the Poly::Object public interface.
Introduce an object method which is expected to be called by the user. A name of the user method can be used alone, without
object variable, in user's scripts and on the command line in compatibility mode, then it is
applied to the user's variable $this.
Introduce a (possibly) overloaded function or object method in the current package. The syntax and functionality of overloaded
functions are described on the separate page. If neither labels nor signature is specified,
these statements have exactly the same meaning as the standard perl sub or sub : method
definition, except that polymake asserts that the function is not defined multiply. Global methods, however, must be overloaded.
Declare a variable as being customizable by the user. All custom variables are collected in the user's private file ~/.polymake/customize.pl, where he/she can comfortably change their values by own taste.
The first form introduces the variable in the current package. var must be a valid perl variable declaration with
appropriate type character $, @, or %, like in the my operator. init can be any valid perl expression suitable
for the variable type.
The second form assigns the "customizable" attribute to a variable which is already defined and initialized somewhere else,
therefore the variable name is allowed to contain the package name. A special case constitute the custom variables initialized by
CONFIGURE subroutines, which are declared without initial value. However, if the CONFIGURE subroutine "forgets" to
assign something to such a variable despite of successful execution, the next polymake run will be terminated by an exception.
Regardless of the declaration kind, the value assigned to a custom variable is registered as its default value. As long as
the user has not overridden it in the customization file, the default value will be its effective value too. Once overridden,
the assignments made in the rule file or some other perl module loaded from there will be ignored. This way you can involve
the custom variable in compile-time expressions initializing other variables without fear that these derived values could be
incompatible with user's changes.
You can insert specially formatted comments into custom hash array initializers, describing the individual elements (keys):
key => value, # comment
# key => value, # comment
The second line does not, obviously, create any hash element, but it will still be copied into the customization file in order
to hint to the user that he may introduce such an element.
The rest of the rule file is compiled just like a usual perl script, with the outer lexical scope comprising the whole rule file.
There are some little details, however, you should be aware off:
The context at the beginning is package Apps::APP_NAME or package Modules::MOD_NAME . You may switch
to other packages as oft as necessary; to revert to the initial context you may use an abbreviation package
default;
The rule file is compiled with namespace mode enabled. This implies that our operator is
forbidden, and all variables must be declared.
You are invited to put packages with large amounts of code into separate perl module files, .pm . Each application and
module has a subdirectory perllib, where they will be found automatically when loaded via require or use from the rule
file. Be aware that these modules are compiled in namespace mode too, and the application
default package is put on the lookup list.