aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/logic/src/main/java/tools/refinery/logic/term/cardinalityinterval/NonEmptyCardinalityInterval.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/logic/src/main/java/tools/refinery/logic/term/cardinalityinterval/NonEmptyCardinalityInterval.java')
-rw-r--r--subprojects/logic/src/main/java/tools/refinery/logic/term/cardinalityinterval/NonEmptyCardinalityInterval.java109
1 files changed, 109 insertions, 0 deletions
diff --git a/subprojects/logic/src/main/java/tools/refinery/logic/term/cardinalityinterval/NonEmptyCardinalityInterval.java b/subprojects/logic/src/main/java/tools/refinery/logic/term/cardinalityinterval/NonEmptyCardinalityInterval.java
new file mode 100644
index 00000000..0919fc36
--- /dev/null
+++ b/subprojects/logic/src/main/java/tools/refinery/logic/term/cardinalityinterval/NonEmptyCardinalityInterval.java
@@ -0,0 +1,109 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.logic.term.cardinalityinterval;
7
8import tools.refinery.logic.term.uppercardinality.FiniteUpperCardinality;
9import tools.refinery.logic.term.uppercardinality.UpperCardinality;
10
11import java.util.Objects;
12import java.util.function.BinaryOperator;
13import java.util.function.IntBinaryOperator;
14
15public record NonEmptyCardinalityInterval(int lowerBound, UpperCardinality upperBound) implements CardinalityInterval {
16 public NonEmptyCardinalityInterval {
17 if (lowerBound < 0) {
18 throw new IllegalArgumentException("lowerBound must not be negative");
19 }
20 if (upperBound.compareToInt(lowerBound) < 0) {
21 throw new IllegalArgumentException("lowerBound must not be larger than upperBound");
22 }
23 }
24
25 @Override
26 public boolean isEmpty() {
27 return false;
28 }
29
30 @Override
31 public CardinalityInterval min(CardinalityInterval other) {
32 return lift(other, Math::min, UpperCardinality::min);
33 }
34
35 @Override
36 public CardinalityInterval max(CardinalityInterval other) {
37 return lift(other, Math::max, UpperCardinality::max);
38 }
39
40 @Override
41 public CardinalityInterval add(CardinalityInterval other) {
42 return lift(other, Integer::sum, UpperCardinality::add);
43 }
44
45 @Override
46 public CardinalityInterval multiply(CardinalityInterval other) {
47 return lift(other, (a, b) -> a * b, UpperCardinality::multiply);
48 }
49
50 @Override
51 public CardinalityInterval meet(CardinalityInterval other) {
52 return lift(other, Math::max, UpperCardinality::min);
53 }
54
55 @Override
56 public CardinalityInterval join(CardinalityInterval other) {
57 return lift(other, Math::min, UpperCardinality::max, this);
58 }
59
60 @Override
61 public CardinalityInterval take(int count) {
62 int newLowerBound = Math.max(lowerBound - count, 0);
63 var newUpperBound = upperBound.take(count);
64 if (newUpperBound == null) {
65 return CardinalityIntervals.ERROR;
66 }
67 return CardinalityIntervals.between(newLowerBound, newUpperBound);
68 }
69
70 private CardinalityInterval lift(CardinalityInterval other, IntBinaryOperator lowerOperator,
71 BinaryOperator<UpperCardinality> upperOperator,
72 CardinalityInterval whenEmpty) {
73 if (other instanceof NonEmptyCardinalityInterval nonEmptyOther) {
74 return CardinalityIntervals.between(lowerOperator.applyAsInt(lowerBound, nonEmptyOther.lowerBound),
75 upperOperator.apply(upperBound, nonEmptyOther.upperBound));
76 }
77 if (other instanceof EmptyCardinalityInterval) {
78 return whenEmpty;
79 }
80 throw new IllegalArgumentException("Unknown CardinalityInterval: " + other);
81 }
82
83 private CardinalityInterval lift(CardinalityInterval other, IntBinaryOperator lowerOperator,
84 BinaryOperator<UpperCardinality> upperOperator) {
85 return lift(other, lowerOperator, upperOperator, CardinalityIntervals.ERROR);
86 }
87
88 @Override
89 public String toString() {
90 if (upperBound instanceof FiniteUpperCardinality finiteUpperCardinality &&
91 finiteUpperCardinality.finiteUpperBound() == lowerBound) {
92 return "[%d]".formatted(lowerBound);
93 }
94 return "[%d..%s]".formatted(lowerBound, upperBound);
95 }
96
97 @Override
98 public boolean equals(Object o) {
99 if (this == o) return true;
100 if (o == null || getClass() != o.getClass()) return false;
101 NonEmptyCardinalityInterval that = (NonEmptyCardinalityInterval) o;
102 return lowerBound == that.lowerBound && Objects.equals(upperBound, that.upperBound);
103 }
104
105 @Override
106 public int hashCode() {
107 return lowerBound * 31 + upperBound.hashCode();
108 }
109}