File: complex_tools.tcc

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 (147 lines) | stat: -rw-r--r-- 4,563 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
/* 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.
--------------------------------------------------------------------------------
*/

#include "polymake/hash_map"
#include "polymake/FaceMap.h"
#include "polymake/Bitset.h"
#include <sstream>

namespace polymake { namespace topaz {

template <typename Complex, typename Set>
bool adj_numbering(Complex& C, const Set& V)
{
   if (V.empty())
      return false;

   const bool renumber= V.front()!=0 || V.back()+1!=V.size();

   if (renumber) {
      hash_map<Int, Int> vertex_map(V.size());
      Int count = 0;
      for (auto s_it=entire(V); !s_it.at_end(); ++s_it, ++count)
         vertex_map[*s_it]=count;

      for (auto c_it=entire(C); !c_it.at_end(); ++c_it) {
         typename Complex::value_type::persistent_type f;
         for (auto s_it=entire(*c_it); !s_it.at_end(); ++s_it)
            f += vertex_map[*s_it];
         *c_it = f;
      }
   }

   return renumber;
}

template <typename OutputIterator>
bool is_pseudo_manifold(const Lattice<BasicDecoration>& HD, bool known_pure, OutputIterator boundary_consumer, Int* bad_face_p)
{
   if (HD.in_degree(HD.top_node())==0)
      return true;

   if (!known_pure && !is_pure(HD)) {
      if (bad_face_p) *bad_face_p=-1;
      return false;
   }

   for (const auto n : HD.nodes_of_rank(HD.rank()-2)) {
      const Int d = HD.out_degree(n);
      if (d > 2) {
         if (bad_face_p) *bad_face_p=n;
         return false;
      }
      if (!is_derived_from_instance_of<OutputIterator, pm::black_hole>::value && d == 1)
         *boundary_consumer++ = HD.face(n);
   }

   return true;
}

// return values: 1=true, 0=false, -1=undef
template <typename Complex, int d>
Int is_ball_or_sphere(const Complex& C, int_constant<d>)
{
   if (POLYMAKE_DEBUG) {
      if (C.empty())
         throw std::runtime_error("is_ball_or_sphere: empty complex");
   }
   // compute the vertex set and test whether C is a pure d-complex
   Set<Int> V;
   for (auto c_it=entire(C); !c_it.at_end(); ++c_it) {
      V += *c_it;
      if (POLYMAKE_DEBUG) {
         if (c_it->size() > d+1) {
            std::ostringstream err;
            pm::wrap(err) << "is_ball_or_sphere: Dimension of " << *c_it << " is greater than " << d;
            throw std::runtime_error(err.str());
         }
      }
      if (c_it->size()!=d+1)  // complex is not pure
         return 0;
   }
   return is_ball_or_sphere(C, V, int_constant<d>());
}

// return values: 1=true, 0=false, -1=undef
template <typename Complex, int d>
Int is_manifold(const Complex& C, int_constant<d>, Int* bad_link_p)
{
   if (POLYMAKE_DEBUG) {
      if (C.empty())
         throw std::runtime_error("is_manifold: empty complex");
   }
   // compute the vertex set and test whether C is a pure 1-complex
   Set<Int> V;
   for (auto c_it=entire(C); !c_it.at_end(); ++c_it) {
      V+=*c_it;
      if (POLYMAKE_DEBUG) {
         if (c_it->size() > d+1) {
            std::ostringstream err;
            err << "is_manifold: Dimension of " << *c_it << " is greater than " << d;
            throw std::runtime_error(err.str());
         }
      }
      if (c_it->size()!=d+1) { // complex is not pure
         if (bad_link_p) *bad_link_p=-1;
         return 0;
      }
   }
   return is_manifold(C, V, int_constant<d>(), bad_link_p);
}

// return values: 1=true, 0=false, -1=undef
template <typename Complex, typename VertexSet, int d>
Int is_manifold(const Complex& C, const GenericSet<VertexSet>& V, int_constant<d>, Int* bad_link_p)
{
   // iterate over the vertices and test if their links are (d-1)-balls or (d-1)-spheres
   for (auto it=entire(V.top()); !it.at_end(); ++it) {
      const Int bos = is_ball_or_sphere(link(C, scalar2set(*it)), int_constant<d-1>());
      if (bos <= 0) { // false or undef
         if (bad_link_p) *bad_link_p = *it;
         return bos;
      }
   }
   return 1;
}

} }

// Local Variables:
// mode:C++
// c-basic-offset:3
// indent-tabs-mode:nil
// End: