blob: c302458f84b99aec333dd247007807fa6b0fa4af [file] [log] [blame]
// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.graph;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* <p>A simple and inefficient directed graph with the adjacency
* relation represented as a 2-D bit-matrix. </p>
*
* <p> Used as an adjunct to Digraph for performing certain algorithms
* which are more naturally implemented on this representation,
* e.g. transitive closure and reduction. </p>
*
* <p> Not many operations are supported. </p>
*/
final class Matrix<T> {
/**
* Constructs a square bit-matrix, initially empty, with the ith row/column
* corresponding to the ith element of 'labels', in iteration order.
*
* Does not retain a references to 'labels'.
*/
public Matrix(Set<T> labels) {
this.N = labels.size();
this.values = new ArrayList<T>(N);
this.indices = new HashMap<>();
this.m = new boolean[N][N];
for (T label: labels) {
int idx = values.size();
values.add(label);
indices.put(label, idx);
}
}
/**
* Constructs a matrix from the set of logical values specified. There is
* one row/column for each node in the graph, and the entry matrix[i,j] is
* set iff there is an edge in 'graph' from the node labelled values[i] to
* the node labelled values[j].
*/
public Matrix(Digraph<T> graph) {
this(graph.getLabels());
for (Node<T> nfrom: graph.getNodes()) {
Integer ifrom = indices.get(nfrom.getLabel());
for (Node<T> nto: nfrom.getSuccessors()) {
Integer ito = indices.get(nto.getLabel());
m[ifrom][ito] = true;
}
}
}
/**
* The size of one side of the matrix.
*/
private final int N;
/**
* The logical values associated with each row/column.
*/
private final List<T> values;
/**
* The mapping from logical values to row/column index.
*/
private final Map<T, Integer> indices;
/**
* The bit-matrix itself.
* m[from][to] indicates an edge from-->to.
*/
private final boolean[][] m;
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (int ii = 0; ii < N; ++ii) {
for (int jj = 0; jj < N; ++jj) {
sb.append(m[ii][jj] ? '1' : '0');
}
sb.append(' ').append(values.get(ii)).append('\n');
}
return sb.toString();
}
}