File: Permutation.pm

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 (204 lines) | stat: -rw-r--r-- 7,712 bytes parent folder | download | duplicates (2)
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
203
204
#  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.
#-------------------------------------------------------------------------------

use strict;
use namespaces;
use warnings qw(FATAL void syntax misc);

package Polymake::Core::Permutation;

use Polymake::Struct (
   [ '@ISA' => 'Property' ],
   [ '$flags' => 'Flags::is_subobject | Flags::is_permutation' ],
   '%sensitive_props',                  # Property->key => Recovery  or  { $sub_key }->{ Property }-> ... -> Recovery
                                        # if there are rules transferring Property from the permuted subobject back into the basis
   '%sub_permutations',                 # Property->key (subobject) => Property (permutation)
   '%parent_permutations',              # Property->key (parent object) => ... => $sub_key => [ Property (permutation) ]
);

sub new {
   my $self=&_new;
   $self->type=$self->type->create_derived($self, $self->belongs_to);
   unless ($self->type->abstract) {
      $self->accept=\&accept_subobject;
      $self->flags |= Flags::is_concrete;
   }
   $self;
}

sub change_to_augmented {
   my ($self, $augm) = @_;
   if ($augm != $self->type->super->[0]) {
      $self->type->modify_super(0, 1, $augm);
   }
}

sub update_pure_type {
   my ($self, $proto) = @_;
   $self->type = $proto->create_derived($self, $self->belongs_to);
}

####################################################################################

declare $sub_key = \(1);         # singular key values used in sensitive_props
declare $is_non_recoverable = \(2);

# Rule => true if it is a recovering rule for a permuted property
sub analyze_rule {
   my ($self, $rule) = @_;
   my ($regular_out_seen, $perm_out_seen);
   foreach my $output (@{$rule->output}) {
      if (@$output == 1) {
         my $prop = $output->[0];
         if ($rule->code == \&Rule::nonexistent) {
            if ($enable_plausibility_checks && is_object($self->sensitive_props->{$prop->key})) {
               croak( "recovery of property ", $prop->name, " was enabled prior to this rule definition" );
            }
            $self->sensitive_props->{$prop->key} = $is_non_recoverable;
         } else {
            if ($enable_plausibility_checks && $self->sensitive_props->{$prop->key} == $is_non_recoverable) {
               croak( "recovery of property ", $prop->name, " was disabled prior to this rule definition" );
            }
            my $recovery = ($self->sensitive_props->{$prop->key} //= new Recovery($self, $prop));
            $rule->defined_for->add_producers_of($recovery, $rule);
         }
         $regular_out_seen = true;
      } else {
         if ($enable_plausibility_checks && get_array_flags($output) & Flags::is_multiple_new) {
            croak( "Rule dealing with permutations may not create new multiple subobjects" );
         }
         my $perm_pos = find_first_in_path($output, Flags::is_permutation);
         if ($perm_pos >= 0) {
            if ($perm_pos == 0) {
               if ($enable_plausibility_checks && $output->[0] != $self) {
                  croak( "dependence between two different permutation subobjects on the same level is not allowed" );
               }
            } else {
               add_sub_permutation($self, @$output[0..$perm_pos]);
            }
            $perm_out_seen = true;
         } else {
            add_sensitive_sub_property($self, @$output, $rule);
            $regular_out_seen = true;
         }
      }
   }
   if ($perm_out_seen && $regular_out_seen) {
      croak( "A production rule can't create properties in the base object and permutation subobject at the same time" );
   }
   $regular_out_seen
}
####################################################################################
sub descend_and_create {
   my $hash = shift;
   my $prop = pop;
   foreach $prop (@_) {
      $hash = ($hash->{$sub_key}->{$prop->key} //= { });
   }
   ($hash, $prop)
}
####################################################################################
# private:
sub add_sensitive_sub_property {
   my $self = shift;
   my $rule = pop;
   my ($hash, $prop) = descend_and_create($self->sensitive_props, @_);
   if ($rule->code == \&Rule::nonexistent) {
      if ($enable_plausibility_checks && is_object($hash->{$prop->key})) {
         croak( "recovery of property ", $prop->name, " was enabled prior to this rule definition" );
      }
      $hash->{$prop->key} = $is_non_recoverable;
   } else {
      if ($enable_plausibility_checks && $hash->{$prop->key} == $is_non_recoverable) {
         croak( "recovery of property ", $prop->name, " was disabled prior to this rule definition" );
      }
      my $recovery = ($hash->{$prop->key} //= new Recovery($self, $prop, @_));
      $rule->defined_for->add_producers_of($recovery, $rule);
   }
}
####################################################################################
# parent Permutation, (path to subobject permutation Property) =>
sub add_sub_permutation {
   my $self = shift;
   my $sub_permutation = pop;
   my ($hash, $prop) = descend_and_create($self->sub_permutations, @_);
   if (exists $hash->{$prop->key}) {
      $hash->{$prop->key} == $sub_permutation or
      croak( "ambiguous permutation propagation into ", join(".", map { $_->name } @_, $prop), " : ",
             $sub_permutation->name, " vs. ", $hash->{$prop->key}->name );
   }

   $hash->{$prop->key} = $sub_permutation;
   # provide for transitive closure
   $hash->{$sub_key}->{$prop->key} = $sub_permutation->sub_permutations;

   # establish reversed relation
   $hash = $sub_permutation->parent_permutations;
   foreach my $parent_prop ($prop, reverse @_) {
      $hash = ($hash->{$parent_prop->key} //= { });
   }
   push @{$hash->{$sub_key}}, $self;
}
####################################################################################
# ( Property, ... ) => Recovery
sub find_sensitive_sub_property {
   my $self = shift;
   my $prop = pop;
   my $hash = $self->sensitive_props;
   foreach $prop (@_) {
      defined($hash = $hash->{$sub_key}) or return;
      defined($hash = $hash->{$prop->key}) or return;
   }
   $hash->{$prop->key}
}
####################################################################################
sub find_sub_permutation {
   my $self = shift;
   my $prop = pop;
   my $hash = $self->sub_permutations;
   foreach $prop (@_) {
      defined($hash = $hash->{$sub_key}) or return;
      defined($hash = $hash->{$prop->key}) or return;
   }
   $hash->{$prop->key}
}

####################################################################################
package Polymake::Core::Permutation::Recovery;

use Polymake::Struct (
   [ new => '$$@' ],
   [ '$permutation' => 'weak(#1)' ],
   [ '$property' => '#2' ],
   [ '@descend' => '@' ],
);

sub key { $_[0] }

sub defined_for { $_[0]->property->defined_for }

sub name {
   my ($self) = @_;
   "recovery of " . join(".", @{$self->descend}, $self->property->name) .
   " after " . $self->permutation->belongs_to->full_name . "::" . $self->permutation->name
}

1

# Local Variables:
# cperl-indent-level: 3
# indent-tabs-mode:nil
# End: