sp-graph-layout 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sp_graph_layout-1.0.0/CMakeLists.txt +164 -0
- sp_graph_layout-1.0.0/LICENSE +21 -0
- sp_graph_layout-1.0.0/PKG-INFO +41 -0
- sp_graph_layout-1.0.0/README.md +28 -0
- sp_graph_layout-1.0.0/include/common/binary_indexed_tree.h +38 -0
- sp_graph_layout-1.0.0/include/common/compare_svg.h +17 -0
- sp_graph_layout-1.0.0/include/common/graph_attributes.h +96 -0
- sp_graph_layout-1.0.0/include/common/graph_def.h +149 -0
- sp_graph_layout-1.0.0/include/directed/cross_minimization.h +106 -0
- sp_graph_layout-1.0.0/include/directed/feedback_arcs.h +40 -0
- sp_graph_layout-1.0.0/include/directed/layer_assignment.h +71 -0
- sp_graph_layout-1.0.0/include/directed/vertex_positioning.h +78 -0
- sp_graph_layout-1.0.0/include/graph_layout.h +66 -0
- sp_graph_layout-1.0.0/pyproject.toml +51 -0
- sp_graph_layout-1.0.0/python/README.md +21 -0
- sp_graph_layout-1.0.0/python/bindings.cpp +82 -0
- sp_graph_layout-1.0.0/python/wrapper/__init__.py +27 -0
- sp_graph_layout-1.0.0/src/common/binary_indexed_tree.cpp +47 -0
- sp_graph_layout-1.0.0/src/common/compare_svg.cpp +12 -0
- sp_graph_layout-1.0.0/src/common/graph_attributes.cpp +133 -0
- sp_graph_layout-1.0.0/src/common/graph_def.cpp +352 -0
- sp_graph_layout-1.0.0/src/common/graph_def_splitter.cpp +88 -0
- sp_graph_layout-1.0.0/src/directed/cross_minimization.cpp +451 -0
- sp_graph_layout-1.0.0/src/directed/feedback_arcs.cpp +182 -0
- sp_graph_layout-1.0.0/src/directed/layer_assignment.cpp +321 -0
- sp_graph_layout-1.0.0/src/directed/vertex_positioning.cpp +274 -0
- sp_graph_layout-1.0.0/src/graph_layout.cpp +313 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 4.0)
|
|
2
|
+
project(GraphLayout)
|
|
3
|
+
|
|
4
|
+
set(CMAKE_CXX_STANDARD 20)
|
|
5
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
6
|
+
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
7
|
+
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
8
|
+
|
|
9
|
+
option(GRAPH_LAYOUT_ENABLE_TESTS "Build tests" OFF)
|
|
10
|
+
option(GRAPH_LAYOUT_ENABLE_RANDOM_TESTS "Build random tests" OFF)
|
|
11
|
+
option(GRAPH_LAYOUT_ENABLE_STRICT "Use strict compile options" OFF)
|
|
12
|
+
option(GRAPH_LAYOUT_ENABLE_COVERAGE "Enable coverage reporting" OFF)
|
|
13
|
+
option(GRAPH_LAYOUT_BIND_PYTHON "Enable python binding" OFF)
|
|
14
|
+
option(GRAPH_LAYOUT_BIND_ES "Enable ECMAScript binding" OFF)
|
|
15
|
+
|
|
16
|
+
if(APPLE)
|
|
17
|
+
set(ENV{PKG_CONFIG_PATH} "/opt/homebrew/lib/pkgconfig:$ENV{PKG_CONFIG_PATH}")
|
|
18
|
+
endif()
|
|
19
|
+
|
|
20
|
+
include(FetchContent)
|
|
21
|
+
|
|
22
|
+
FetchContent_Declare(
|
|
23
|
+
SVGDiagram
|
|
24
|
+
GIT_REPOSITORY https://github.com/CyberZHG/SVGDiagram.git
|
|
25
|
+
GIT_TAG v1.3.0
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
FetchContent_MakeAvailable(SVGDiagram)
|
|
29
|
+
|
|
30
|
+
if(GRAPH_LAYOUT_ENABLE_STRICT)
|
|
31
|
+
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
|
|
32
|
+
add_compile_options(
|
|
33
|
+
-Wall
|
|
34
|
+
-Wextra
|
|
35
|
+
-Werror
|
|
36
|
+
-Wpedantic
|
|
37
|
+
-Wmissing-include-dirs
|
|
38
|
+
-Wundef
|
|
39
|
+
-Wredundant-decls
|
|
40
|
+
)
|
|
41
|
+
endif()
|
|
42
|
+
endif()
|
|
43
|
+
|
|
44
|
+
if(GRAPH_LAYOUT_ENABLE_COVERAGE)
|
|
45
|
+
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
|
46
|
+
add_compile_options(--coverage -O0 -g)
|
|
47
|
+
add_link_options(--coverage)
|
|
48
|
+
endif()
|
|
49
|
+
endif()
|
|
50
|
+
|
|
51
|
+
add_library(GraphLayout STATIC
|
|
52
|
+
include/graph_layout.h
|
|
53
|
+
src/graph_layout.cpp
|
|
54
|
+
include/directed/feedback_arcs.h
|
|
55
|
+
src/directed/feedback_arcs.cpp
|
|
56
|
+
include/common/graph_def.h
|
|
57
|
+
src/common/graph_def.cpp
|
|
58
|
+
include/directed/layer_assignment.h
|
|
59
|
+
src/directed/layer_assignment.cpp
|
|
60
|
+
src/common/graph_def_splitter.cpp
|
|
61
|
+
include/directed/cross_minimization.h
|
|
62
|
+
src/directed/cross_minimization.cpp
|
|
63
|
+
include/common/binary_indexed_tree.h
|
|
64
|
+
src/common/binary_indexed_tree.cpp
|
|
65
|
+
include/directed/vertex_positioning.h
|
|
66
|
+
src/directed/vertex_positioning.cpp
|
|
67
|
+
include/common/graph_attributes.h
|
|
68
|
+
src/common/graph_attributes.cpp
|
|
69
|
+
include/common/compare_svg.h
|
|
70
|
+
src/common/compare_svg.cpp
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
target_include_directories(GraphLayout
|
|
74
|
+
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
target_link_libraries(GraphLayout
|
|
78
|
+
PRIVATE SVGDiagram
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
if(GRAPH_LAYOUT_ENABLE_TESTS)
|
|
82
|
+
enable_testing()
|
|
83
|
+
|
|
84
|
+
FetchContent_Declare(
|
|
85
|
+
googletest
|
|
86
|
+
GIT_REPOSITORY https://github.com/google/googletest.git
|
|
87
|
+
GIT_TAG v1.17.0
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
FetchContent_MakeAvailable(googletest)
|
|
91
|
+
|
|
92
|
+
add_executable(runTests
|
|
93
|
+
tests/test_main.cpp
|
|
94
|
+
tests/feedback_arcs/test_eades_93.cpp
|
|
95
|
+
tests/layer_assignment/test_topological.cpp
|
|
96
|
+
tests/graph_def/test_component_splitter.cpp
|
|
97
|
+
tests/layer_assignment/test_gansner_93.cpp
|
|
98
|
+
tests/cross_minimization/test_cross_minimization.cpp
|
|
99
|
+
tests/cross_minimization/test_barycenter.cpp
|
|
100
|
+
tests/cross_minimization/test_median.cpp
|
|
101
|
+
tests/cross_minimization/test_pairwise_switch.cpp
|
|
102
|
+
tests/vertex_positioning/test_brandes_kopf.cpp
|
|
103
|
+
tests/graph_layout/test_directed_graph_hierarchical_layout.cpp
|
|
104
|
+
tests/feedback_arcs/test_min_id.cpp
|
|
105
|
+
tests/docs/test_basic.cpp
|
|
106
|
+
tests/docs/test_graph_attr.cpp
|
|
107
|
+
tests/docs/test_vertex_attr.cpp
|
|
108
|
+
tests/docs/test_edge_attr.cpp
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
target_link_libraries(runTests
|
|
112
|
+
PRIVATE GraphLayout
|
|
113
|
+
PRIVATE gtest gtest_main
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
if (GRAPH_LAYOUT_ENABLE_RANDOM_TESTS)
|
|
117
|
+
target_compile_definitions(runTests
|
|
118
|
+
PRIVATE GRAPH_LAYOUT_ENABLE_RANDOM_TESTS=ON
|
|
119
|
+
)
|
|
120
|
+
endif ()
|
|
121
|
+
|
|
122
|
+
add_test(NAME GraphLayoutTests COMMAND runTests)
|
|
123
|
+
endif ()
|
|
124
|
+
|
|
125
|
+
if(GRAPH_LAYOUT_BIND_PYTHON)
|
|
126
|
+
include(FetchContent)
|
|
127
|
+
FetchContent_Declare(
|
|
128
|
+
pybind11
|
|
129
|
+
GIT_REPOSITORY https://github.com/pybind/pybind11.git
|
|
130
|
+
GIT_TAG v3.0
|
|
131
|
+
)
|
|
132
|
+
FetchContent_MakeAvailable(pybind11)
|
|
133
|
+
|
|
134
|
+
pybind11_add_module(_core
|
|
135
|
+
python/bindings.cpp
|
|
136
|
+
)
|
|
137
|
+
target_link_libraries(_core
|
|
138
|
+
PRIVATE GraphLayout
|
|
139
|
+
)
|
|
140
|
+
install(TARGETS _core
|
|
141
|
+
LIBRARY DESTINATION sp_graph_layout)
|
|
142
|
+
install(FILES python/wrapper/__init__.py DESTINATION sp_graph_layout)
|
|
143
|
+
endif()
|
|
144
|
+
|
|
145
|
+
if (GRAPH_LAYOUT_BIND_ES)
|
|
146
|
+
|
|
147
|
+
add_executable(GraphLayoutWASM
|
|
148
|
+
wasm/graph_layout_wasm.cpp)
|
|
149
|
+
|
|
150
|
+
target_link_libraries(GraphLayoutWASM
|
|
151
|
+
PRIVATE GraphLayout
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
target_compile_options(GraphLayoutWASM PRIVATE "-O3")
|
|
155
|
+
|
|
156
|
+
set_target_properties(GraphLayoutWASM PROPERTIES SUFFIX ".js")
|
|
157
|
+
|
|
158
|
+
target_link_options(GraphLayoutWASM PRIVATE
|
|
159
|
+
"--bind"
|
|
160
|
+
"-sMODULARIZE=1"
|
|
161
|
+
"-sEXPORT_ES6=1"
|
|
162
|
+
"-sEXPORT_NAME=GraphLayoutWASMModule"
|
|
163
|
+
)
|
|
164
|
+
endif ()
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 - Present CyberZHG
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: sp-graph-layout
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A library for visualizing directed graphs.
|
|
5
|
+
License: MIT
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: Programming Language :: C++
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Project-URL: Homepage, https://github.com/CyberZHG/GraphLayout
|
|
10
|
+
Project-URL: Repository, https://github.com/CyberZHG/GraphLayout
|
|
11
|
+
Project-URL: Issues, https://github.com/CyberZHG/GraphLayout/issues
|
|
12
|
+
Project-URL: Documentation, https://cyberzhg.github.io/GraphLayout/
|
|
13
|
+
Requires-Python: >=3.8
|
|
14
|
+
Provides-Extra: test
|
|
15
|
+
Requires-Dist: pytest; extra == "test"
|
|
16
|
+
Requires-Dist: black; extra == "test"
|
|
17
|
+
Requires-Dist: isort; extra == "test"
|
|
18
|
+
Requires-Dist: flake8; extra == "test"
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
Graph Layout
|
|
22
|
+
============
|
|
23
|
+
|
|
24
|
+
## Overview
|
|
25
|
+
|
|
26
|
+
A library for visualizing directed graphs.
|
|
27
|
+
|
|
28
|
+
| rank dir = TB | rank dir = LR |
|
|
29
|
+
|:----------------------------------------------------------------------------------:|:----------------------------------------------------------------------------------:|
|
|
30
|
+
|  |  |
|
|
31
|
+
|  |  |
|
|
32
|
+
|
|
33
|
+
## Documentation
|
|
34
|
+
|
|
35
|
+
* [Documentation](https://cyberzhg.github.io/GraphLayout/)
|
|
36
|
+
|
|
37
|
+
* [Installation](https://cyberzhg.github.io/GraphLayout/install.html)
|
|
38
|
+
* [Basic Concepts](https://cyberzhg.github.io/GraphLayout/basic.html)
|
|
39
|
+
* [Graph Attributes](https://cyberzhg.github.io/GraphLayout/graph_attr.html)
|
|
40
|
+
* [Vertex Attributes](https://cyberzhg.github.io/GraphLayout/vertex_attr.html)
|
|
41
|
+
* [Edge Attributes](https://cyberzhg.github.io/GraphLayout/edge_attr.html)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Graph Layout
|
|
2
|
+
============
|
|
3
|
+
|
|
4
|
+
[](https://github.com/CyberZHG/GraphLayout/actions/workflows/cpp-unit-test.yml)
|
|
5
|
+
[](https://github.com/CyberZHG/GraphLayout/actions/workflows/python-build-test.yml)
|
|
6
|
+
[](https://github.com/CyberZHG/GraphLayout/actions/workflows/wasm-build-test.yml)
|
|
7
|
+
[](https://github.com/CyberZHG/GraphLayout/actions/workflows/deploy-docs.yml)
|
|
8
|
+
[](https://pypi.org/project/sp-graph-layout/)
|
|
9
|
+
[](https://www.npmjs.com/package/sp-graph-layout)
|
|
10
|
+
|
|
11
|
+
## Overview
|
|
12
|
+
|
|
13
|
+
A library for visualizing directed graphs.
|
|
14
|
+
|
|
15
|
+
| rank dir = TB | rank dir = LR |
|
|
16
|
+
|:------------------------------:|:------------------------------:|
|
|
17
|
+
|  |  |
|
|
18
|
+
|  |  |
|
|
19
|
+
|
|
20
|
+
## Documentation
|
|
21
|
+
|
|
22
|
+
* [Documentation](https://cyberzhg.github.io/GraphLayout/)
|
|
23
|
+
|
|
24
|
+
* [Installation](https://cyberzhg.github.io/GraphLayout/install.html)
|
|
25
|
+
* [Basic Concepts](https://cyberzhg.github.io/GraphLayout/basic.html)
|
|
26
|
+
* [Graph Attributes](https://cyberzhg.github.io/GraphLayout/graph_attr.html)
|
|
27
|
+
* [Vertex Attributes](https://cyberzhg.github.io/GraphLayout/vertex_attr.html)
|
|
28
|
+
* [Edge Attributes](https://cyberzhg.github.io/GraphLayout/edge_attr.html)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#ifndef GRAPHLAYOUT_BINARY_INDEXED_TREE_H
|
|
2
|
+
#define GRAPHLAYOUT_BINARY_INDEXED_TREE_H
|
|
3
|
+
|
|
4
|
+
#include <vector>
|
|
5
|
+
|
|
6
|
+
namespace graph_layout {
|
|
7
|
+
|
|
8
|
+
class BinaryIndexedTree {
|
|
9
|
+
public:
|
|
10
|
+
explicit BinaryIndexedTree(size_t n);
|
|
11
|
+
~BinaryIndexedTree() = default;
|
|
12
|
+
|
|
13
|
+
/** Add a number to a binary indexed tree.
|
|
14
|
+
*
|
|
15
|
+
* @param index The index to add the value.
|
|
16
|
+
* @param val The value to add.
|
|
17
|
+
*/
|
|
18
|
+
void add(int index, int val = 1);
|
|
19
|
+
|
|
20
|
+
/** Get the prefix sum from a binary indexed tree.
|
|
21
|
+
*
|
|
22
|
+
* @param index The index of the last element, inclusive.
|
|
23
|
+
* @return The prefix sum.
|
|
24
|
+
*/
|
|
25
|
+
[[nodiscard]] long long prefixSum(int index) const;
|
|
26
|
+
|
|
27
|
+
void clear();
|
|
28
|
+
void clear(size_t n);
|
|
29
|
+
|
|
30
|
+
private:
|
|
31
|
+
std::vector<long long> _bit;
|
|
32
|
+
|
|
33
|
+
static int next(int index);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
#endif //GRAPHLAYOUT_BINARY_INDEXED_TREE_H
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#ifndef GRAPHLAYOUT_COMPARE_SVG_H
|
|
2
|
+
#define GRAPHLAYOUT_COMPARE_SVG_H
|
|
3
|
+
|
|
4
|
+
#include <string>
|
|
5
|
+
|
|
6
|
+
namespace graph_layout {
|
|
7
|
+
/** A helper function for unit tests only.
|
|
8
|
+
*
|
|
9
|
+
* @param a
|
|
10
|
+
* @param b
|
|
11
|
+
* @return Whether the two input SVGs are the same.
|
|
12
|
+
*/
|
|
13
|
+
bool _compareSVG(const std::string& a, const std::string& b);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
#endif //GRAPHLAYOUT_COMPARE_SVG_H
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#ifndef GRAPHLAYOUT_GRAPH_ATTRIBUTES_H
|
|
2
|
+
#define GRAPHLAYOUT_GRAPH_ATTRIBUTES_H
|
|
3
|
+
|
|
4
|
+
#include <string>
|
|
5
|
+
#include <unordered_map>
|
|
6
|
+
|
|
7
|
+
namespace graph_layout {
|
|
8
|
+
|
|
9
|
+
constexpr std::string ATTRIBUTE_KEY_BG_COLOR = "bgcolor";
|
|
10
|
+
constexpr std::string ATTRIBUTE_KEY_RANK_DIR = "rankdir";
|
|
11
|
+
constexpr std::string ATTRIBUTE_KEY_LABEL = "label";
|
|
12
|
+
constexpr std::string ATTRIBUTE_KEY_SHAPE = "shape";
|
|
13
|
+
constexpr std::string ATTRIBUTE_KEY_FONT_NAME = "fontname";
|
|
14
|
+
constexpr std::string ATTRIBUTE_KEY_FONT_SIZE = "fontsize";
|
|
15
|
+
constexpr std::string ATTRIBUTE_KEY_WIDTH = "width";
|
|
16
|
+
constexpr std::string ATTRIBUTE_KEY_HEIGHT = "height";
|
|
17
|
+
|
|
18
|
+
class Attribute {
|
|
19
|
+
public:
|
|
20
|
+
Attribute();
|
|
21
|
+
explicit Attribute(const std::string& value);
|
|
22
|
+
~Attribute() = default;
|
|
23
|
+
|
|
24
|
+
void set(const std::string& value);
|
|
25
|
+
[[nodiscard]] const std::string& value() const;
|
|
26
|
+
|
|
27
|
+
protected:
|
|
28
|
+
std::string _raw;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
class AttributeColor : public Attribute {
|
|
32
|
+
public:
|
|
33
|
+
using Attribute::Attribute;
|
|
34
|
+
|
|
35
|
+
[[nodiscard]] static std::tuple<double, double, double> toRGB(const std::string& raw);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
class AttributeRankDir : public Attribute {
|
|
39
|
+
public:
|
|
40
|
+
using Attribute::Attribute;
|
|
41
|
+
|
|
42
|
+
static const std::string TOP_TO_BOTTOM;
|
|
43
|
+
static const std::string BOTTOM_TO_TOP;
|
|
44
|
+
static const std::string LEFT_TO_RIGHT;
|
|
45
|
+
static const std::string RIGHT_TO_LEFT;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
class AttributeShape : public Attribute {
|
|
49
|
+
public:
|
|
50
|
+
using Attribute::Attribute;
|
|
51
|
+
|
|
52
|
+
static const std::string NONE;
|
|
53
|
+
static const std::string CIRCLE;
|
|
54
|
+
static const std::string DOUBLE_CIRCLE;
|
|
55
|
+
static const std::string ELLIPSE;
|
|
56
|
+
static const std::string RECT;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
class Attributes {
|
|
60
|
+
public:
|
|
61
|
+
Attributes() = default;
|
|
62
|
+
~Attributes() = default;
|
|
63
|
+
|
|
64
|
+
[[nodiscard]] std::string graphAttributes(const std::string& key) const;
|
|
65
|
+
void setGraphAttributes(const std::string& key, const std::string& value);
|
|
66
|
+
void setGraphAttributes(const std::unordered_map<std::string, std::string> &attributes);
|
|
67
|
+
|
|
68
|
+
[[nodiscard]] std::string vertexAttributes(int u, const std::string& key) const;
|
|
69
|
+
void setVertexAttributes(int u, const std::string& key, const std::string& value);
|
|
70
|
+
void setVertexAttributes(int u, const std::unordered_map<std::string, std::string> &attributes);
|
|
71
|
+
|
|
72
|
+
[[nodiscard]] std::string edgeAttributes(int u, const std::string& key) const;
|
|
73
|
+
void setEdgeAttributes(int u, const std::string& key, const std::string& value);
|
|
74
|
+
void setEdgeAttributes(int u, const std::unordered_map<std::string, std::string>& mapping);
|
|
75
|
+
void transferEdgeAttributes(int u, int v);
|
|
76
|
+
|
|
77
|
+
[[nodiscard]] std::string rankDir() const;
|
|
78
|
+
void setRankDir(const std::string& value);
|
|
79
|
+
|
|
80
|
+
void setVertexShape(int u, const std::string& value);
|
|
81
|
+
|
|
82
|
+
private:
|
|
83
|
+
static std::unordered_map<std::string, std::string> DEFAULT_GRAPH_ATTRIBUTE_VALUES;
|
|
84
|
+
static std::unordered_map<std::string, std::string> DEFAULT_VERTEX_ATTRIBUTE_VALUES;
|
|
85
|
+
static std::unordered_map<std::string, std::string> DEFAULT_EDGE_ATTRIBUTE_VALUES;
|
|
86
|
+
|
|
87
|
+
std::unordered_map<std::string, std::string> _graphAttributes;
|
|
88
|
+
std::unordered_map<std::string, std::string> _vertexGlobalAttributes;
|
|
89
|
+
std::unordered_map<int, std::unordered_map<std::string, std::string>> _vertexAttributes;
|
|
90
|
+
std::unordered_map<std::string, std::string> _edgeGlobalAttributes;
|
|
91
|
+
std::unordered_map<int, std::unordered_map<std::string, std::string>> _edgeAttributes;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
#endif //GRAPHLAYOUT_GRAPH_ATTRIBUTES_H
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
#ifndef GRAPHLAYOUT_GRAPH_DEF_H
|
|
2
|
+
#define GRAPHLAYOUT_GRAPH_DEF_H
|
|
3
|
+
|
|
4
|
+
#include <vector>
|
|
5
|
+
#include <unordered_set>
|
|
6
|
+
#include <unordered_map>
|
|
7
|
+
#include <memory>
|
|
8
|
+
|
|
9
|
+
namespace graph_layout {
|
|
10
|
+
|
|
11
|
+
class EdgeIterationWithIDs;
|
|
12
|
+
|
|
13
|
+
struct SPEdge {
|
|
14
|
+
int id, u, v;
|
|
15
|
+
|
|
16
|
+
bool operator==(const SPEdge&) const;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
struct SPVirtualEdge {
|
|
20
|
+
SPEdge originalEdge;
|
|
21
|
+
std::vector<int> virtualEdgeIds;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
class SPDirectedGraph {
|
|
25
|
+
public:
|
|
26
|
+
explicit SPDirectedGraph(size_t numVertices);
|
|
27
|
+
~SPDirectedGraph() = default;
|
|
28
|
+
|
|
29
|
+
void updateNumVertices(size_t numVertices);
|
|
30
|
+
[[nodiscard]] size_t numVertices() const { return _numVertices; }
|
|
31
|
+
[[nodiscard]] size_t numEdges() const { return _edges.size(); }
|
|
32
|
+
[[nodiscard]] const std::vector<SPEdge>& edges() const { return _edges; }
|
|
33
|
+
std::vector<SPEdge>& edges() { return _edges;}
|
|
34
|
+
|
|
35
|
+
void addEdge(const SPEdge& edge);
|
|
36
|
+
int addEdge(int u, int v);
|
|
37
|
+
void addEdges(const std::vector<std::pair<int ,int>>& edges);
|
|
38
|
+
void addOutEdges(int u, const std::vector<int>& vertices);
|
|
39
|
+
SPEdge& getEdge(int id);
|
|
40
|
+
void removeEdge(int id);
|
|
41
|
+
|
|
42
|
+
bool operator==(const SPDirectedGraph& other) const;
|
|
43
|
+
|
|
44
|
+
void disableSelfCycleEdges();
|
|
45
|
+
void enableSelfCycleEdges();
|
|
46
|
+
|
|
47
|
+
void reverseEdges(const std::unordered_set<int>& ids);
|
|
48
|
+
void reverseEdgesBack();
|
|
49
|
+
[[nodiscard]] bool isReverseEdge(int id) const;
|
|
50
|
+
|
|
51
|
+
void sortEdgesById();
|
|
52
|
+
const std::unordered_map<int, size_t>& getEdgeIdToIndexMap();
|
|
53
|
+
const std::vector<int>& getInDegrees();
|
|
54
|
+
const std::vector<int>& getOutDegrees();
|
|
55
|
+
const std::vector<std::vector<int>>& getInVertices();
|
|
56
|
+
const std::vector<std::vector<int>>& getOutVertices();
|
|
57
|
+
std::vector<std::vector<int>>& getInEdgeIdsRef();
|
|
58
|
+
std::vector<std::vector<int>>& getOutEdgeIdsRef();
|
|
59
|
+
const std::vector<std::vector<int>>& getInEdgeIds();
|
|
60
|
+
const std::vector<std::vector<int>>& getOutEdgeIds();
|
|
61
|
+
EdgeIterationWithIDs getInEdges(int v);
|
|
62
|
+
EdgeIterationWithIDs getOutEdges(int u);
|
|
63
|
+
bool hasCycle();
|
|
64
|
+
|
|
65
|
+
[[nodiscard]] SPDirectedGraph buildSpanningTree(const std::vector<int>& parents);
|
|
66
|
+
|
|
67
|
+
private:
|
|
68
|
+
size_t _numVertices{};
|
|
69
|
+
std::vector<SPEdge> _edges;
|
|
70
|
+
|
|
71
|
+
bool _edgeIdToIndexMapInitialized = false;
|
|
72
|
+
std::unordered_map<int, size_t> _edgeIdToIndexMap;
|
|
73
|
+
|
|
74
|
+
bool _degreesInitialized = false;
|
|
75
|
+
std::vector<int> _inDegrees;
|
|
76
|
+
std::vector<int> _outDegrees;
|
|
77
|
+
|
|
78
|
+
bool _inOutVerticesInitialized = false;
|
|
79
|
+
std::vector<std::vector<int>> _inVertices;
|
|
80
|
+
std::vector<std::vector<int>> _outVertices;
|
|
81
|
+
|
|
82
|
+
bool _inOutEdgesInitialized = false;
|
|
83
|
+
std::vector<std::vector<int>> _inEdges;
|
|
84
|
+
std::vector<std::vector<int>> _outEdges;
|
|
85
|
+
|
|
86
|
+
bool _hasCycleInitialized = false;
|
|
87
|
+
bool _hasCycle = false;
|
|
88
|
+
|
|
89
|
+
std::vector<SPEdge> _selfCycleEdges;
|
|
90
|
+
|
|
91
|
+
std::unordered_set<int> _reverseIds;
|
|
92
|
+
|
|
93
|
+
void resetInitialization();
|
|
94
|
+
void initializeDegrees();
|
|
95
|
+
void initializeInOutVertices();
|
|
96
|
+
void initializeInOutEdges();
|
|
97
|
+
void initializeHasCycle();
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
class EdgeIterationWithIDs {
|
|
101
|
+
public:
|
|
102
|
+
EdgeIterationWithIDs(SPDirectedGraph& graph, const std::vector<int>& ids) : _graph(graph), _ids(ids) {}
|
|
103
|
+
|
|
104
|
+
class iterator {
|
|
105
|
+
public:
|
|
106
|
+
explicit iterator(SPDirectedGraph& graph, const std::vector<int>& ids, const int index) : _graph(graph), _ids(ids), _index(index) {}
|
|
107
|
+
const SPEdge &operator*() const;
|
|
108
|
+
iterator& operator++() { ++_index; return *this; }
|
|
109
|
+
bool operator!=(const iterator& other) const { return _index != other._index; }
|
|
110
|
+
private:
|
|
111
|
+
SPDirectedGraph& _graph;
|
|
112
|
+
const std::vector<int>& _ids;
|
|
113
|
+
int _index;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
[[nodiscard]] iterator begin() const { return iterator(_graph, _ids, 0); }
|
|
117
|
+
[[nodiscard]] iterator end() const { return iterator(_graph, _ids, static_cast<int>(_ids.size())); }
|
|
118
|
+
private:
|
|
119
|
+
SPDirectedGraph &_graph;
|
|
120
|
+
const std::vector<int> &_ids;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
class RandomSimpleDirectedGraphGenerator {
|
|
124
|
+
public:
|
|
125
|
+
explicit RandomSimpleDirectedGraphGenerator(const int maxNumVertices) : _minNumVertices(1), _maxNumVertices(maxNumVertices), _allowSelfCycle(false) {}
|
|
126
|
+
|
|
127
|
+
[[nodiscard]] SPDirectedGraph generateRandomGraph() const;
|
|
128
|
+
[[nodiscard]] SPDirectedGraph generateRandomGraphWithoutDuplicateEdge() const;
|
|
129
|
+
private:
|
|
130
|
+
int _minNumVertices;
|
|
131
|
+
int _maxNumVertices;
|
|
132
|
+
bool _allowSelfCycle;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
class GraphComponentSplitter {
|
|
136
|
+
public:
|
|
137
|
+
static std::vector<int> getConnectedComponents(const SPDirectedGraph& graph);
|
|
138
|
+
std::vector<SPDirectedGraph>& splitGraph(const SPDirectedGraph& graph);
|
|
139
|
+
[[nodiscard]] SPDirectedGraph mergeBack() const;
|
|
140
|
+
[[nodiscard]] int originalVertexId(int groupIndex, int u) const;
|
|
141
|
+
|
|
142
|
+
private:
|
|
143
|
+
std::vector<SPDirectedGraph> _graphs;
|
|
144
|
+
std::vector<std::vector<int>> _groups;
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
#endif //GRAPHLAYOUT_GRAPH_DEF_H
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#ifndef GRAPHLAYOUT_CROSS_MINIMIZATION_H
|
|
2
|
+
#define GRAPHLAYOUT_CROSS_MINIMIZATION_H
|
|
3
|
+
|
|
4
|
+
#include "common/graph_def.h"
|
|
5
|
+
#include "common/binary_indexed_tree.h"
|
|
6
|
+
#include <functional>
|
|
7
|
+
|
|
8
|
+
namespace graph_layout {
|
|
9
|
+
|
|
10
|
+
/** The struct for storing the results of cross minimization */
|
|
11
|
+
struct SPLayering {
|
|
12
|
+
// Discrete ranks for each layer.
|
|
13
|
+
std::vector<int> layerRanks;
|
|
14
|
+
// Vertex order within each layer.
|
|
15
|
+
std::vector<std::vector<int>> orders;
|
|
16
|
+
// Mapping from a vertex ID to its index in the corresponding layer.
|
|
17
|
+
std::vector<std::unordered_map<int, int>> positions;
|
|
18
|
+
// Mapping from a vertex ID to the layer it belongs to.
|
|
19
|
+
std::unordered_map<int, int> idToLayer;
|
|
20
|
+
// Maximum number of vertices in each layer.
|
|
21
|
+
size_t width;
|
|
22
|
+
|
|
23
|
+
/** Initialize the two mappings in this struct.
|
|
24
|
+
*
|
|
25
|
+
* Note that we only guarantee that the mappings are initialized
|
|
26
|
+
* in the return values of `CrossMinimization`.
|
|
27
|
+
*/
|
|
28
|
+
void initializeMapping();
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
enum class CrossMinimizationMethod {
|
|
32
|
+
// Barycenter heuristic.
|
|
33
|
+
BARYCENTER,
|
|
34
|
+
// Median heuristic.
|
|
35
|
+
MEDIAN,
|
|
36
|
+
// Greedily switch two adjacent vertices.
|
|
37
|
+
PAIRWISE_SWITCH,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/** Reduce the number of crossings between two adjacent layers. */
|
|
41
|
+
class CrossMinimization {
|
|
42
|
+
public:
|
|
43
|
+
explicit CrossMinimization(CrossMinimizationMethod method = CrossMinimizationMethod::BARYCENTER);
|
|
44
|
+
~CrossMinimization() = default;
|
|
45
|
+
|
|
46
|
+
// The start index for virtual edges.
|
|
47
|
+
static constexpr int VIRTUAL_EDGE_ID_OFFSET = 1000000000;
|
|
48
|
+
|
|
49
|
+
void setMethod(CrossMinimizationMethod method);
|
|
50
|
+
|
|
51
|
+
/** Reduce the number of crossings between each two adjacent layers.
|
|
52
|
+
*
|
|
53
|
+
* @param graph A connected DAG.
|
|
54
|
+
* @param ranks Layer assignment of vertices.
|
|
55
|
+
* @return Orders of vertices in each layer and any virtual edges added to the graph.
|
|
56
|
+
*/
|
|
57
|
+
std::pair<SPLayering, std::vector<SPVirtualEdge>> reduceNumCross(SPDirectedGraph& graph, std::vector<int>& ranks) const;
|
|
58
|
+
|
|
59
|
+
/** Add virtual edges to the graph so that no edge spans more than two layers.
|
|
60
|
+
*
|
|
61
|
+
* @param graph A connected DAG.
|
|
62
|
+
* @param ranks Layer assignment of vertices.
|
|
63
|
+
* @return Orders of vertices in each layer and any virtual edges added to the graph.
|
|
64
|
+
*/
|
|
65
|
+
static std::pair<SPLayering, std::vector<SPVirtualEdge>> addVirtualEdges(SPDirectedGraph& graph, std::vector<int>& ranks);
|
|
66
|
+
|
|
67
|
+
/** Compute the total number of crossings between each two adjacent layers.
|
|
68
|
+
*
|
|
69
|
+
* This function is mainly used for testing.
|
|
70
|
+
*
|
|
71
|
+
* @param graph A connected DAG.
|
|
72
|
+
* @param layering A cross minimization result.
|
|
73
|
+
* @return Total number of crossings.
|
|
74
|
+
*/
|
|
75
|
+
static long long computeNumCross(SPDirectedGraph& graph, const SPLayering& layering);
|
|
76
|
+
|
|
77
|
+
private:
|
|
78
|
+
CrossMinimizationMethod _method;
|
|
79
|
+
|
|
80
|
+
static long long computeNumCross(
|
|
81
|
+
SPDirectedGraph &graph,
|
|
82
|
+
BinaryIndexedTree &bit,
|
|
83
|
+
const std::vector<int> &order1,
|
|
84
|
+
const std::vector<int> &order2,
|
|
85
|
+
bool forward = true);
|
|
86
|
+
static long long computeNumCross(SPDirectedGraph& graph,
|
|
87
|
+
const std::vector<std::unordered_map<int, int>> &positions,
|
|
88
|
+
std::vector<int> &adjPositionsU,
|
|
89
|
+
std::vector<int> &adjPositionsV,
|
|
90
|
+
int layerIndex, int u, int v, bool forward);
|
|
91
|
+
static long long computeNumCross(SPDirectedGraph& graph,
|
|
92
|
+
const std::vector<std::unordered_map<int, int>> &positions,
|
|
93
|
+
std::vector<int> &adjPositionsU,
|
|
94
|
+
std::vector<int> &adjPositionsV,
|
|
95
|
+
int layerIndex, int u, int v);
|
|
96
|
+
|
|
97
|
+
static void reduceNumCrossWithWeightingHeuristic(SPDirectedGraph& graph, SPLayering& layering,
|
|
98
|
+
const std::function<double(SPDirectedGraph&, const std::unordered_map<int, int>&, int, bool)> &weighting);
|
|
99
|
+
static void reduceNumCrossWithBaryCenterHeuristic(SPDirectedGraph& graph, SPLayering& layering);
|
|
100
|
+
static void reduceNumCrossWithMedianHeuristic(SPDirectedGraph& graph, SPLayering& layering);
|
|
101
|
+
static void reduceNumCrossWithPairwiseSwitchHeuristic(SPDirectedGraph& graph, SPLayering& layering);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
#endif //GRAPHLAYOUT_CROSS_MINIMIZATION_H
|