forked from mysql/mysql-server
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhypergraph.h
118 lines (96 loc) · 4.58 KB
/
hypergraph.h
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
/* Copyright (c) 2020, 2024, Oracle and/or its affiliates.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2.0,
as published by the Free Software Foundation.
This program is designed to work with certain software (including
but not limited to OpenSSL) that is licensed under separate terms,
as designated in a particular file or component or in included license
documentation. The authors of MySQL hereby grant you an additional
permission to link the program and your derivative works with the
separately licensed software that they have either included with
the program or referenced in the documentation.
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, version 2.0, for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#ifndef SQL_JOIN_OPTIMIZER_HYPERGRAPH_H_
#define SQL_JOIN_OPTIMIZER_HYPERGRAPH_H_ 1
/**
@file
Definition of an undirected (join) hypergraph. A hypergraph in this context
is an undirected graph consisting of nodes and hyperedges, where hyperedges
are edges that can have more than one node in each side of the edge.
For instance, in a graph with nodes {A, B, C, D}, a regular undirected edge
could be e.g. (A,B), while in a hypergraph, an edge such as ({A,C},B) would
also be allowed. Note that this definition of hypergraphs differs from that
on Wikipedia.
The main user of Hypergraph is subgraph_enumeration.h.
*/
#include <stddef.h>
#include <algorithm>
#include <bit>
#include <vector>
#include "sql/join_optimizer/node_map.h"
#include "sql/mem_root_array.h"
struct MEM_ROOT;
namespace hypergraph {
struct Node {
// List of edges (indexes into the hypergraph's “edges” array) that touch this
// node. We split these into simple edges (only one node on each side) and
// complex edges (all others), because we can often quickly discard all simple
// edges by testing the set of interesting nodes against the
// “simple_neighborhood” bitmap.
//
// For optimization purposes, the edges are stored as if they were directed,
// even though the hypergraph is fundamentally undirected. That is, a (u,v)
// edge will be duplicated internally to (v,u), and the version that is posted
// in a node's edge list is the one where the node itself is on the left side.
// This saves a lot of duplicate code, and also reduces the amount of branch
// mispredictions significantly (it helps something like 30% on the overall
// speed).
std::vector<unsigned> complex_edges, simple_edges;
// All nodes on the “right” side of an edge in simple_edges.
NodeMap simple_neighborhood = 0;
private:
// Speeds up BM_HyperStar17_ManyHyperedges by 5–10%.
// (MSVC with debug STL will get a dummy byte here, since the struct is
// already more than 64 bytes.)
static constexpr int Size =
sizeof(std::vector<unsigned>) * 2 + sizeof(NodeMap);
char padding[std::max<int>(1, 64 - Size)];
};
static_assert(sizeof(Node) >= 64);
struct Hyperedge {
// The endpoints (hypernodes) of this hyperedge. See the comment about
// duplicated edges in Node.
//
// left and right may not overlap, and both must have at least one bit set.
NodeMap left;
NodeMap right;
};
struct Hypergraph {
public:
explicit Hypergraph(MEM_ROOT *mem_root) : nodes(mem_root), edges(mem_root) {}
Mem_root_array<Node> nodes; // Maximum 8*sizeof(NodeMap) elements.
Mem_root_array<Hyperedge> edges;
void AddNode();
void AddEdge(NodeMap left, NodeMap right);
// NOTE: Since every edge is stored twice (see AddEdge), also updates the
// corresponding opposite-direction edge automatically. Also note that this
// will shift internal edge lists around, so even after no-op changes,
// you are not guaranteed to get back subgraph pairs in the same order
// as before.
void ModifyEdge(unsigned edge_idx, NodeMap new_left, NodeMap new_right);
private:
void AttachEdgeToNodes(size_t left_first_idx, size_t right_first_idx,
NodeMap left, NodeMap right);
};
/// Is an edge between "left" and "right" a simple edge?
inline bool IsSimpleEdge(NodeMap left, NodeMap right) {
return std::has_single_bit(left) && std::has_single_bit(right);
}
} // namespace hypergraph
#endif // SQL_JOIN_OPTIMIZER_HYPERGRAPH_H_