File: cyclic.pl

package info (click to toggle)
polymake 4.14-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 35,888 kB
  • sloc: cpp: 168,933; perl: 43,407; javascript: 31,575; ansic: 3,007; java: 2,654; python: 632; sh: 268; xml: 117; makefile: 61
file content (202 lines) | stat: -rw-r--r-- 6,770 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#########################################################
# ------------------------------------------------------
# This script contains functions for working with
# series of core points with respect to 
# cyclic groups of even order.
# ---
# A circulant matrix is a matrix generated by one 
# vector which is shifted in each row by one position.
# The resulting vectors are the elements of the orbit
# of the generating vector under the cyclic group
# acting on the coordinates.
#
# Cyclic groups (of even order) have infinite core sets.
# This can be shown by describing an infinite series of
# core points in one 1-layer, for instance, in H_{1,1}.
# Two different constructions of such series are
# realized by the functions 
#  - infinite_cp_series_one_dir
#  - infinite_cp_series_mult_dir
#
# The function 'nested_C4' produces a certain point
# whose NOP-graph (see object OrbitPolytope) is a
# path ending in some core point with respect to C4.
#
# ------------------------------------------------------
# subs:
# - circulant($vec)
# - circ_vec($l, $params_ref)
# - random_vec($l,$limit)
# - circ_rank_test($l_low, $l_high, $limit)
# - infinite_cp_series_one_dir($l, $m_low, $m_up)
# - infinite_cp_series_mult_dir($even_params_ref)
# - nested_C4($a, $b, $r)
# ------------------------------------------------------
#########################################################


# Produces a circulant matrix from the given vector //vec//.
# @param Vector vec the generating vector for the circulant matrix
# @return Matrix the circulant matrix corresponding to //vec//
sub circulant {
    my $vec = $_[0];
    my $n = $vec->dim;
    my $circ = new Matrix ($n,$n);
    for ( my $i=0; $i < $n; ++$i ) {
	for ( my $j=0; $j < $n; ++$j ) {
	    my $ind =  ($j-$i) % $n;
	    $circ->[$i]->[$j] = $vec->[$ind];
	}	
    }
    return $circ;
}


# Help function.
# Constructs a vector of the form
# z=e_1+\sum_{j_1}^{2l-2} k_jw_j
# where w_j = e_j-e_{j+2}.
# The parameters k_j are stored in the array params.
# @param Int l defines the dimension 2*l of the vector (no homogenization!)
# @param arrayref params_ref the parameters k_j
# @return Vector the generated vector 
sub circ_vec {
    my ($l, $params_ref) = @_;
    if ( $l < 2 ) {
	die "circ_vec: l must be greater than 1!";
    }
    if ( scalar(@$params_ref) != 2*($l-1) ) {
	die "circ_vec: wrong number of parameters!";
    }
    my $vec = new Vector(2*$l);
    $vec->[0] = 1 + $params_ref->[0];
    $vec->[1] = $params_ref->[1];
    for (my $i = 2; $i < 2*($l-1); ++$i) {
	$vec->[$i] = $params_ref->[$i] - $params_ref->[$i-2];
    }
    $vec->[2*$l-2] = -$params_ref->[2*$l-4];
    $vec->[2*$l-1] = -$params_ref->[2*$l-3];
    return $vec;
}


# Help function.
# Constructs a list of random parameters k_j
# e.g. for the function circ_vec for a given length of
# 2//l//-2. The random number between 0 and 1 is scaled 
# by //limit//.
# @param Int l defines the dimension 2*l-2 of the list
# @param Int limit the factor by which the random numbers are scaled
# @return arrayref a reference to an array of random parameters
sub random_vec {
    my ($l,$limit) = @_;
    my @params = ();
    for (my $i=0; $i<2*($l-1); ++$i) {
	my $random_number = rand();
	push(@params,(new Int(rand()*$limit)));
    }
    return \@params;
}


# Tests the ranks of circulant matrices of randomly generated
# vectors of the form described in the function circ_vec.
# The dimension of the generating vector varies between
# //l_low// and //l_high//. The parameter //limit// refers
# to the scaling factor for the randomly generated
# parameters k_j, see Function random_vec.
# @param Int l_low defines the lower limit of the dimension (l>1)
# @param Int l_high defines the upper limit of the dimension
# @param Int limit the factor by which the random numbers are scaled
# @return OUTPUT produces a warning if a matrix does not have full rank;
#                otherwise it prints "." for every successful test
sub circ_rank_test {
    if ( $l < 2 ) {
	die "circ_rank_test: l must be greater than 1!";
    }
    my ($l_low, $l_high, $limit) = @_;
    for (my $l=$l_low; $l<=$l_high; ++$l) {
	my $v=circ_vec($l,random_vec($l,$limit));
	my $m=circulant($v);
	if (rank($m)==2*$l) {
	    print ".";
	} else {
	    print "\n Circulant of [$v] does not have full rank! \n";	    
	}
	if ($l % 10 == 0) {
	    print "\n";
	}
    }
}


#---------------------------------------
# Orbit polytopes with respect to C_2l
#---------------------------------------

# Produces members of an infinite series of core points
# 'in one direction' with respect to the cyclic group of order 2//l//.
# The points are of the form
# z=e_1+m*w
# where w=sum_{i=1}^l(e_{2i-1}-e_{2i}).
# All points for m between //m_low// and //m_up// are produced.
# @param Int l defines the dimension 2*l of the core points
# @param Int m_low the lower limit for the parameter m
# @param Int m_up the upper limit for the parameter m
# @return Matrix a matrix of core points for C_2l
sub infinite_cp_series_one_dir {
    my ($l, $m_low, $m_up) = @_;
    my $z0 = new Vector(1 | unit_vector<Rational>(2*$l,0));
    my $w = new Vector(2*$l+1);
    $w->[0] = 0;
    foreach (1..$l) {
	$w->[2*$_-1] = 1;
	$w->[2*$_] = -1;
    }
    my @cps = ();
    for (my $m = $m_low; $m <= $m_up; ++$m) {
	push(@cps,($z0 + $m*$w));
    }
    return new Matrix(\@cps);
}


# Produces a point of an infinite series of core points
# 'in multiple directions' with respect to the cyclic group of order 2//l//.
# The point is of the form
# z=e_1+\sum_{j_1}^{2l-2} k_jw_j
# where w_j = e_j-e_{j+2} (compare circ_vec). For odd j, the parameter k_j
# is set to zero. The list of even_params only specifies the parameters k_j
# for even j.
# @param arrayref even_params_ref the parameters k_j for even j
# @return Vector a core point in the infinite series
sub infinite_cp_series_mult_dir {
    my ($even_params_ref) = @_;
    my @even_params = @$even_params_ref;
    my @params = ();
    foreach (@even_params) {
	push(@params,0);
	push(@params,$_);
    }
    return new Vector(1|circ_vec(scalar(@even_params)+1,\@params));
}


# Generates a point of the form 
# z=e_1+m_1*w_1+m_2*w_2
# where w_j = e_j-e_{j+2} (compare circ_vec) and the m_i  
# are dependent of the input parameters //a//, //b//, and //r//. 
# Note that the NOP-graph of z is a path, and the orbit polytopes
# of all points corresponding to (a,b,x) with x<r are nested
# in the orbit polytope of z with respect to C4.
# @param Int a the parameter 'a'
# @param Int b the parameter 'b'
# @param Int r the parameter 'r'
# @return Vector the constructed point z
sub nested_C4 {
    my ($a, $b, $r) = @_;
    my $m1 = (2*$r+1)*$a + $r;
    my $m2 = (2*$r+1)*$b;
    my @params = ($m1, $m2);
    return new Vector(1|circ_vec(2,\@params)); 
}