Skip to content

Commit ecd335f

Browse files
committed
Sema: Add utility header for working with relations represented by Boolean matrices
1 parent 06f5eef commit ecd335f

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed

lib/Sema/Relation.h

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
//===--- Relation.h - Relations and boolean matrices ------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2026 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// The code here is meant for debugging relations implemented as boolean
14+
// predicates. You can construct a Boolean matrix by evaluating the predicate
15+
// against all possible pairs of values from some range, and then check that
16+
// this matrix satisfies various conditions.
17+
//
18+
//===----------------------------------------------------------------------===//
19+
20+
#ifndef SWIFT_SEMA_RELATION_H
21+
#define SWIFT_SEMA_RELATION_H
22+
23+
#include "swift/Basic/Assertions.h"
24+
#include "llvm/ADT/STLExtras.h"
25+
#include "llvm/Support/raw_ostream.h"
26+
#include <vector>
27+
28+
namespace swift {
29+
30+
namespace constraints {
31+
32+
struct BooleanMatrix {
33+
std::vector<std::vector<bool>> elements;
34+
35+
size_t rows() const {
36+
return elements.size();
37+
}
38+
39+
size_t columns() const {
40+
return elements[0].size();
41+
}
42+
43+
explicit BooleanMatrix(std::vector<std::vector<bool>> elements)
44+
: elements(elements) {
45+
ASSERT(elements.size() > 0);
46+
size_t columns = elements[0].size();
47+
for (const auto &row : elements) {
48+
ASSERT(columns == row.size());
49+
}
50+
}
51+
52+
void dump(llvm::raw_ostream &out) {
53+
for (auto &row : elements) {
54+
llvm::interleave(
55+
row,
56+
[&](bool elt) { out << (elt ? "1" : "0"); },
57+
[&]() { out << " "; });
58+
out << "\n";
59+
}
60+
}
61+
62+
BooleanMatrix multiply(const BooleanMatrix &other) const {
63+
std::vector<std::vector<bool>> result;
64+
65+
ASSERT(columns() == other.rows());
66+
67+
for (unsigned i = 0; i < rows(); ++i) {
68+
result.emplace_back();
69+
for (unsigned j = 0; j < other.columns(); ++j) {
70+
bool entry = false;
71+
for (unsigned k = 0; k < columns(); ++k) {
72+
entry |= elements[i][k] && other.elements[k][j];
73+
}
74+
result.back().push_back(entry);
75+
}
76+
}
77+
78+
return BooleanMatrix(result);
79+
}
80+
81+
bool isReflexive() const {
82+
ASSERT(rows() == columns());
83+
84+
for (unsigned i = 0; i < rows(); ++i) {
85+
if (!elements[i][i])
86+
return false;
87+
}
88+
89+
return true;
90+
}
91+
92+
bool isAntiReflexive() const {
93+
ASSERT(rows() == columns());
94+
95+
for (unsigned i = 0; i < rows(); ++i) {
96+
if (elements[i][i])
97+
return false;
98+
}
99+
100+
return true;
101+
}
102+
103+
bool isSymmetric() const {
104+
ASSERT(rows() == columns());
105+
106+
for (unsigned i = 0; i < rows(); ++i) {
107+
for (unsigned j = 0; j < i; ++j) {
108+
if (elements[i][j] != elements[j][i])
109+
return false;
110+
}
111+
}
112+
113+
return true;
114+
}
115+
116+
bool isAntiSymmetric() const {
117+
ASSERT(rows() == columns());
118+
119+
for (unsigned i = 0; i < rows(); ++i) {
120+
for (unsigned j = 0; j < i; ++j) {
121+
if (elements[i][j] && elements[j][i])
122+
return false;
123+
}
124+
}
125+
126+
return true;
127+
}
128+
129+
bool isTransitive() const {
130+
ASSERT(rows() == columns());
131+
132+
auto square = multiply(*this);
133+
for (unsigned i = 0; i < square.rows(); ++i) {
134+
for (unsigned j = 0; j < square.columns(); ++j) {
135+
if (square.elements[i][j] && !elements[i][j])
136+
return false;
137+
}
138+
}
139+
140+
return true;
141+
}
142+
143+
template<typename Iter, typename Fn>
144+
static BooleanMatrix forPredicate(Iter begin, Iter end, Fn pred) {
145+
std::vector<std::vector<bool>> elements;
146+
147+
for (Iter row = begin; row != end; ++row) {
148+
elements.emplace_back();
149+
for (Iter col = begin; col != end; ++col)
150+
elements.back().push_back(pred(*row, *col));
151+
}
152+
153+
return BooleanMatrix(elements);
154+
}
155+
};
156+
157+
}
158+
159+
}
160+
161+
#endif // SWIFT_SEMA_RELATION_H

0 commit comments

Comments
 (0)