Skip to content

Commit 15bcfad

Browse files
committed
initial hgl io
1 parent 9b48ebb commit 15bcfad

8 files changed

Lines changed: 290 additions & 24 deletions

File tree

include/gl/edge_descriptor.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ class edge_descriptor final {
192192
}
193193
}
194194

195+
// TODO: rm
195196
std::ostream& _write_no_properties(std::ostream& os) const
196197
requires std::same_as<directional_tag, undirected_t>
197198
{
@@ -227,6 +228,7 @@ class edge_descriptor final {
227228
}
228229
}
229230

231+
// TODO: rm
230232
std::ostream& _write_no_properties(std::ostream& os) const
231233
requires std::same_as<directional_tag, directed_t>
232234
{

include/gl/graph.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,14 +210,14 @@ class graph final {
210210

211211
// --- vertex getters ---
212212

213-
[[nodiscard]] gl_attr_force_inline auto vertices() const
213+
[[nodiscard]] gl_attr_force_inline auto vertices() const noexcept
214214
requires(traits::c_empty_properties<vertex_properties_type>)
215215
{
216216
return this->vertex_ids()
217217
| std::views::transform([](const id_type id) { return vertex_descriptor{id}; });
218218
}
219219

220-
[[nodiscard]] gl_attr_force_inline auto vertices() const
220+
[[nodiscard]] gl_attr_force_inline auto vertices() const noexcept
221221
requires(traits::c_non_empty_properties<vertex_properties_type>)
222222
{
223223
return this->_vertex_properties | std::views::enumerate
@@ -749,12 +749,13 @@ class graph final {
749749
std::ostream& _gsf_write(std::ostream& os) const {
750750
using io::detail::option_bit;
751751

752+
// TODO: include c_writable + rename to _props
752753
const bool with_vertex_properties =
753754
io::is_option_set(os, option_bit::with_vertex_properties);
754755
const bool with_edge_properties =
755756
io::is_option_set(os, option_bit::with_connection_properties);
756757

757-
// print graph size
758+
// print graph metadata
758759
os << std::format(
759760
"{} {} {} {} {}\n",
760761
static_cast<int>(traits::c_directed_edge<edge_type>),

include/gl/io/format.hpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,49 @@
77
#include "gl/attributes/force_inline.hpp"
88
#include "gl/traits.hpp"
99

10+
#include <iostream>
11+
#include <ranges>
12+
1013
namespace gl::io {
1114

15+
// TODO: add tests
16+
template <std::ranges::range Range>
17+
struct range_formatter {
18+
const Range& range;
19+
std::string_view sep = ", ";
20+
std::string_view open = "[";
21+
std::string_view close = "]";
22+
23+
friend std::ostream& operator<<(std::ostream& os, const range_formatter& formatter) {
24+
os << formatter.open;
25+
bool first = true;
26+
for (const auto& item : formatter.range) {
27+
if (! first)
28+
os << formatter.sep;
29+
os << item;
30+
first = false;
31+
}
32+
os << formatter.close;
33+
return os;
34+
}
35+
};
36+
37+
template <std::ranges::range Range>
38+
range_formatter(const Range&) -> range_formatter<Range>;
39+
40+
template <std::ranges::range Range>
41+
range_formatter<Range> set_formatter(const Range& range, std::string_view sep = ", ") {
42+
return range_formatter<Range>{range, sep, "{", "}"};
43+
}
44+
1245
/*
46+
Is it necessary
1347
Custom format functions (casts to types compatible with std::formatter)
1448
Not std::formatter overloads to avoid collision with
1549
user defined std::formatter overloads
1650
*/
1751

52+
1853
template <typename T>
1954
[[nodiscard]] gl_attr_force_inline void* format(T* ptr) {
2055
// std::format is not compatible with all types of ptrs

include/gl/vertex_descriptor.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ class vertex_descriptor final {
116116
}
117117
}
118118

119+
// TODO: rm
119120
std::ostream& _write_no_properties(std::ostream& os) const {
120121
using io::detail::option_bit;
121122

include/hgl/hypergraph.hpp

Lines changed: 140 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
#pragma once
66

77
#include "gl/attributes/force_inline.hpp"
8+
#include "gl/traits.hpp"
89
#include "gl/types/core.hpp"
910
#include "hgl/constants.hpp"
1011
#include "hgl/directional_tags.hpp"
1112
#include "hgl/hypergraph_traits.hpp"
1213
#include "hgl/impl/impl_tags.hpp"
14+
#include "hgl/io.hpp"
1315
#include "hgl/util.hpp"
1416

1517
#include <algorithm>
@@ -131,7 +133,7 @@ class hypergraph final {
131133

132134
// --- vertex methods ---
133135

134-
[[nodiscard]] gl_attr_force_inline auto vertices() noexcept {
136+
[[nodiscard]] gl_attr_force_inline auto vertices() const noexcept {
135137
return this->vertex_ids() | std::views::transform(this->_create_vertex_descriptor());
136138
}
137139

@@ -258,7 +260,7 @@ class hypergraph final {
258260

259261
// --- hyperedge methods ---
260262

261-
[[nodiscard]] gl_attr_force_inline auto hyperedges() noexcept {
263+
[[nodiscard]] gl_attr_force_inline auto hyperedges() const noexcept {
262264
return this->hyperedge_ids() | std::views::transform(this->_create_hyperedge_descriptor());
263265
}
264266

@@ -517,14 +519,14 @@ class hypergraph final {
517519
return this->_impl.degree_map(this->_n_vertices);
518520
}
519521

520-
[[nodiscard]] gl_attr_force_inline auto out_hyperedges(const id_type vertex_id)
522+
[[nodiscard]] gl_attr_force_inline auto out_hyperedges(const id_type vertex_id) const
521523
requires std::same_as<directional_tag, bf_directed_t>
522524
{
523525
return this->out_hyperedge_ids(vertex_id)
524526
| std::views::transform(this->_create_hyperedge_descriptor());
525527
}
526528

527-
[[nodiscard]] gl_attr_force_inline auto out_hyperedges(const vertex_type& vertex)
529+
[[nodiscard]] gl_attr_force_inline auto out_hyperedges(const vertex_type& vertex) const
528530
requires std::same_as<directional_tag, bf_directed_t>
529531
{
530532
return this->out_hyperedges(vertex.id());
@@ -562,14 +564,14 @@ class hypergraph final {
562564
return this->_impl.out_degree_map(this->_n_vertices);
563565
}
564566

565-
[[nodiscard]] gl_attr_force_inline auto in_hyperedges(const id_type vertex_id)
567+
[[nodiscard]] gl_attr_force_inline auto in_hyperedges(const id_type vertex_id) const
566568
requires std::same_as<directional_tag, bf_directed_t>
567569
{
568570
return this->in_hyperedge_ids(vertex_id)
569571
| std::views::transform(this->_create_hyperedge_descriptor());
570572
}
571573

572-
[[nodiscard]] gl_attr_force_inline auto in_hyperedges(const vertex_type& vertex)
574+
[[nodiscard]] gl_attr_force_inline auto in_hyperedges(const vertex_type& vertex) const
573575
requires std::same_as<directional_tag, bf_directed_t>
574576
{
575577
return this->in_hyperedges(vertex.id());
@@ -607,12 +609,13 @@ class hypergraph final {
607609
return this->_impl.in_degree_map(this->_n_vertices);
608610
}
609611

610-
[[nodiscard]] auto incident_vertices(const id_type hyperedge_id) {
612+
[[nodiscard]] auto incident_vertices(const id_type hyperedge_id) const {
611613
return this->incident_vertex_ids(hyperedge_id)
612614
| std::views::transform(this->_create_vertex_descriptor());
613615
}
614616

615-
[[nodiscard]] gl_attr_force_inline auto incident_vertices(const hyperedge_type& hyperedge) {
617+
[[nodiscard]] gl_attr_force_inline auto incident_vertices(const hyperedge_type& hyperedge
618+
) const {
616619
return this->incident_vertices(hyperedge.id());
617620
}
618621

@@ -640,14 +643,14 @@ class hypergraph final {
640643
return this->_impl.hyperedge_size_map(this->_n_hyperedges);
641644
}
642645

643-
[[nodiscard]] gl_attr_force_inline auto tail_vertices(const id_type hyperedge_id)
646+
[[nodiscard]] gl_attr_force_inline auto tail_vertices(const id_type hyperedge_id) const
644647
requires std::same_as<directional_tag, bf_directed_t>
645648
{
646649
return this->tail_vertex_ids(hyperedge_id)
647650
| std::views::transform(this->_create_vertex_descriptor());
648651
}
649652

650-
[[nodiscard]] gl_attr_force_inline auto tail_vertices(const hyperedge_type& hyperedge)
653+
[[nodiscard]] gl_attr_force_inline auto tail_vertices(const hyperedge_type& hyperedge) const
651654
requires std::same_as<directional_tag, bf_directed_t>
652655
{
653656
return this->tail_vertices(hyperedge.id());
@@ -685,14 +688,14 @@ class hypergraph final {
685688
return this->_impl.tail_size_map(this->_n_hyperedges);
686689
}
687690

688-
[[nodiscard]] gl_attr_force_inline auto head_vertices(const id_type hyperedge_id)
691+
[[nodiscard]] gl_attr_force_inline auto head_vertices(const id_type hyperedge_id) const
689692
requires std::same_as<directional_tag, bf_directed_t>
690693
{
691694
return this->head_vertex_ids(hyperedge_id)
692695
| std::views::transform(this->_create_vertex_descriptor());
693696
}
694697

695-
[[nodiscard]] gl_attr_force_inline auto head_vertices(const hyperedge_type& hyperedge)
698+
[[nodiscard]] gl_attr_force_inline auto head_vertices(const hyperedge_type& hyperedge) const
696699
requires std::same_as<directional_tag, bf_directed_t>
697700
{
698701
return this->head_vertices(hyperedge.id());
@@ -753,6 +756,80 @@ class hypergraph final {
753756
return lhs._impl == rhs._impl;
754757
}
755758

759+
// --- I/O utility ---
760+
761+
struct hyperedge_formatter {
762+
public:
763+
const hypergraph& hg;
764+
const hyperedge_type& hyperedge;
765+
766+
friend std::ostream& operator<<(std::ostream& os, const hyperedge_formatter& proxy)
767+
requires std::same_as<directional_tag, undirected_t>
768+
{
769+
using io::detail::option_bit;
770+
const bool with_props =
771+
io::is_option_set(os, option_bit::with_connection_properties)
772+
and traits::c_writable<hyperedge_properties_type>;
773+
774+
if (io::is_option_set(os, option_bit::verbose)) {
775+
os << "[id: " << proxy.hyperedge.id() << " | vertices: "
776+
<< io::set_formatter(proxy.hg.incident_vertex_ids(proxy.hyperedge.id()));
777+
if (with_props)
778+
os << " | " << proxy.hyperedge.properties();
779+
os << ']';
780+
}
781+
else { // concise
782+
os << io::set_formatter(proxy.hg.incident_vertex_ids(proxy.hyperedge.id()));
783+
if (with_props)
784+
os << '[' << proxy.hyperedge.properties() << ']';
785+
}
786+
787+
return os;
788+
}
789+
790+
friend std::ostream& operator<<(std::ostream& os, const hyperedge_formatter& proxy)
791+
requires std::same_as<directional_tag, bf_directed_t>
792+
{
793+
using io::detail::option_bit;
794+
const bool with_props =
795+
io::is_option_set(os, option_bit::with_connection_properties)
796+
and traits::c_writable<hyperedge_properties_type>;
797+
798+
if (io::is_option_set(os, option_bit::verbose)) {
799+
os << "[id: " << proxy.hyperedge.id() << " | tail: "
800+
<< io::set_formatter(proxy.hg.tail_vertex_ids(proxy.hyperedge.id()))
801+
<< ", head: "
802+
<< io::set_formatter(proxy.hg.head_vertex_ids(proxy.hyperedge.id()));
803+
if (with_props)
804+
os << " | " << proxy.hyperedge.properties();
805+
os << "]";
806+
}
807+
else { // concise
808+
os << '(' << io::set_formatter(proxy.hg.tail_vertex_ids(proxy.hyperedge.id()))
809+
<< " -> " << io::set_formatter(proxy.hg.head_vertex_ids(proxy.hyperedge.id()))
810+
<< ')';
811+
if (with_props)
812+
os << '[' << proxy.hyperedge.properties() << ']';
813+
}
814+
815+
return os;
816+
}
817+
};
818+
819+
[[nodiscard]] hyperedge_formatter display(const hyperedge_type& hyperedge) const {
820+
return hyperedge_formatter{*this, hyperedge};
821+
}
822+
823+
friend std::ostream& operator<<(std::ostream& os, const hypergraph& hg) {
824+
// if (gl::io::is_option_set(os, gl::io::detail::option_bit::gsf))
825+
// return hg._gsf_write(os);
826+
827+
if (gl::io::is_option_set(os, gl::io::detail::option_bit::verbose))
828+
return hg._verbose_write(os);
829+
830+
return hg._concise_write(os);
831+
}
832+
756833
// --- friend declarations ---
757834

758835
template <traits::c_hypergraph Hypergraph>
@@ -824,34 +901,81 @@ class hypergraph final {
824901

825902
// --- transformations ---
826903

827-
gl_attr_force_inline auto _create_vertex_descriptor() noexcept
904+
gl_attr_force_inline auto _create_vertex_descriptor() const noexcept
828905
requires(traits::c_empty_properties<vertex_properties_type>)
829906
{
830907
return [](const id_type id) { return vertex_type{id}; };
831908
}
832909

833-
gl_attr_force_inline auto _create_vertex_descriptor() noexcept
910+
gl_attr_force_inline auto _create_vertex_descriptor() const noexcept
834911
requires(traits::c_non_empty_properties<vertex_properties_type>)
835912
{
836913
return [&pmap = this->_vertex_properties](const id_type id) {
837914
return vertex_type{id, *pmap[to_idx(id)]};
838915
};
839916
}
840917

841-
gl_attr_force_inline auto _create_hyperedge_descriptor() noexcept
918+
gl_attr_force_inline auto _create_hyperedge_descriptor() const noexcept
842919
requires(traits::c_empty_properties<hyperedge_properties_type>)
843920
{
844921
return [](const id_type id) { return hyperedge_type{id}; };
845922
}
846923

847-
gl_attr_force_inline auto _create_hyperedge_descriptor() noexcept
924+
gl_attr_force_inline auto _create_hyperedge_descriptor() const noexcept
848925
requires(traits::c_non_empty_properties<hyperedge_properties_type>)
849926
{
850927
return [&pmap = this->_hyperedge_properties](const id_type id) {
851928
return hyperedge_type{id, *pmap[to_idx(id)]};
852929
};
853930
}
854931

932+
// --- I/O utility ---
933+
934+
std::ostream& _verbose_write(std::ostream& os) const {
935+
using enum io::detail::option_bit;
936+
using fmt_traits = io::detail::hypergraph_fmt_traits<directional_tag>;
937+
938+
os << "type: " << fmt_traits::type << ", |V| = " << this->order()
939+
<< ", |E| = " << this->size() << '\n';
940+
941+
const bool with_v_props =
942+
io::is_option_set(os, with_vertex_properties)
943+
and traits::c_writable<vertex_properties_type>;
944+
if (with_v_props) {
945+
os << "vertices:\n";
946+
for (const auto& vertex : this->vertices())
947+
os << " - " << vertex << '\n';
948+
}
949+
950+
os << "hyperedges:\n";
951+
for (const auto& edge : this->hyperedges())
952+
os << " - " << this->display(edge) << '\n';
953+
954+
return os;
955+
}
956+
957+
std::ostream& _concise_write(std::ostream& os) const {
958+
using enum io::detail::option_bit;
959+
960+
const bool with_v_props =
961+
io::is_option_set(os, with_vertex_properties)
962+
and traits::c_writable<vertex_properties_type>;
963+
if (with_v_props) {
964+
os << "V :";
965+
for (const auto& vertex : this->vertices())
966+
os << " " << vertex;
967+
}
968+
else {
969+
os << "|V| = " << this->order();
970+
}
971+
972+
os << "\nE:\n";
973+
for (const auto& edge : this->hyperedges())
974+
os << this->display(edge) << '\n';
975+
976+
return os;
977+
}
978+
855979
// --- data members ---
856980

857981
size_type _n_vertices = 0uz;

0 commit comments

Comments
 (0)