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
|
# Copyright (c) 1997-2024
# Ewgenij Gawrilow, Michael Joswig, and the polymake team
# Technische Universität Berlin, Germany
# https://polymake.org
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2, or (at your option) any
# later version: http://www.gnu.org/licenses/gpl.txt.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#-------------------------------------------------------------------------------
# @category Symmetry
# This represents a stacky fan built from the orbit of a fan F under a group G that permutes the homogeneous coordinates of F's rays.
#
# ****
# It is assumed, but currently not checked, that the interior of F does not intersect the interiors of its images.
# ****
declare object DisjointStackyFan<Scalar=Rational> [ is_ordered_field(Scalar) ] : PolyhedralFan<Scalar>;
object DisjointStackyFan {
# @category Symmetry
# The RAYS of the stacky fan that were used to generate it.
property GENERATING_RAYS : Matrix<Scalar>;
# @category Symmetry
# The number of RAYS of the stacky fan that were used to generate it.
# By the way orbit_fan works, these rays also show up at the beginning of the RAYS matrix.
property N_GENERATING_RAYS : Int;
# @category Symmetry
# The MAXIMAL_CONES of the fan that were used to generate it.
property GENERATING_MAXIMAL_CONES : IncidenceMatrix;
# @category Symmetry
# The HASSE_DIAGRAM of the fan that was used to generate it.
# Must be of type Sequential because Cone::HASSE_DIAGRAM has that type
property GENERATING_HASSE_DIAGRAM : Lattice<BasicDecoration, Sequential>;
# @category Symmetry
# From a fan F equipped with a symmetry group G acting on the coordinates,
# *** such that the interior of F does not intersect the interiors of its images,***
# calculate the faces of F of all dimensions that lie in distinct orbits of G.F
# The data is organized as an array, one entry for each dimension starting with 1;
# each entry is a Set, one for each orbit of that dimension;
# each entry is a Set<Set<Int>> of faces Set<Int> in that orbit that lie in F
property STACKY_FACES : Array<Set<Set<Set<Int>>>>;
rule STACKY_FACES : N_GENERATING_RAYS, COMBINATORIAL_DIM, HASSE_DIAGRAM {
my $ground_set = sequence(0, $this->N_GENERATING_RAYS);
my @orbit_restrictions;
for my $orbit_rank (1..$this->COMBINATORIAL_DIM+1) {
my $a = cones_action($this, $orbit_rank);
my $cones_of_dim = $this->HASSE_DIAGRAM->cones_of_dim($orbit_rank);
my $orbit_restrictions_in_dim = new Set<Set<Set<Int>>>;
foreach my $indexed_orbits (@{$a->ORBITS}) {
my $part_in_ground_set = new Set<Set<Int>>;
foreach my $cone_index (@{$indexed_orbits}) {
if (incl($cones_of_dim->[$cone_index], $ground_set) <= 0) {
$part_in_ground_set += $cones_of_dim->[$cone_index];
}
}
$orbit_restrictions_in_dim += $part_in_ground_set;
}
push @orbit_restrictions, $orbit_restrictions_in_dim;
}
$this->STACKY_FACES = new Array<Set<Set<Set<Int>>>>(\@orbit_restrictions);
}
# @category Symmetry
# Counts the number of STACKY_FACES
property STACKY_F_VECTOR : Vector<Int>;
rule STACKY_F_VECTOR : STACKY_FACES {
my @f = map { $_->size() } (@{$this->STACKY_FACES});
$this->STACKY_F_VECTOR = \@f;
}
# @category Symmetry
# Vertex labels as an array of Set<Set<Int>>.
# This is more efficient than the String type used in topaz::SimplicialComplex
property VERTEX_LABELS : Array<Set<Set<Int>>>;
# @category Symmetry
# for higher barycentric subdivisions, store the original RAYS_ACTION.GENERATORS
# They are stored outside of a GROUP object, because these generators act on the
# elements of the innermost sets of the VERTEX_LABELS, but not on anything
# directly in the object itself
property ORIGINAL_RAYS_ACTION_GENERATORS : Array<Array<Int>>;
}
# @category Symmetry
# Calculate the stacky, locally embedded fan associated to a Cone and a group acting on homogeneous coordinates.
# This function turns the input Cone C into a PolyhedralFan PF, calculates the orbit_fan OF of PF, and packages the data in OF into the data for a DisjointStackyFan. No additional computation is executed at this point.
# The terminology 'locally embedded' references the fact that each constituent cone comes with a local embedding into the ambient space of the original Cone, but the faces of the constituent cones may intersect in complicated ways due to the identifications induced by the group action.
#
# @param Cone C the input cone, equipped with a GROUP->HOMOGENEOUS_COORDINATE_ACTION
# @return DisjointStackyFan F representing the quotient of C by its group
# @example
# Consider the cone over the standard 2-simplex on which Z_2 acts by interchanging coordinates 0 and 1.
# > $c = new Cone(RAYS=>[[1,0,0],[0,1,0],[0,0,1]], GROUP=>new group::Group(HOMOGENEOUS_COORDINATE_ACTION=>new group::PermutationAction(GENERATORS=>[[1,0,2]])));
# The stacky fan defined by this cone identifies the rays 0 and 1.
# The property STACKY_FACES records the orbits under the group action:
# > $sf = stacky_le_fan($c);
# > print $sf->STACKY_FACES;
# | {{{0} {1}} {{2}}}
# | {{{0 1}} {{0 2} {1 2}}}
# > print $sf->STACKY_F_VECTOR;
# | 2 2
user_function stacky_le_fan<Scalar>(Cone<Scalar>) {
my ($c) = @_;
if ($c->lookup("GROUP")) {
my $f = new PolyhedralFan(RAYS=>$c->RAYS, MAXIMAL_CONES=>$c->RAYS_IN_FACETS, GROUP=>$c->GROUP);
my $of = orbit_fan($f, $f->GROUP->HOMOGENEOUS_COORDINATE_ACTION->GENERATORS);
return new DisjointStackyFan<Scalar>(GENERATING_RAYS=>$c->RAYS, N_GENERATING_RAYS=>$c->RAYS->rows, GENERATING_MAXIMAL_CONES=>$c->RAYS_IN_FACETS, GENERATING_HASSE_DIAGRAM=>$c->HASSE_DIAGRAM, GROUP=>$of->GROUP);
} else {
return new DisjointStackyFan<Scalar>(GENERATING_RAYS=>$c->RAYS, N_GENERATING_RAYS=>$c->RAYS->rows, GENERATING_MAXIMAL_CONES=>$c->RAYS_IN_FACETS, GENERATING_HASSE_DIAGRAM=>$c->HASSE_DIAGRAM);
}
}
# Local Variables:
# mode: perl
# cperl-indent-level: 3
# indent-tabs-mode:nil
# End:
|