scripting:start

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Last revisionBoth sides next revision
scripting:start [2012/02/29 09:04] – [Using C++ objects] gawrilowscripting:start [2019/01/25 09:27] – ↷ Links adapted because of a move operation oroehrig
Line 65: Line 65:
  
 Special variables residing in the global package such as ''$_'', ''@_'', ''@ARGV'', ''@INC'', ''%ENV'', ''%SIG'', etc. don't need to be declared.  The package inheritance list ''@ISA'' and sort placeholders ''$a'' and ''$b'' are also exempt from declaration. Special variables residing in the global package such as ''$_'', ''@_'', ''@ARGV'', ''@INC'', ''%ENV'', ''%SIG'', etc. don't need to be declared.  The package inheritance list ''@ISA'' and sort placeholders ''$a'' and ''$b'' are also exempt from declaration.
 +
 +Variables can also be declared temporarily in scripts loaded by operator ''do'':
 +<code>declare local $bla=123;</code>
 +After the script has been executed, the variable disappears as if it were never declared, so that this script or other ones reusing the same variable name can safely be loaded again.  However, if the variable was already declared persistently beforehand, the effect of such local declaration is equivalent to a standard perl ''local'' operator, that is, its value will be temporarily changed but not the declaration status.  Please beware that this is a quite exotic feature introduced primarily for testing purposes.  In most cases, one-shot scripts should only create lexical variables and avoid injecting new names in namespaces.
  
 === Name lookup === === Name lookup ===
Line 89: Line 93:
 === Extending lookup scope === === Extending lookup scope ===
  
-Each package compiled from polymake source code possesses its own lookup list.  By default it consists of all enclosing packages, but can be easily extended by arbitrary further packages.  This is accomplished with a statement <code>using namespaces "OTHER_PACKAGE", ...;</code> put somewhere in the package being extended.  Please note that this a real function call, not a pragma, therefore it must be executed early enough to have effect on the package code.  The extension relation is transitive.+Each package compiled from polymake source code possesses its own lookup list.  By default it consists of all enclosing packages, but can be easily extended by arbitrary further packages.  This is accomplished with a statement <code>using namespaces "OTHER_PACKAGE", ...;</code> put somewhere in the package being extended.  Please note that this is a real function call, not a pragma, therefore it must be executed early enough to have effect on the package code.  The extension relation is transitive.
  
 This extension mechanism is involved, for example, in the process of importing applications: the application polytope imports everything from applications graph and common, so the lookup list for the package ''Polymake::polytope'' contains ''Polymake:::graph'' and ''Polymake::common'' along with the enclosing ''Polymake'' If some other application would import the application polytope, it would automatically inherit its entire lookup list. This extension mechanism is involved, for example, in the process of importing applications: the application polytope imports everything from applications graph and common, so the lookup list for the package ''Polymake::polytope'' contains ''Polymake:::graph'' and ''Polymake::common'' along with the enclosing ''Polymake'' If some other application would import the application polytope, it would automatically inherit its entire lookup list.
Line 129: Line 133:
 The standard ''local'' operator is very useful as it allows to make exception-safe temporary changes.  polymake enhances this functionality in two aspects: The standard ''local'' operator is very useful as it allows to make exception-safe temporary changes.  polymake enhances this functionality in two aspects:
    -- ''local'' works with package variables only.  Using new functions ''local_scalar'', ''local_array'', ''local_hash'', and ''local_sub'', you can temporarily modify each data type passed by reference too:\\ ''$a=[1,2];''\\ ''local_array($a, [3,4]);''    -- ''local'' works with package variables only.  Using new functions ''local_scalar'', ''local_array'', ''local_hash'', and ''local_sub'', you can temporarily modify each data type passed by reference too:\\ ''$a=[1,2];''\\ ''local_array($a, [3,4]);''
-   .. There are further functions doing temporary changes, which are reverted on leaving the block scope:\\ ''local_incr($scalar, number)'' -- add a number\\ ''local_shift(\@array)'' -- hide the first element\\ ''local_pop(\@array)'' -- hide the last element \\ ''local_shorten(\@array, n)'' -- hide abs(n) elements at the front (n>0) or back (n<0) end\\ ''local_unshift(\@array, list)'' -- prepend elements\\ ''local_push(\@array, list)'' -- append elements \\ ''local_swap(\@array, i1, i2)'' -- exchange two elements with given indices+   .. There are further functions doing temporary changes, which are reverted on leaving the block scope:\\ ''local_incr($scalar, number)'' -- add a number\\ ''local_shift(\@array)'' -- hide the first element\\ ''local_pop(\@array)'' -- hide the last element \\ ''local_clip_front(\@array, n)'' -- hide elements at the front so that the element [n] becomes the first one\\ ''local_clip_back(\@array, n)'' -- hide elements at the end so that the element [n] becomes the last one\\ ''local_unshift(\@array, list)'' -- prepend elements\\ ''local_push(\@array, list)'' -- append elements \\ ''local_swap(\@array, i1, i2)'' -- exchange two elements with given indices\\ ''%%local_bless($object, "Package" or \%Package::)%%'' -- change the type of an object
    -- You can postpone the reverting actions to an outer enclosing block scope, even located in a different subroutine.  You create a special guard object in the outer scope and pass it to other subroutines.  All temporary modifications remain in effect until the guard object is destroyed:    -- You can postpone the reverting actions to an outer enclosing block scope, even located in a different subroutine.  You create a special guard object in the outer scope and pass it to other subroutines.  All temporary modifications remain in effect until the guard object is destroyed:
    .. <code>    .. <code>
Line 147: Line 151:
    .. All ''local_XXX'' functions described above can be used in the block ''begin_locals'' .. ''end_locals'' too.    .. All ''local_XXX'' functions described above can be used in the block ''begin_locals'' .. ''end_locals'' too.
    .. There is one session-scope guard dwelling in the variable ''$Polymake::Scope'' (aka ''$Scope'' due to namespace lookup rules).  Its lifetime ends with the complete interpretation of the current input line in the interactive shell, or complete execution of the script started in [[#calling|batch mode]].  This guard is used, among others, by [[:general#preferences|prefer_now]] commands, as well as for purging temporary properties from the objects.    .. There is one session-scope guard dwelling in the variable ''$Polymake::Scope'' (aka ''$Scope'' due to namespace lookup rules).  Its lifetime ends with the complete interpretation of the current input line in the interactive shell, or complete execution of the script started in [[#calling|batch mode]].  This guard is used, among others, by [[:general#preferences|prefer_now]] commands, as well as for purging temporary properties from the objects.
- 
-=== Classes === 
  
 ===== Most important interfaces ===== ===== Most important interfaces =====
Line 195: Line 197:
 === Name and Description === === Name and Description ===
  
-The name is supposed to be a short string distinguishing the object from all others, but its uniqueness is neither enforced nor checked.  The name appears in the drawings, where appropriate, as part of drawable object identifiers (in visualization engines supporting it, e.g. povray or javaview).  The name is also included as the stem into the default file name if the object is to be stored in a file.+The name is supposed to be a short string distinguishing the object from all others, but its uniqueness is only required for multiple subobjects (described further below).  The name appears in the drawings, where appropriate, as part of drawable object identifiers (in visualization engines supporting it, e.g. povray or javaview).  The name is also included as the stem into the default file name if the object is to be stored in a file.
  
 The name is optional; however, if a unnamed new object is assigned to a non-local variable (like this: ''$p=new Polytope(...);'' or ''$c=cube(3);'' then the variable name is used as the object name too. The name is optional; however, if a unnamed new object is assigned to a non-local variable (like this: ''$p=new Polytope(...);'' or ''$c=cube(3);'' then the variable name is used as the object name too.
Line 243: Line 245:
   ? ''%%$p->take("FACETS_THRU_VERTICES", temporary, $F);%%''   ? ''%%$p->take("FACETS_THRU_VERTICES", temporary, $F);%%''
   :: creates a property temporarily.  It survives until the end of the execution cycle.  In the interactive mode, the cycle ends after the complete evaluation of the last input line; in scripting mode it is the termination of the script.  Under no circumstances can temporary values be stored in the XML file; an explicit ''save'' of the object discards the temporary values instantly.  However, please note the difference to older versions of polymake: now it's a concrete value that can be declared as temporary, while earlier it was an inherent attribute of a property.   :: creates a property temporarily.  It survives until the end of the execution cycle.  In the interactive mode, the cycle ends after the complete evaluation of the last input line; in scripting mode it is the termination of the script.  Under no circumstances can temporary values be stored in the XML file; an explicit ''save'' of the object discards the temporary values instantly.  However, please note the difference to older versions of polymake: now it's a concrete value that can be declared as temporary, while earlier it was an inherent attribute of a property.
-  ? ''%%$p->remove("POINTS_IN_FACETS");%%'' +  ? ''%%$p->remove("POINTS_IN_FACETS", ...);%%'' 
-  :: removes a property from the object.  A //mutable// property can be removed at any time.  A normal property may be removed only if the object contains enough data to reconstruct this property later.  A production rule may remove a property only if it is one of its sources.+  :: removes one or more properties from the object.  A //mutable// property can be removed at any time.  A normal property may be removed only if the object contains enough data to reconstruct this property later.  A production rule may remove a property only if it is one of its sources.
  
 Methods ''give'' and ''take'' do exactly the same as the operations using the unquoted property name as a method.  The only difference lies in small additional costs for the former caused by property name lookup performed in each call.  Thus you should generally prefer the direct property-named methods unless your code must handle flexible property names. Methods ''give'' and ''take'' do exactly the same as the operations using the unquoted property name as a method.  The only difference lies in small additional costs for the former caused by property name lookup performed in each call.  Thus you should generally prefer the direct property-named methods unless your code must handle flexible property names.
Line 265: Line 267:
   ? ''%%$p->GRAPH->ADJACENCY=$a;%%''   ? ''%%$p->GRAPH->ADJACENCY=$a;%%''
   ? ''%%$p->take("GRAPH.ADJACENCY", $a);%%''   ? ''%%$p->take("GRAPH.ADJACENCY", $a);%%''
-  :: creates a property in a subobject; the same constrains apply as in the simple case above.+  :: creates a property in a subobject; the same constraints apply as in the simple case above.
   ? ''%%$p->GRAPH->remove("NODE_DEGREES");%%''   ? ''%%$p->GRAPH->remove("NODE_DEGREES");%%''
   ? ''%%$p->remove("GRAPH.NODE_DEGREES");%%''   ? ''%%$p->remove("GRAPH.NODE_DEGREES");%%''
-  :: removes a property in a subobject.+  :: removes a property in a subobject.  The same restriction apply here: either the property must be //mutable//, or the object must have enough data to reconstruct it later. 
 +  ? ''%%$p->remove("GRAPH")%%'' 
 +  :: removes the complete subobject.  The restriction about being mutable or reconstructible applies to all properties of this subobject, also recursively to all deeper subobjects.
  
 One can also create a subobject property from a complete object like this: One can also create a subobject property from a complete object like this:
Line 278: Line 282:
 === Multiple subobjects === === Multiple subobjects ===
  
-While normal (singular) subobjects are treated much like other properties, multiple subobjects require special methods capable of choosing the desired instance or iterating over them all.+While normal (singular) subobjects are treated much like other properties, multiple subobjects require special methods capable of choosing the desired instance or iterating over them all.  Multiple subobject instances must have non-empty, unique names; uniqueness (among all instances of the same property in one parent object) is enforced. 
 + 
 +== Construction of multiple subobjects ==
  
 The method ''add'' is used for creating and/or attaching multiple subobjects to the parent.  It has several flavors, resembling the construction modes of top-level objects: The method ''add'' is used for creating and/or attaching multiple subobjects to the parent.  It has several flavors, resembling the construction modes of top-level objects:
  
   ? ''%%$lp=$p->add("LP");%%''   ? ''%%$lp=$p->add("LP");%%''
-  :: creates a new empty subobject to be consequently filled with initial properties+  :: creates a new empty subobject to be consequently filled with initial properties.  Its name will be of the form "unnamed#NN".
   ? ''%%$lp=$p->add("LP", LINEAR_OBJECTIVE => Vector, ...);%%''   ? ''%%$lp=$p->add("LP", LINEAR_OBJECTIVE => Vector, ...);%%''
   :: creates a new subobject and initializes it with given properties. No further immutable properties can be added to it afterwards.   :: creates a new subobject and initializes it with given properties. No further immutable properties can be added to it afterwards.
 +  ? ''%%$lp=$p->add("LP", "name", ...);%%''
 +  :: creates a new subobject with a desired name.  If there is already another sibling subobject with identical name, the name will be amended with a suffix #NN in order to ensure its uniqueness.
   ? ''%%$my_tr=$p->add("TRIANGULATION", $tr);%%''   ? ''%%$my_tr=$p->add("TRIANGULATION", $tr);%%''
   :: takes an existing object ''$tr'' and attach it as a subobject.  Usually, the object ''$tr'' itself will become a property of ''$p'', but in some cases, as explained above, a copy will be created.  The return value is always the child subobject of ''$p''.   :: takes an existing object ''$tr'' and attach it as a subobject.  Usually, the object ''$tr'' itself will become a property of ''$p'', but in some cases, as explained above, a copy will be created.  The return value is always the child subobject of ''$p''.
Line 293: Line 301:
 In any flavor, you can add an option ''temporary'' directly after the name of the property, specifying that the subobject is to be added temporarily. In any flavor, you can add an option ''temporary'' directly after the name of the property, specifying that the subobject is to be added temporarily.
  
-Having added a subobject, you can retrieve it later using numerous search criteria.  Some of the retrieval methods can even create new subobject on the fly, as described in the corresponding remarks:+**Note:** For the sake of convenience, the very first instance of multiple subobject may be created in the same manner as singular subobjects, that is, using ''take()'', providing initial property values in the constructor list, or assigning values to property access methods during the initialization phase. 
  
 +== Examining multiple subobjects ==
 +
 +Having added a subobject instance, you can retrieve it later using numerous search criteria.  Some of the retrieval methods can even create a new subobject on the fly, as described in the corresponding remarks:
 +
 +  ? ''%%$p->LP%%''
 +  ? ''%%$p->give("LP.MAXIMAL_VALUE")%%''
 +  :: access the default subobject instance, that is, a subobject with ordinal number 0.  If no subobject of the requested type exists and there are production rules creating new instances, plans the cheapest rule chain and returns a new instance.
   ? ''%%$p->LP->[$i]%%''   ? ''%%$p->LP->[$i]%%''
-  :: select the subobject by its ordinal number+  ? ''%%$p->give("LP")->[$i]%%'' 
 +  :: select the subobject instance by its ordinal number
   ? ''%%$p->LP("name")%%''   ? ''%%$p->LP("name")%%''
   ? ''%%$p->give("LP", "name")%%''   ? ''%%$p->give("LP", "name")%%''
   :: select the subobject by its name; if no match found, returns ''undef''   :: select the subobject by its name; if no match found, returns ''undef''
 +  ? ''%%$p->LP(sub { $_->MAXIMAL_VALUE >= 0 })%%''
 +  ? ''%%$p->give("LP", sub { $_->MAXIMAL_VALUE >= 0 })%%''
 +  :: select the first subobject satisfying the filter expression; if none satisfies the criteria, returns ''undef''. The subobject under test is passed in the variable ''$_'' .
   ? ''%%$p->SCHLEGEL_DIAGRAM(FACET => 1, ...)%%''   ? ''%%$p->SCHLEGEL_DIAGRAM(FACET => 1, ...)%%''
   ? ''%%$p->give("SCHLEGEL_DIAGRAM", FACET => 1)%%''   ? ''%%$p->give("SCHLEGEL_DIAGRAM", FACET => 1)%%''
Line 305: Line 324:
   ? ''%%$p->give("SCHLEGEL_DIAGRAM", FACET => 1, temporary)%%''   ? ''%%$p->give("SCHLEGEL_DIAGRAM", FACET => 1, temporary)%%''
   :: the same as above, but in the non-match case the new subobject will be created temporarily   :: the same as above, but in the non-match case the new subobject will be created temporarily
-  ? ''%%$p->SCHLEGEL_DIAGRAM%%'' 
-  ? ''%%$p->give("SCHLEGEL_DIAGRAM")%%'' 
-  :: if there are many instances, retrieves a random one; if none exists and there are suitable production rules, a new subobject will be created. 
   ? ''%%foreach $lp (@{$p->LP}) { ... }%%''   ? ''%%foreach $lp (@{$p->LP}) { ... }%%''
-  :: iterates over all subobjects +  :: iterates over all existing instances 
-  ? ''%%$p->remove($lp);%%'' +  ? ''%%$p->LP->list_names%%'' 
-  :: removes the given instance of a multiple subobject.  Please note the difference to the operation ''%%$p->remove("LP")%%'', which would remove //all// subobjects attached as a LP property.+  :: returns the list of names of all existing instances 
 +  ? ''%%$p->LP(...)->select_as_default%%'' 
 +  :: permanently makes the selected instance the default one, which simply means moving it at the front of the instance list 
 +  ? ''%%$p->LP(...)->select_as_default_now%%'' 
 +  :: temporarily makes the selected instance the default one; the change is reverted at the end of the current user cycle 
 + 
 +== Removing multiple subobjects == 
 + 
 +  ? ''%%$p->remove($lp, ...);%%'' 
 +  :: removes the given instance of a multiple subobject.  Several instances may be removed at once. 
 +  ? ''%%$p->remove("LP");%%'' 
 +  .. removes //all// subobjects attached as a LP property.
  
 === Rule planning === === Rule planning ===
Line 360: Line 387:
   :: gets a type of an Object   :: gets a type of an Object
   ? ''%%$t=typeof Polytope<Rational>;%%''   ? ''%%$t=typeof Polytope<Rational>;%%''
-  :: constructs a literally specified type+  :: constructs a literally specified type; it must be known in the current application.
   ? ''%%$t=Polytope->type($t2->type);%%''   ? ''%%$t=Polytope->type($t2->type);%%''
   :: constructs a type with dynamic parameters   :: constructs a type with dynamic parameters
 +  ? ''%%$t=application->eval_type($string);%%''
 +  :: constructs a type specified by its full name in string form, e.g. ''%%$string="Polytope<Rational>";%%''
 +  .. The type must be known in the current application.
 +  ? ''%%$t=application("appname")->eval_type($string);%%''
 +  :: constructs a type defined in the specified application.
   ? ''%%$t->isa("Polytope")%%''   ? ''%%$t->isa("Polytope")%%''
   ? ''%%$t->isa($t2)%%''   ? ''%%$t->isa($t2)%%''
Line 404: Line 436:
 ==== Common operations ==== ==== Common operations ====
  
-Almost all C++ classes wrapped in polymake have an automatic conversion to character strings, allowing to print them directly to the screen or write into text files.  Also almost all classes have comparison operators == != , and if they support full ordering, all other comparison operators < > <= >= as well.+Almost all C++ classes wrapped in polymake have an automatic conversion to character strings, allowing to print them directly to the screen or write into text files.  Also almost all classes have comparison operators ''%%== !=%%'' , and if they support full ordering, all other comparison operators ''%%< > <= >=%%'' as well.
  
 ==== Numbers ==== ==== Numbers ====
Line 445: Line 477:
   0 1/2 1 0 3/4 -5/6 0   0 1/2 1 0 3/4 -5/6 0
  
-Classes Vector and SparseVector should be only used with numerical element types, because they overload all possible arithmetic operators.  Class Array is a normal random-access container, which does not impose any requirements on the type of its elements.+Classes Vector and SparseVector should only be used with numerical element types, because they overload all possible arithmetic operators.  Class Array is a normal random-access container, which does not impose any requirements on the type of its elements.
  
 ==== Matrices ==== ==== Matrices ====
Line 483: Line 515:
 ==== Complex objects ==== ==== Complex objects ====
  
-Some more complex objects like Graphs or Polynomials are also wrapped for directed use from perl code.  Please refer to the release documentation and the [[tutorial:start|tutorials]] for more details.+Some more complex objects like Graphs or Polynomials are also wrapped for directed use from perl code.  Please refer to the release documentation and the [[user_guide:start|tutorials]] for more details.
 ===== Debugging ===== ===== Debugging =====
  
-You can use the perl debugger to debug your scripts.  The only problem is how to set the initial breakpoint into your script: When you start polymake under the debugger <code>perl -dS polymake</code> not only your script, but also all the applications and even a part of the polymake core modules are still not loaded.  Stepping through polymake bootstrap is **very** tedious.  A much more convenient way is to insert a call to ''stop_here();'' at the very beginning of your script.  This little function does nothing but prints its arguments to STDOUT.  And it has a big advantage to be defined directly in the polymake main script, so you can just enter+You can use the perl debugger to debug your scripts.  The only problem is how to set the initial breakpoint into your script: When you start polymake under the debugger <code>perl -dS polymake</code> not only your script, but also all the applications and even some of the polymake core modules are still not loaded.  Stepping through polymake bootstrap is **very** tedious.  A much more convenient way is to insert a call to ''stop_here();'' at the very beginning of your script.  This little function does nothing but prints its arguments to STDOUT.  And it has a big advantage to be defined directly in the polymake main script, so you can just enter
   b stop_here   b stop_here
   c   c