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 [2013/08/23 21:18] – [Vectors] 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 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]%%''
   ? ''%%$p->give("LP")->[$i]%%''   ? ''%%$p->give("LP")->[$i]%%''
-  :: select the subobject by its ordinal number+  :: 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 306: 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 489: 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