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