1 /*
2 This program is free software; you can redistribute it and/or
3 modify it under the terms of the GNU General Public License
4 as published by the Free Software Foundation; either version 2
5 of the License, or (at your option) any later version.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor,
15 Boston, MA 02110-1301, USA.
16
17 ---
18 Copyright (C) 2011 - 2015, Simon Hampe <simon.hampe@googlemail.com>
19
20 ---
21 Copyright (c) 2016-2021
22 Ewgenij Gawrilow, Michael Joswig, and the polymake team
23 Technische Universität Berlin, Germany
24 https://polymake.org
25
26 Implements the addition of two morphisms.
27 */
28
29 #include "polymake/client.h"
30 #include "polymake/Matrix.h"
31 #include "polymake/Rational.h"
32 #include "polymake/Vector.h"
33 #include "polymake/tropical/refine.h"
34
35 namespace polymake { namespace tropical {
36
37 /*
38 * @brief Takes a morphism and a Cycle whose support is equal to f's [[DOMAIN]]
39 * and returns f as a morphism on that cycle.
40 * @param Morphism f
41 * @param Cycle X
42 * @param bool need_to_refine Whether the cycle needs to be refined or it is
43 * already fine in f's [[DOMAIN]].
44 * @tparam Addition Min or Max
45 * @return Morphism The "refined" morphism
46 */
47 template <typename Addition>
refine_domain(BigObject f,BigObject cycle,bool need_to_refine)48 BigObject refine_domain(BigObject f, BigObject cycle, bool need_to_refine)
49 {
50 BigObject oldDomain = f.give("DOMAIN");
51 bool has_matrix = f.exists("MATRIX");
52 RefinementResult r = refinement(cycle, oldDomain, false, !has_matrix,false,need_to_refine,false);
53
54 BigObject nDomain = r.complex;
55 if (has_matrix) {
56 Matrix<Rational> matrix = f.give("MATRIX");
57 Vector<Rational> translate = f.give("TRANSLATE");
58 return BigObject("Morphism", mlist<Addition>(),
59 "DOMAIN", nDomain,
60 "MATRIX", matrix,
61 "TRANSLATE", translate);
62 }
63
64 Matrix<Rational> rayRep = r.rayRepFromY;
65 Matrix<Rational> linRep = r.linRepFromY;
66
67 Matrix<Rational> vertex_values = f.give("VERTEX_VALUES");
68 Matrix<Rational> lineality_values = f.give("LINEALITY_VALUES");
69 Matrix<Rational> total_values = T( vertex_values / lineality_values);
70 Int target_dim = std::max(vertex_values.cols(), lineality_values.cols());
71
72 Matrix<Rational> ndom_vertices = nDomain.give("SEPARATED_VERTICES");
73 Matrix<Rational> ndom_lineality = nDomain.give("LINEALITY_SPACE");
74
75 Matrix<Rational> rValues(0,target_dim);
76 Matrix<Rational> lValues(0,target_dim);
77
78 for (Int v = 0; v < ndom_vertices.rows(); ++v) {
79 rValues /= total_values * rayRep.row(v);
80 }
81
82 for (Int l = 0; l < ndom_lineality.rows(); ++l) {
83 lValues /= total_values * linRep.row(l);
84 }
85
86 return BigObject("Morphism", mlist<Addition>(),
87 "DOMAIN", nDomain,
88 "VERTEX_VALUES", rValues,
89 "LINEALITY_VALUES", lValues);
90 }
91
92 /**
93 @brief Computes the sum of two morphisms (which should be defined on the same support)
94 @param BigObject f A Morphism object
95 @param BigObject g A Morphism object, whose DOMAIN has the same support as f's DOMAIN and whose image has the same ambient dimension as f's image
96 @return BigObject A Morphism object representing f+g
97 */
98 template <typename Addition>
add_morphisms(BigObject f,BigObject g)99 BigObject add_morphisms(BigObject f, BigObject g)
100 {
101 // First we treat the special case where both are global
102 bool f_global = f.exists("MATRIX");
103 bool g_global = g.exists("MATRIX");
104 Matrix<Rational> sum_matrix;
105 Vector<Rational> sum_translate;
106 if (f_global && g_global) {
107 Matrix<Rational> fmatrix = f.give("MATRIX");
108 Vector<Rational> ftranslate = f.give("TRANSLATE");
109 Matrix<Rational> gmatrix = g.give("MATRIX");
110 Vector<Rational> gtranslate = g.give("TRANSLATE");
111
112 sum_matrix = fmatrix + gmatrix;
113 sum_translate = ftranslate + gtranslate;
114 }
115
116 // First we homogenize where necessary
117 BigObject fDomain = f.give("DOMAIN");
118 BigObject gDomain = g.give("DOMAIN");
119
120 // Then compute the common refinement of the domains
121 RefinementResult r = refinement(fDomain,gDomain,false,false,false,true,false);
122 BigObject nDomain = r.complex;
123
124 // If the map is given by a matrix, we're done
125 if (f_global && g_global) {
126 return BigObject("Morphism", mlist<Addition>(),
127 "MATRIX", sum_matrix,
128 "TRANSLATE", sum_translate,
129 "DOMAIN", nDomain);
130 }
131
132 // Otherwise, compute values on the new domain
133 BigObject f_refined = refine_domain<Addition>(f, nDomain, false);
134 BigObject g_refined = refine_domain<Addition>(g, nDomain, false);
135
136 Matrix<Rational> fref_vert = f_refined.give("VERTEX_VALUES");
137 Matrix<Rational> gref_vert = g_refined.give("VERTEX_VALUES");
138 Matrix<Rational> fref_lin = f_refined.give("LINEALITY_VALUES");
139 Matrix<Rational> gref_lin = g_refined.give("LINEALITY_VALUES");
140
141 return BigObject("Morphism", mlist<Addition>(),
142 "DOMAIN", nDomain,
143 "VERTEX_VALUES", fref_vert + gref_vert,
144 "LINEALITY_VALUES", fref_lin + gref_lin);
145 }
146
147 UserFunctionTemplate4perl("# @category Morphisms"
148 "# Computes the sum of two morphisms. Both [[DOMAIN]]s should have the same support"
149 "# and the target spaces should have the same ambient dimension"
150 "# The domain of the result will be the common refinement of the two domains."
151 "# @param Morphism f"
152 "# @param Morphism g"
153 "# @return Morphism",
154 "add_morphisms<Addition>(Morphism<Addition>, Morphism<Addition>)");
155 } }
156