File: Edge.hh

package info (click to toggle)
ignition-math 6.7.0%2Bds-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 2,396 kB
  • sloc: cpp: 22,476; python: 2,730; ansic: 1,152; ruby: 844; sh: 168; makefile: 14
file content (341 lines) | stat: -rw-r--r-- 10,769 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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
/*
 * Copyright (C) 2017 Open Source Robotics Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
*/
#ifndef IGNITION_MATH_GRAPH_EDGE_HH_
#define IGNITION_MATH_GRAPH_EDGE_HH_

// uint64_t
#include <cstdint>
#include <functional>
#include <iostream>
#include <map>
#include <set>

#include <ignition/math/config.hh>
#include "ignition/math/graph/Vertex.hh"

namespace ignition
{
namespace math
{
// Inline bracket to help doxygen filtering.
inline namespace IGNITION_MATH_VERSION_NAMESPACE {
namespace graph
{
  /// \typedef EdgeId.
  /// \brief The unique Id for an edge.
  using EdgeId = uint64_t;

  /// \brief Used in the Graph constructors for uniform initialization.
  template<typename E>
  struct EdgeInitializer
  {
    /// \brief Constructor.
    /// \param[in] _vertices The vertices of the edge.
    /// \param[in] _data The data stored in the edge.
    /// \param[in] _weight The weight (cost) of the edge.
    EdgeInitializer(const VertexId_P &_vertices,
                    const E &_data = E(),
                    const double _weight = 1)
      : vertices(_vertices),
        data(_data),
        weight(_weight)
    {
    };

    /// \brief IDs of the vertices.
    public: VertexId_P vertices;

    /// \brief User data.
    public: E data;

    /// \brief The weight (cost) of the edge.
    public: double weight = 1;
  };

  /// \brief Generic edge class. An edge has two ends and some constraint
  /// between them. For example, a directed edge only allows traversing the
  /// edge in one direction.
  template<typename E>
  class Edge
  {
    /// \brief Constructor.
    /// \param[in] _vertices The vertices of the edge.
    /// \param[in] _data The data stored in the edge.
    /// \param[in] _weight The weight (cost) of the edge.
    /// \param[in] _id Optional unique id.
    public: explicit Edge(const VertexId_P &_vertices,
                          const E &_data,
                          const double _weight,
                          const EdgeId &_id = kNullId)
      : id(_id),
        vertices(_vertices),
        data(_data),
        weight(_weight)
    {
    }

    /// \brief Get the edge Id.
    /// \return The edge Id.
    public: EdgeId Id() const
    {
      return this->id;
    }

    /// \brief Get the two vertices contained in the edge.
    /// \return The two vertices contained in the edge.
    public: VertexId_P Vertices() const
    {
      if (!this->Valid())
        return {kNullId, kNullId};

      return this->vertices;
    }

    /// \brief Get a non-mutable reference to the user data stored in the edge
    /// \return The non-mutable reference to the user data stored in the edge.
    public: const E &Data() const
    {
      return this->data;
    }

    /// \brief Get a mutable reference to the user data stored in the edge.
    /// \return The mutable reference to the user data stored in the edge.
    public: E &Data()
    {
      return this->data;
    }

    /// \brief The cost of traversing the _from end to the other end of the
    /// edge.
    /// \return The cost.
    public: double Weight() const
    {
      return this->weight;
    }

    /// \brief Set the cost of the edge.
    /// \param[in] _newWeight The new cost.
    public: void SetWeight(const double _newWeight)
    {
      this->weight = _newWeight;
    }

    /// \brief Get the destination end that is reachable from a source end of
    /// an edge.
    ///
    /// E.g.: Let's assume that we have an undirected edge (e1) with ends
    /// (v1) and (v2): (v1)--(v2). The operation e1.From(v1) returns (v2).
    /// The operation e1.From(v2) returns (v1).
    ///
    /// E.g.: Let's assume that we have a directed edge (e2) with the tail end
    /// (v1) and the head end (v2): (v1)->(v2). The operation e2.From(v1)
    /// returns (v2). The operation e2.From(v2) returns kNullId.
    ///
    /// \param[in] _from Source vertex.
    /// \return The other vertex of the edge reachable from the "_from"
    /// vertex or kNullId otherwise.
    public: virtual VertexId From(const VertexId &_from) const = 0;

    /// \brief Get the source end that can reach the destination end of
    /// an edge.
    ///
    /// E.g.: Let's assume that we have an undirected edge (e1) with ends
    /// (v1) and (v2): (v1)--(v2). The operation e1.To(v1) returns (v2).
    /// The operation e1.To(v2) returns (v1).
    ///
    /// E.g.: Let's assume that we have a directed edge (e2) with the tail end
    /// (v1) and the head end (v2): (v1)->(v2). The operation e2.To(v1)
    /// returns kNullId. The operation e2.To(v2) returns v1.
    ///
    /// \param[in] _to Destination vertex.
    /// \return The other vertex of the edge that can reach "_to"
    /// vertex or kNullId otherwise.
    public: virtual VertexId To(const VertexId &_to) const = 0;

    /// \brief An edge is considered valid when its id is not kNullId.
    /// \return Whether the edge is valid or not.
    public: bool Valid() const
    {
      return this->id != kNullId;
    }

    /// \brief Unique edge Id.
    private: EdgeId id = kNullId;

    /// \brief The set of Ids of the two vertices.
    private: VertexId_P vertices;

    /// \brief User data.
    private: E data;

    /// \brief The weight (cost) of the edge. By default, the cost of an edge
    /// is 1.0 .
    private: double weight = 1.0;
  };

  /// \def EdgeId_S
  /// \brief A set of edge Ids.
  using EdgeId_S = std::set<EdgeId>;

  /// \def EdgeRef_M
  /// \brief A map of edges. The key is the edge Id. The value is a reference
  /// to the edge.
  template<typename EdgeType>
  using EdgeRef_M = std::map<EdgeId, std::reference_wrapper<const EdgeType>>;

  /// \brief An undirected edge represents a connection between two vertices.
  /// The connection is bidirectional, it's possible to traverse the edge
  /// in both directions.
  template<typename E>
  class UndirectedEdge : public Edge<E>
  {
    /// \brief An invalid undirected edge.
    public: static UndirectedEdge<E> NullEdge;

    /// \brief Constructor.
    /// \param[in] _vertices The vertices of the edge.
    /// \param[in] _data The data stored in the edge.
    /// \param[in] _weight The weight (cost) of the edge.
    /// \param[in] _id Optional unique id.
    public: explicit UndirectedEdge(const VertexId_P &_vertices,
                                    const E &_data,
                                    const double _weight,
                                    const EdgeId &_id = kNullId)
      : Edge<E>(_vertices, _data, _weight, _id)
    {
    }

    // Documentation inherited.
    public: VertexId From(const VertexId &_from) const override
    {
      if (!this->Valid())
        return kNullId;

      if (this->Vertices().first != _from && this->Vertices().second != _from)
        return kNullId;

      if (this->Vertices().first == _from)
        return this->Vertices().second;

      return this->Vertices().first;
    }

    // Documentation inherited.
    public: VertexId To(const VertexId &_to) const override
    {
      return this->From(_to);
    }

    /// \brief Stream insertion operator. The output uses DOT graph
    /// description language.
    /// \param[out] _out The output stream.
    /// \param[in] _e Edge to write to the stream.
    /// \sa https://en.wikipedia.org/wiki/DOT_(graph_description_language).
    public: friend std::ostream &operator<<(std::ostream &_out,
                                            const UndirectedEdge<E> &_e)
    {
      auto vertices = _e.Vertices();
      _out << "  " << vertices.first << " -- " << vertices.second
           << " [label=" << _e.Weight() << "];" << std::endl;
      return _out;
    }
  };

  /// \brief An invalid undirected edge.
  template<typename E>
  UndirectedEdge<E> UndirectedEdge<E>::NullEdge(
    VertexId_P(kNullId, kNullId), E(), 1.0, kNullId);

  /// \brief A directed edge represents a connection between two vertices.
  /// The connection is unidirectional, it's only possible to traverse the edge
  /// in one direction (from the tail to the head).
  template<typename E>
  class DirectedEdge : public Edge<E>
  {
    /// \brief An invalid directed edge.
    public: static DirectedEdge<E> NullEdge;

    /// \brief Constructor.
    /// \param[in] _vertices The vertices of the edge.
    /// \param[in] _data The data stored in the edge.
    /// \param[in] _weight The weight (cost) of the edge.
    /// \param[in] _id Optional unique id.
    public: explicit DirectedEdge(const VertexId_P &_vertices,
                                  const E &_data,
                                  const double _weight,
                                  const EdgeId &_id = kNullId)
      : Edge<E>(_vertices, _data, _weight, _id)
    {
    }

    /// \brief Get the Id of the tail vertex in this edge.
    /// \return An id of the tail vertex in this edge.
    /// \sa Head()
    public: VertexId Tail() const
    {
      return this->Vertices().first;
    }

    /// \brief Get the Id of the head vertex in this edge.
    /// \return An id of the head vertex in this edge.
    /// \sa Tail()
    public: VertexId Head() const
    {
      return this->Vertices().second;
    }

    // Documentation inherited.
    public: VertexId From(const VertexId &_from) const override
    {
      if (_from != this->Tail())
        return kNullId;

      return this->Head();
    }

    // Documentation inherited.
    public: VertexId To(const VertexId &_to) const override
    {
      if (_to != this->Head())
        return kNullId;

      return this->Tail();
    }

    /// \brief Stream insertion operator. The output uses DOT graph
    /// description language.
    /// \param[out] _out The output stream.
    /// \param[in] _e Edge to write to the stream.
    /// \sa https://en.wikipedia.org/wiki/DOT_(graph_description_language).
    public: friend std::ostream &operator<<(std::ostream &_out,
                                            const DirectedEdge<E> &_e)
    {
      _out << "  " << _e.Tail() << " -> " << _e.Head()
           << " [label=" << _e.Weight() << "];" << std::endl;
      return _out;
    }
  };

  /// \brief An invalid directed edge.
  template<typename E>
  DirectedEdge<E> DirectedEdge<E>::NullEdge(
    VertexId_P(kNullId, kNullId), E(), 1.0, kNullId);
}
}
}
}
#endif