File: canonicalize.h

package info (click to toggle)
polymake 4.15-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 35,892 kB
  • sloc: cpp: 168,945; perl: 43,410; javascript: 31,575; ansic: 3,007; java: 2,654; python: 632; sh: 268; xml: 117; makefile: 61
file content (182 lines) | stat: -rw-r--r-- 6,358 bytes parent folder | download | duplicates (3)
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
/* 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.
--------------------------------------------------------------------------------
*/

#pragma once

#include "polymake/Vector.h"
#include "polymake/Matrix.h"
#include "polymake/linalg.h"
#include "polymake/TropicalNumber.h"
#include "polymake/polytope/canonicalize.h"

namespace polymake { namespace tropical {

// The following all canonicalize a matrix/vector of tropical numbers such that the first entry
// is zero.

template <typename TVector, typename Addition, typename Scalar>
void canonicalize_to_leading_zero(GenericVector<TVector, TropicalNumber<Addition, Scalar>>& V)
{
   if (!is_leading_zero(V)) {
      const auto first = *V.top().begin();
      V /= first;
   }
}

template <typename TVector, typename Addition, typename Scalar>
void canonicalize_to_leading_zero(GenericVector<TVector, TropicalNumber<Addition, Scalar>>&& V)
{
   canonicalize_to_leading_zero(V);
}

template <typename TMatrix, typename Addition, typename Scalar>
void canonicalize_to_leading_zero(GenericMatrix<TMatrix, TropicalNumber<Addition,Scalar>>& M)
{
   if (M.rows() == 0)
      throw std::runtime_error("point matrix may not be empty");
   for (auto r=entire(rows(M)); !r.at_end();  ++r)
      canonicalize_to_leading_zero(*r);
}

template <typename TMatrix, typename Addition, typename Scalar>
void canonicalize_to_leading_zero(GenericMatrix<TMatrix, TropicalNumber<Addition,Scalar>>&& M)
{
   canonicalize_to_leading_zero(M);
}

// Does the same as canonicalize_to_leading_zero, and checks and complains if there is a zero column
template <typename TMatrix, typename Addition, typename Scalar>
void canonicalize_to_leading_zero_and_check_columns(GenericMatrix<TMatrix, TropicalNumber<Addition, Scalar>>& M)
{
   for (auto c = entire(rows(T(M))); !c.at_end(); ++c) {
      if (support(*c).empty())
         throw std::runtime_error("The points can't all lie in the same boundary stratum of projective space. Maybe use a projection?");
   }
   return canonicalize_to_leading_zero(M);
}

template <typename TMatrix, typename Addition, typename Scalar>
void canonicalize_to_leading_zero_and_check_columns(GenericMatrix<TMatrix, TropicalNumber<Addition, Scalar>>&& M)
{
   canonicalize_to_leading_zero_and_check_columns(M);
}

// The following canonicalize matrices/vectors of scalars, but representing (finite) 
// tropical homogeneous coordinates.

template <typename TVector, typename Scalar>
void canonicalize_scalar_to_leading_zero(GenericVector<TVector, Scalar>& V)
{
   if (!is_leading_zero(V)) {
      const auto first = *V.top().begin();
      V -= same_element_vector(first, V.dim());
   }
}

template <typename TVector, typename Scalar>
void canonicalize_scalar_to_leading_zero(GenericVector<TVector, Scalar>&& V)
{
   canonicalize_scalar_to_leading_zero(V);
}

template <typename TMatrix, typename Scalar>
void canonicalize_scalar_to_leading_zero(GenericMatrix<TMatrix, Scalar>& M)
{
   if (M.rows() == 0)
      throw std::runtime_error("point matrix may not be empty");
   for (auto r=entire(rows(M)); !r.at_end();  ++r)
      canonicalize_scalar_to_leading_zero(*r);
}

template <typename TMatrix, typename Scalar>
void canonicalize_scalar_to_leading_zero(GenericMatrix<TMatrix, Scalar>&& M)
{
   canonicalize_scalar_to_leading_zero(M);
}

// FIXME Should this be swapped for min/max, i.e. should there be a nonpositive - or rather,
// a templated version of this?

template <typename TVector, typename Scalar>
void canonicalize_scalar_to_nonnegative(GenericVector<TVector, Scalar>& V)
{
   const auto x_min = accumulate(V.top(), operations::min());
   if (pm::check_container_feature<TVector, pm::sparse>::value
       ? x_min<0 || V.top().size()==V.dim()
       : !is_zero(x_min))
      V -= same_element_vector(x_min, V.dim());
}

template <typename TVector, typename Scalar>
void canonicalize_scalar_to_nonnegative(GenericVector<TVector, Scalar>&& V)
{
   canonicalize_scalar_to_nonnegative(V);
}

template <typename TMatrix, typename Scalar>
void canonicalize_scalar_to_nonnegative(GenericMatrix<TMatrix, Scalar>& M)
{
   if (M.rows() == 0)
      throw std::runtime_error("point matrix may not be empty");
   for (auto r=entire(rows(M)); !r.at_end();  ++r)
      canonicalize_scalar_to_nonnegative(*r);
}

template <typename TMatrix, typename Scalar>
void canonicalize_scalar_to_nonnegative(GenericMatrix<TMatrix, Scalar>&& M)
{
   canonicalize_scalar_to_nonnegative(M);
}

// Assumes as input a matrix of tropically homogeneous vectors with a leading 1/0 indicating
// vertex or far vertex. Will canonicalize M.minor(All,~[0]) to have first coordinate 0. 
// Then will canonicalize the full matrix as a usual vertex matrix.
template <typename TMatrix, typename Scalar>
void canonicalize_vertices_to_leading_zero(GenericMatrix<TMatrix, Scalar>& M)
{
  canonicalize_scalar_to_leading_zero(M.minor(All, range_from(1)));
  for (auto r = entire(rows(M)); !r.at_end(); ++r) {
    polytope::canonicalize_oriented( find_in_range_if(entire(*r), operations::non_zero()) );
  }
}

template <typename TMatrix, typename Scalar>
void canonicalize_vertices_to_leading_zero(GenericMatrix<TMatrix, Scalar>&& M)
{
   canonicalize_vertices_to_leading_zero(M);
}

template <typename TVector, typename Scalar>
void canonicalize_vertex_to_leading_zero(GenericVector<TVector,Scalar>& V)
{
   canonicalize_scalar_to_leading_zero(V.slice(1));
   polytope::canonicalize_oriented( find_in_range_if(entire(V.top()), operations::non_zero()) );
}

template <typename TVector, typename Scalar>
void canonicalize_vertex_to_leading_zero(GenericVector<TVector,Scalar>&& V)
{
   canonicalize_vertex_to_leading_zero(V);
}

} }

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