tutorial:perl_continued

This is an old revision of the document!


This is a tutorial about how to use Perl within polymake, which was presented at the polymake-Workshop at Darmstadt, in March 2011. A short introduction to Perl in polymake can be found at “polymake for the Perl Newbie”.

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> polytope > 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> $i=5; $j=6; $sum=$i+$j; print $sum; </code> * Arrays <code> @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); </code> * Hashes <code> %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); </code>
===“Small objects”: Data structures inherited from C++=== In addition to the three standard data structures, the enriched version of
Perl used in polymake also provides special data structures that are inherited from the C++-side of polymake. A complete list of these so-called “small objects” can be found in the online documentation under the heading “Property types”. To define a Perl-variable of such a type, you initialize the variable via <code> $my_var=new [SMALL_OBJECT]([INITIALIZATION]); </code> Note that the Perl-type of the variable my_var is Scalar, as the variable is internally treated as a reference to a C++-object. You can find out the (C++-)type of your variable via <code> print ref($my_var); </code> 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> @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; </code> It is also possible to convert the C++-object Array into a Perl-array by writing <code> @arr4=@{$arr4}; print $arr2; </code> or simply<code> @arr4=@$arr4; </code> * Sets
On
C++-side sets are stored in a balanced binary search (AVL) tree. For more information see the PTL-documentation. In many cases, the small objects can be converted into Perl-types in the expected way: <code> $set=new Set<Int>(3,2,5); print $set; print $set→size; @array_from_set=@$set; </code> * Matrices
Here is a simple way to initialize a matrix:<code> $mat=new Matrix<Rational>(2,1,4,0,0],[3,1,5,2,1],[1,0,4,0,6); print $mat; </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> $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> $mat→row(1)→[1]=7; print $mat→row(1)→[1]; print $mat; $mat→(1,2)=8; print $mat; </code> A unit matrix of a certain dimension can be defined via the user-function unit_matrix<COORDINATE_TYPE>(.): <code> $unit_mat=4*unit_matrix<Rational>(3); print $unit_mat; </code> The reason for the “strange output” is the implementation as sparse matrix: <code> print ref($unit_mat); </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> $dense=new Matrix<Rational>($unit_mat);print $dense; </code> or just<code> $dense2=dense($unit_mat);print $dense2; </code> You can also work with matrices that have different types of coordinates like Rational, Float, or Int: <code> $m_rat=new Matrix<Rational>(3/5*unit_matrix<Rational>(5)); print $m_rat; $m2=$mat/$m_rat; print $m2; $m_int=new Matrix<Int>(unit_matrix<Rational>(5)); print $m_int; $m3=$m_rat/$m_int; </code> The error message <code> polymake: ERROR: undefined operator Matrix<Rational> / Matrix<Int> at input line 1. </code>indicates that you need to convert the integer matrix to a rational matrix first:<code> $m3=$m_rat/(convert_to<Rational>($m_int)); print $m3; </code> By “/” you can add rows to a matrix, whereas “|” adds columns. By the way, this also works for Vector.<code> $z_vec=zero_vector<Int>($m_int→rows); $extended_matrix=($z_vec|$m_int); print $extended_matrix; </code> It is also possible to nest template parameters in any way you like, e.g. <code> $set=new Set<Int>(3,2,5); $template_Ex=new Array<Set<Int»1),$set); print $template_Ex; print ref($template_Ex); </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

$p=new Polytope<Rational>(POINTS=>cube(4)->VERTICES);
$lp=new LinearProgram<Rational>(LINEAR_OBJECTIVE=>[0,1,1,1,1]);
$p->LP=$lp;
print $p->LP->MAXIMAL_VALUE;

Working with Perl in polymake

points.demo

open(INPUT, "< $HOME/polymake/demo/Workshop2011/points.demo");
$matrix=new Matrix<Rational>(<INPUT>);
close(INPUT);
print $matrix;

$p=new Polytope<Rational>(POINTS=>$matrix);
print $p->FACETS;
print $p->DIM;
print $p->VERTEX_SIZES;
;### choose "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";
    }
}
$s=new Set<Int>();
for(my $i=0;$i<scalar(@{$p->VERTEX_SIZES});$i++){
    if($p->VERTEX_SIZES->[$i]==$p->DIM){
	$s+=$i;
    }
}
$special_points=$p->VERTICES->minor($s,All); print $special_points;
;
foreach(@{$s}){
    print $p->VERTICES->row($_)."\n";
}
foreach my $index(@{$s}){
    print $p->VERTICES->row($index)."\n";
}

Scripts


1)
new Set<Int>(5,2,6
  • tutorial/perl_continued.1490544938.txt.gz
  • Last modified: 2017/03/26 16:15
  • by oroehrig