user_guide:tutorials:latest:perl_intro

Differences

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

Link to this comparison view

user_guide:tutorials:latest:perl_intro [2020/01/22 09:02] (current)
Line 1: Line 1:
 +====== Using Perl within polymake ======
 +
 +The language that the interactive version of ''​polymake''​ speaks is a dialect of Perl that we refer to as ''​polymake''/​Perl. See [[http://​www.perl.org|www.perl.org]] for comprehensive Perl information. Note also that the ordinary Perl manual pages are particularly useful, especially the perlintro man page which is also available on [[http://​perldoc.perl.org/​perlintro.html|perldoc]]. This short section here cannot be a replacement for a thorough introduction to this language, but we want to focus on a few key points that are relevant to ''​polymake''​.
 +
 +==== Standard data structures ====
 +
 +The Perl programming language originally provides three different data structures, scalars(''​$''​),​ arrays(''​@''​),​ and hashes(''​%%%%%''​). The user always has to specify the type of a variable using the appropriate symbol ''​$'',​ ''​@'',​ or ''​%%%%%''​. If you forget to do so, you will receive the following error message:
 +
 +<​code>​
 +> i=5;
 +polymake: ​ ERROR: Unquoted string "​i"​ may clash with future reserved word.
 +</​code>​
 +Here are some simple commands illustrating how to use the different data structures:
 +
 +== Scalars ==
 +
 +<code perl>
 +> $i=5;
 +> $j=6;
 +> $sum=$i+$j; print $sum;
 +11
 +</​code>​
 +== Arrays ==
 +
 +<code perl>
 +> @array=("​a","​b","​c"​);​ print scalar(@array);​
 +> push(@array,"​d"​);​ print "​@array"; ​
 +> $first_entry=$array[0];​ print $first_entry;​
 +> print join("​\n",​@array);​
 +> @array2=(3,​1,​4,​2);​
 +> print sort(@array2);​
 +3a b c daa
 +b
 +c
 +d1234
 +</​code>​
 +== Hashes ==
 +
 +<code perl>
 +> %hash=();
 +> $hash{"​zero"​}=0;​
 +> $hash{"​four"​}=4;​
 +> print keys %hash;
 +> print join(",​ ",keys %hash);
 +> print join(",​ ",​values %hash);
 +> %hash=("​one",​1,"​two",​2);​
 +> %hash=("​one"​=>​1,"​two"​=>​2);​
 +zerofourzero,​ four0, 4
 +</​code>​
 +==== polymake-Perl ====
 +
 +In addition to the three standard data structures, the enriched version of ''​Perl''​ used in ''​polymake''​ also provides special data structures for dealing with more complicated concepts. For an introduction to the polymake object model see [[.properties#​objects|here]].
 +
 +''​polymake'''​s object hierarchy is completely reflected on the Perl side. Let us create a small polytope as an example object.
 +
 +<code perl>
 +> $p = new Polytope(POINTS=>​[[1,​0,​1],​[1,​0,​-1],​[1,​1,​0],​[1,​-1,​0]]);​
 +</​code>​
 +Note that the ''​Perl''​-type of the variable ''​$p''​ is ''​Scalar'',​ as the variable is internally treated as a reference to a ''​C++''​-object. The true nature of the object becomes visible if it is printed:
 +
 +<code perl>
 +> print $p;
 +Polymake::​polytope::​Polytope__Rational=ARRAY(0x55f7a179be78)
 +</​code>​
 +In this case it is a ''​polymake''​ object from the application ''​polytope'',​ and it happens to be of type ''​Polytope<​Rational>''​. Technically,​ ''​$p''​ is a reference to an array (but it should be never treated as an array unless you are deliberately trying to crash ''​polymake''​). If you want less technical information on the type of your object, use this:
 +
 +<code perl>
 +> print $p->​type->​full_name;​
 +Polytope<​Rational>​
 +</​code>​
 +=== "Small objects":​ Data structures inherited from C++ ===
 +
 +You can use objects that are inherited from the ''​C++''​-side of ''​polymake''​ in the interactive shell. A complete list of so-called "small objects"​ can be found in the [[https://​polymake.org/​release_docs/​latest/​common.html|online documentation]] under the heading "​Property types"​. Here is a selection of three different structures that facilitate everyday work with ''​polymake'':​
 +
 +== Arrays ==
 +
 +The small object ''​Array''​ can be initialized in different ways and with different template parameters:
 +
 +<code perl>
 +> @array=("​a","​b","​c"​);​
 +> $arr1=new Array<​String>​(\@array);​ print $arr1;
 +> $arr2=new Array<​Int>​([3,​2,​5]);​ print $arr2;
 +> $arr3=new Array<​Int>​(0,​1,​2,​3);​ print $arr3;
 +> $arr4=new Array<​Int>​(0..4);​ print $arr4;
 +> $arr5=new Array<​Int>​($arr4);​ print $arr5;
 +a b c3 2 50 1 2 30 1 2 3 40 1 2 3 4
 +</​code>​
 +You have random access:
 +
 +<code perl>
 +> $arr5->​[0] = 100;
 +> print $arr5;
 +100 1 2 3 4
 +</​code>​
 +It is also possible to convert the ''​C++''​-object ''​Array''​ into a ''​Perl''​-array by writing
 +
 +<code perl>
 +> @arr4=@{$arr4};​ print $arr2;
 +3 2 5
 +</​code>​
 +or simply
 +
 +<code perl>
 +> @arr4=@$arr4;​
 +</​code>​
 +== Sets ==
 +
 +On ''​C++''​-side sets are stored in a balanced binary search (AVL) tree. For more information see the [[https://​polymake.org/​release_docs/​master/​PTL/​classpm_1_1Set.html|PTL-documentation]]. In many cases, the small objects can be converted into ''​Perl''​-types in the expected way:
 +
 +<code perl>
 +> $set=new Set<​Int>​(3,​2,​5);​ print $set;
 +> print $set->​size;​
 +> @array_from_set=@$set;​
 +{2 3 5}3
 +</​code>​
 +== Matrices ==
 +
 +Here is a simple way to initialize a matrix:
 +
 +<code perl>
 +> $mat=new Matrix<​Rational>​([[2,​1,​4,​0,​0],​[3,​1,​5,​2,​1],​[1,​0,​4,​0,​6]]);​
 +> print $mat;
 +2 1 4 0 0
 +3 1 5 2 1
 +1 0 4 0 6
 +</​code>​
 +You could also define it by passing a reference to an (''​Perl''​-)array of ''​Vectors''​. The single entries are interpreted as different rows:
 +
 +<code perl>
 +> $row1=new Vector<​Rational>​([2,​1,​4,​0,​0]);​
 +> $row2=new Vector<​Rational>​([3,​1,​5,​2,​1]);​
 +> $row3=new Vector<​Rational>​([1,​0,​4,​0,​6]);​
 +> @matrix_rows=($row1,​$row2,​$row3);​
 +> $matrix_from_array=new Matrix<​Rational>​(\@matrix_rows);​
 +</​code>​
 +You can change a single entry of a matrix in the following way (if it is not already assigned to an immutable property like ''​VERTICES''​!):​
 +
 +<code perl>
 +> $mat->​row(1)->​[1]=7;​
 +> print $mat->​row(1)->​[1],​ "​\n";​
 +> print $mat, "​\n";​
 +> $mat->​elem(1,​2)=8;​
 +> print $mat;
 +7
 +2 1 4 0 0
 +3 7 5 2 1
 +1 0 4 0 6
 +
 +2 1 4 0 0
 +3 7 8 2 1
 +1 0 4 0 6
 +</​code>​
 +A unit matrix of a certain dimension can be defined via the user-function ''​unit_matrix<​COORDINATE_TYPE>​(.)'':​
 +
 +<code perl>
 +> $unit_mat=4*unit_matrix<​Rational>​(3);​
 +> print $unit_mat;
 +(3) (0 4)
 +(3) (1 4)
 +(3) (2 4)
 +</​code>​
 +The reason for the "​strange output"​ is the implementation as //sparse matrix//:
 +
 +<code perl>
 +> print ref($unit_mat);​
 +Polymake::​common::​SparseMatrix_A_Rational_I_NonSymmetric_Z
 +</​code>​
 +However, some functions cannot deal with this special type of matrix. In this case it is necessary to transform the sparse matrix into a dense matrix first via:
 +
 +<code perl>
 +> $dense=new Matrix<​Rational>​($unit_mat);​print $dense;
 +4 0 0
 +0 4 0
 +0 0 4
 +</​code>​
 +or just
 +
 +<code perl>
 +> $dense2=dense($unit_mat);​print $dense2;
 +4 0 0
 +0 4 0
 +0 0 4
 +</​code>​
 +You can also work with matrices that have different types of coordinates like ''​Rational'',​ ''​Float'',​ or ''​Int'':​
 +
 +<code perl>
 +> $m_rat=new Matrix<​Rational>​(3/​5*unit_matrix<​Rational>​(5));​ print $m_rat, "​\n"; ​
 +> $m2=$mat/​$m_rat;​ print $m2, "​\n";​
 +> $m_int=new Matrix<​Int>​(unit_matrix<​Rational>​(5));​ print $m_int, "​\n";​
 +3/5 0 0 0 0
 +0 3/5 0 0 0
 +0 0 3/5 0 0
 +0 0 0 3/5 0
 +0 0 0 0 3/5
 +
 +2 1 4 0 0
 +3 7 8 2 1
 +1 0 4 0 6
 +3/5 0 0 0 0
 +0 3/5 0 0 0
 +0 0 3/5 0 0
 +0 0 0 3/5 0
 +0 0 0 0 3/5
 +
 +1 0 0 0 0
 +0 1 0 0 0
 +0 0 1 0 0
 +0 0 0 1 0
 +0 0 0 0 1
 +
 +</​code>​
 +Sometimes there is incompatible types:
 +
 +<​code>​
 +> $m3=$m_rat/​$m_int;​
 +</​code>​
 +C++/perl Interface module compilation failed; most likely due to a type mismatch. Set the variable $Polymake::​User::​Verbose::​cpp to a positive value and repeat for more details.
 +
 +The error message indicates that you need to convert the integer matrix to a rational matrix first:
 +
 +<code perl>
 +> $m3=$m_rat/​(convert_to<​Rational>​($m_int));​ print $m3;
 +3/5 0 0 0 0
 +0 3/5 0 0 0
 +0 0 3/5 0 0
 +0 0 0 3/5 0
 +0 0 0 0 3/5
 +1 0 0 0 0
 +0 1 0 0 0
 +0 0 1 0 0
 +0 0 0 1 0
 +0 0 0 0 1
 +</​code>​
 +By "/"​ you can add rows to a matrix, whereas "​|"​ adds columns. By the way, this also works for ''​Vector''​.
 +
 +<code perl>
 +> $z_vec=zero_vector<​Int>​($m_int->​rows);​
 +> $extended_matrix=($z_vec|$m_int);​ print $extended_matrix;​
 +0 1 0 0 0 0
 +0 0 1 0 0 0
 +0 0 0 1 0 0
 +0 0 0 0 1 0
 +0 0 0 0 0 1
 +</​code>​
 +It is also possible to nest template parameters in any way you like, e.g.
 +
 +<code perl>
 +> $set=new Set<​Int>​(3,​2,​5);​
 +> $template_Ex=new Array<​Set<​Int>>​((new Set<​Int>​(5,​2,​6)),​$set);​ print $template_Ex;​ print ref($template_Ex);​
 +{2 5 6}
 +{2 3 5}
 +Polymake::​common::​Array__Set__Int
 +</​code>​
 +However, if you use a template combination,​ you have never used before, it may take some time until you see the result. This is due to the fact that ''​polymake''​ compiles your new combination //on the fly//. But this is only a one-time effect, and next time you use this combination it will work without delay.
 +
 +=== "Big Objects":​ Objects with properties ===
 +
 +A big object is an instance of a data type which represents a mathematical concept with clear semantics. They may have template parameters.
 +
 +<code perl>
 +> $p=new Polytope<​Rational>​(POINTS=>​cube(4)->​VERTICES);​
 +> $lp=new LinearProgram<​Rational>​(LINEAR_OBJECTIVE=>​[0,​1,​1,​1,​1]);​
 +</​code>​
 +Big objects have properties which come with a type, which is either built-in or a small object type or a big object type, and which can be accessed using the ''​-``>''​ operator.
 +
 +<code perl>
 +> # access the property named `LP`:
 +> $p->​LP=$lp;​
 +> # properties can have properties themselves.
 +> print $p->​LP->​MAXIMAL_VALUE;​
 +4
 +</​code>​
 +Scalar properties can be used in arithmetic expressions right away.
 +
 +<code perl>
 +> $i = ($p->​N_FACETS * $p->​N_FACETS) * 15;
 +> print $i;
 +960
 +</​code>​
 +Check out the tutorial on properties to learn more about the way properties are used and computed.
 +
 +==== A small example script... ====
 +
 +...to demonstrate the usage of ''​polymake''/​Perl. You can download the matrix file {{:​points.demo| here}}.
 +
 +<code perl>
 +> ### load matrix from file
 +> open(INPUT, "< demo/​Workshop2011/​points.demo"​);​
 +> $matrix=new Matrix<​Rational>​(<​INPUT>​);​
 +> close(INPUT);​
 +> print $matrix;
 +
 +
 +> ### create a polytope from the matrix
 +> $p=new Polytope<​Rational>​(POINTS=>​$matrix);​
 +> print $p->​FACETS;​
 +> print $p->DIM;
 +> print $p->​VERTEX_SIZES;​
 +
 +
 +> ### print "​simple"​ vertices
 +> for(my $i=0;​$i<​scalar(@{$p->​VERTEX_SIZES});​$i++){
 +>     ​if($p->​VERTEX_SIZES->​[$i]==$p->​DIM){
 +>     print $i.": "​.$p->​VERTICES->​row($i)."​\n";​
 +>     }
 +> }
 +
 +
 +> ### put their indices in a set
 +> $s=new Set<​Int>​();​
 +> for(my $i=0;​$i<​scalar(@{$p->​VERTEX_SIZES});​$i++){
 +>     ​if($p->​VERTEX_SIZES->​[$i]==$p->​DIM){
 +>     ​$s+=$i;​
 +>     }
 +> }
 +
 +
 +> ### iterate the set in two different ways
 +> foreach(@{$s}){
 +>     print $p->​VERTICES->​row($_)."​\n";​
 +> }
 +> foreach my $index(@{$s}){
 +>     print $p->​VERTICES->​row($index)."​\n";​
 +> }
 +
 +
 +> ### create a minor of the vertices matrix that only contains the simple ones
 +> $special_points=$p->​VERTICES->​minor($s,​All);​ print $special_points;​
 +-1
 +</​code>​
 +==== Writing scripts ====
 +
 +Comprehensive information on how to use scripts within ''​polymake''​ can be found [[:​user_guide:​howto:​scripting|here]].
 +
  
  • user_guide/tutorials/latest/perl_intro.txt
  • Last modified: 2020/01/22 09:02
  • (external edit)