Skip to content

Commit 2a100f5

Browse files
s1ckknutwalker
andcommitted
Add GraphCharacteristics
Co-Authored-By: Paul Horn <paul.horn@neotechnology.com>
1 parent 2e3ee1a commit 2a100f5

File tree

2 files changed

+236
-0
lines changed

2 files changed

+236
-0
lines changed
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Neo4j is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
package org.neo4j.gds.api;
21+
22+
import org.neo4j.gds.Orientation;
23+
import org.neo4j.gds.api.schema.Direction;
24+
25+
import java.util.Objects;
26+
27+
/**
28+
* Graph characteristics describe certain capabilities of the graph.
29+
* <p>
30+
* Algorithms define the graph characteristics that they require to
31+
* for correct execution. The execution framework can use both, the
32+
* graph and the required characteristics to check if the algorithm
33+
* can be run on the given graph.
34+
*/
35+
public final class GraphCharacteristics {
36+
37+
public static final GraphCharacteristics ALL;
38+
public static final GraphCharacteristics NONE;
39+
40+
static {
41+
ALL = GraphCharacteristics.builder().directed().undirected().inverseIndexed().build();
42+
NONE = GraphCharacteristics.builder().build();
43+
}
44+
45+
private static final int DIRECTED = 1;
46+
private static final int UNDIRECTED = 1 << 1;
47+
private static final int INVERSE_INDEXED = 1 << 2;
48+
49+
// We use a single int value to store the characteristics.
50+
// Each bit represents a characteristic. Setting / Getting
51+
// a characteristic is performed by bit-wise Or / And.
52+
private final int characteristics;
53+
54+
public static GraphCharacteristics.Builder builder() {
55+
return new Builder();
56+
}
57+
58+
private GraphCharacteristics(int characteristics) {
59+
this.characteristics = characteristics;
60+
}
61+
62+
public boolean isDirected() {
63+
return (characteristics() & DIRECTED) == DIRECTED;
64+
}
65+
66+
public boolean isUndirected() {
67+
return (characteristics() & UNDIRECTED) == UNDIRECTED;
68+
}
69+
70+
public boolean isInverseIndexed() {
71+
return (characteristics() & INVERSE_INDEXED) == INVERSE_INDEXED;
72+
}
73+
74+
private int characteristics() {
75+
return characteristics;
76+
}
77+
78+
@Override
79+
public String toString() {
80+
return "GraphCharacteristics{" +
81+
"isDirected=" + isDirected() +
82+
", isUndirected=" + isUndirected() +
83+
", isInverseIndexed=" + isInverseIndexed() +
84+
'}';
85+
}
86+
87+
@Override
88+
public boolean equals(Object o) {
89+
if (this == o) return true;
90+
if (o == null || getClass() != o.getClass()) return false;
91+
GraphCharacteristics that = (GraphCharacteristics) o;
92+
return characteristics == that.characteristics;
93+
}
94+
95+
@Override
96+
public int hashCode() {
97+
return Objects.hash(characteristics);
98+
}
99+
100+
public static class Builder {
101+
private int characteristics = 0;
102+
103+
public Builder directed() {
104+
this.characteristics |= GraphCharacteristics.DIRECTED;
105+
return this;
106+
}
107+
108+
public Builder undirected() {
109+
this.characteristics |= GraphCharacteristics.UNDIRECTED;
110+
return this;
111+
}
112+
113+
public Builder inverseIndexed() {
114+
this.characteristics |= GraphCharacteristics.INVERSE_INDEXED;
115+
return this;
116+
}
117+
118+
public Builder withOrientation(Orientation orientation) {
119+
switch (orientation) {
120+
case NATURAL:
121+
case REVERSE:
122+
return this.directed();
123+
case UNDIRECTED:
124+
return this.undirected();
125+
default:
126+
throw new UnsupportedOperationException("Unexpected orientation: " + orientation);
127+
}
128+
}
129+
130+
public Builder withDirection(Direction direction) {
131+
switch (direction) {
132+
case DIRECTED:
133+
return this.directed();
134+
case UNDIRECTED:
135+
return this.undirected();
136+
default:
137+
throw new UnsupportedOperationException("Unexpected direction: " + direction);
138+
}
139+
}
140+
141+
public GraphCharacteristics build() {
142+
return new GraphCharacteristics(this.characteristics);
143+
}
144+
}
145+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Neo4j is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
package org.neo4j.gds.api;
21+
22+
import org.junit.jupiter.api.Test;
23+
import org.junit.jupiter.params.ParameterizedTest;
24+
import org.junit.jupiter.params.provider.Arguments;
25+
import org.junit.jupiter.params.provider.MethodSource;
26+
import org.neo4j.gds.Orientation;
27+
import org.neo4j.gds.api.schema.Direction;
28+
29+
import java.util.stream.Stream;
30+
31+
import static org.assertj.core.api.Assertions.assertThat;
32+
33+
class GraphCharacteristicsTest {
34+
35+
@Test
36+
void emptyCharacteristics() {
37+
var characteristics = GraphCharacteristics.builder().build();
38+
assertThat(characteristics.isUndirected()).isFalse();
39+
assertThat(characteristics.isDirected()).isFalse();
40+
assertThat(characteristics.isInverseIndexed()).isFalse();
41+
42+
assertThat(characteristics).isEqualTo(GraphCharacteristics.NONE);
43+
}
44+
45+
@Test
46+
void nonEmptyCharacteristics() {
47+
var characteristics = GraphCharacteristics.builder().directed().build();
48+
assertThat(characteristics.isDirected()).isTrue();
49+
assertThat(characteristics.isUndirected()).isFalse();
50+
assertThat(characteristics.isInverseIndexed()).isFalse();
51+
52+
characteristics = GraphCharacteristics.builder().directed().undirected().build();
53+
assertThat(characteristics.isDirected()).isTrue();
54+
assertThat(characteristics.isUndirected()).isTrue();
55+
assertThat(characteristics.isInverseIndexed()).isFalse();
56+
57+
characteristics = GraphCharacteristics.builder().directed().undirected().inverseIndexed().build();
58+
assertThat(characteristics.isDirected()).isTrue();
59+
assertThat(characteristics.isUndirected()).isTrue();
60+
assertThat(characteristics.isInverseIndexed()).isTrue();
61+
}
62+
63+
static Stream<Arguments> orientation() {
64+
return Stream.of(
65+
Arguments.of(Orientation.NATURAL, GraphCharacteristics.builder().directed().build()),
66+
Arguments.of(Orientation.REVERSE, GraphCharacteristics.builder().directed().build()),
67+
Arguments.of(Orientation.UNDIRECTED, GraphCharacteristics.builder().undirected().build())
68+
);
69+
}
70+
71+
@ParameterizedTest
72+
@MethodSource("orientation")
73+
void buildFromOrientation(Orientation orientation, GraphCharacteristics expected) {
74+
var actual = GraphCharacteristics.builder().withOrientation(orientation).build();
75+
assertThat(actual).isEqualTo(expected);
76+
}
77+
78+
static Stream<Arguments> direction() {
79+
return Stream.of(
80+
Arguments.of(Direction.DIRECTED, GraphCharacteristics.builder().directed().build()),
81+
Arguments.of(Direction.UNDIRECTED, GraphCharacteristics.builder().undirected().build())
82+
);
83+
}
84+
85+
@ParameterizedTest
86+
@MethodSource("direction")
87+
void buildFromDirection(Direction direction, GraphCharacteristics expected) {
88+
var actual = GraphCharacteristics.builder().withDirection(direction).build();
89+
assertThat(actual).isEqualTo(expected);
90+
}
91+
}

0 commit comments

Comments
 (0)