diff options
Diffstat (limited to 'searchlib')
33 files changed, 257 insertions, 271 deletions
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/ExpressionFunction.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/ExpressionFunction.java index 093e65b2e4d..840eacd9dd9 100755..100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/ExpressionFunction.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/ExpressionFunction.java @@ -15,7 +15,6 @@ import static com.yahoo.searchlib.rankingexpression.Reference.wrapInRankingExpre import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; -import java.util.Collections; import java.util.Deque; import java.util.HashMap; import java.util.List; @@ -50,7 +49,7 @@ public class ExpressionFunction { * @param body the ranking expression that defines this function */ public ExpressionFunction(String name, RankingExpression body) { - this(name, Collections.emptyList(), body); + this(name, List.of(), body); } /** diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/EmbracedNode.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/EmbracedNode.java index 1186541b9c0..c7231ecd800 100755..100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/EmbracedNode.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/EmbracedNode.java @@ -7,7 +7,6 @@ import com.yahoo.searchlib.rankingexpression.evaluation.Value; import com.yahoo.tensor.TensorType; import com.yahoo.tensor.evaluation.TypeContext; -import java.util.Collections; import java.util.Deque; import java.util.List; import java.util.Objects; @@ -36,7 +35,7 @@ public final class EmbracedNode extends CompositeNode { @Override public List<ExpressionNode> children() { - return Collections.singletonList(value); + return List.of(value); } @Override diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/FunctionNode.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/FunctionNode.java index e7db8848be5..e93edb71ac6 100755..100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/FunctionNode.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/FunctionNode.java @@ -11,7 +11,6 @@ import com.yahoo.tensor.evaluation.TypeContext; import com.yahoo.tensor.functions.Join; import java.util.ArrayList; -import java.util.Collections; import java.util.Deque; import java.util.List; import java.util.Objects; @@ -34,7 +33,7 @@ public final class FunctionNode extends CompositeNode { public FunctionNode(Function function, ExpressionNode argument) { if (function.arity() != 1) throw new IllegalArgumentException(function + " is not unary"); this.function = function; - this.arguments = new Arguments(Collections.singletonList(argument)); + this.arguments = new Arguments(List.of(argument)); } /** Creates a binary function node */ diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/FunctionReferenceContext.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/FunctionReferenceContext.java index a2cf662a255..be0a532128f 100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/FunctionReferenceContext.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/FunctionReferenceContext.java @@ -4,8 +4,8 @@ package com.yahoo.searchlib.rankingexpression.rule; import com.yahoo.searchlib.rankingexpression.ExpressionFunction; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -23,12 +23,12 @@ public class FunctionReferenceContext { /** Create a context for a single serialization task */ public FunctionReferenceContext() { - this(Collections.emptyList()); + this(List.of()); } /** Create a context for a single serialization task */ public FunctionReferenceContext(Collection<ExpressionFunction> functions) { - this(toMap(functions), Collections.emptyMap()); + this(toMap(functions), Map.of()); } public FunctionReferenceContext(Collection<ExpressionFunction> functions, Map<String, String> bindings) { diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/GeneratorLambdaFunctionNode.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/GeneratorLambdaFunctionNode.java index bef19a656f8..49311b1553b 100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/GeneratorLambdaFunctionNode.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/GeneratorLambdaFunctionNode.java @@ -8,7 +8,6 @@ import com.yahoo.searchlib.rankingexpression.evaluation.Value; import com.yahoo.tensor.TensorType; import com.yahoo.tensor.evaluation.TypeContext; -import java.util.Collections; import java.util.Deque; import java.util.List; import java.util.Objects; @@ -39,7 +38,7 @@ public class GeneratorLambdaFunctionNode extends CompositeNode { @Override public List<ExpressionNode> children() { - return Collections.singletonList(generator); + return List.of(generator); } @Override diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/LambdaFunctionNode.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/LambdaFunctionNode.java index 0f1331515cc..b84bb655140 100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/LambdaFunctionNode.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/LambdaFunctionNode.java @@ -9,7 +9,6 @@ import com.yahoo.tensor.TensorType; import com.yahoo.tensor.evaluation.TypeContext; import com.yahoo.tensor.functions.Generate; -import java.util.Collections; import java.util.Deque; import java.util.HashSet; import java.util.List; @@ -50,7 +49,7 @@ public class LambdaFunctionNode extends CompositeNode { @Override public List<ExpressionNode> children() { - return Collections.singletonList(functionExpression); + return List.of(functionExpression); } @Override diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/NotNode.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/NotNode.java index ba8fb10a1cd..dcf1f857832 100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/NotNode.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/NotNode.java @@ -7,7 +7,6 @@ import com.yahoo.searchlib.rankingexpression.evaluation.Value; import com.yahoo.tensor.TensorType; import com.yahoo.tensor.evaluation.TypeContext; -import java.util.Collections; import java.util.Deque; import java.util.List; import java.util.Objects; @@ -31,7 +30,7 @@ public class NotNode extends BooleanNode { @Override public List<ExpressionNode> children() { - return Collections.singletonList(value); + return List.of(value); } @Override diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SerializationContext.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SerializationContext.java index d1cb77fb1b4..271e367c1f4 100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SerializationContext.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SerializationContext.java @@ -9,9 +9,9 @@ import com.yahoo.tensor.evaluation.TypeContext; import static com.yahoo.searchlib.rankingexpression.Reference.wrapInRankingExpression; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Optional; @@ -29,7 +29,7 @@ public class SerializationContext extends FunctionReferenceContext { /** Create a context for a single serialization task */ public SerializationContext() { - this(Collections.emptyList(), Collections.emptyMap(), Optional.empty(), new LinkedHashMap<>()); + this(List.of(), Map.of(), Optional.empty(), new LinkedHashMap<>()); } /** @@ -40,7 +40,7 @@ public class SerializationContext extends FunctionReferenceContext { */ public SerializationContext(Collection<ExpressionFunction> functions, Optional<TypeContext<Reference>> typeContext) { - this(functions, Collections.emptyMap(), typeContext, new LinkedHashMap<>()); + this(functions, Map.of(), typeContext, new LinkedHashMap<>()); } /** diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/TensorFunctionNode.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/TensorFunctionNode.java index b3f2f265900..202dbebc311 100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/TensorFunctionNode.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/TensorFunctionNode.java @@ -19,7 +19,6 @@ import com.yahoo.tensor.functions.TensorFunction; import com.yahoo.tensor.functions.ToStringContext; import java.util.ArrayList; -import java.util.Collections; import java.util.Deque; import java.util.LinkedHashMap; import java.util.List; @@ -238,7 +237,7 @@ public class TensorFunctionNode extends CompositeNode { .map(ExpressionTensorFunction::new) .collect(Collectors.toList()); else - return Collections.emptyList(); + return List.of(); } @Override diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/UnpackBitsNode.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/UnpackBitsNode.java index 81ad09dd880..0a0f48df823 100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/UnpackBitsNode.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/UnpackBitsNode.java @@ -11,7 +11,6 @@ import com.yahoo.tensor.TensorAddress; import com.yahoo.tensor.TensorType; import com.yahoo.tensor.evaluation.TypeContext; -import java.util.Collections; import java.util.Deque; import java.util.List; import java.util.Objects; @@ -53,7 +52,7 @@ public class UnpackBitsNode extends CompositeNode { @Override public List<ExpressionNode> children() { - return Collections.singletonList(input); + return List.of(input); } private static record Meta(TensorType outputType, TensorType outputDenseType, String unpackDimension) {} diff --git a/searchlib/src/main/javacc/RankingExpressionParser.jj b/searchlib/src/main/javacc/RankingExpressionParser.jj index 97aa42f79c9..51f433bf67d 100755..100644 --- a/searchlib/src/main/javacc/RankingExpressionParser.jj +++ b/searchlib/src/main/javacc/RankingExpressionParser.jj @@ -24,7 +24,6 @@ import com.yahoo.searchlib.rankingexpression.evaluation.StringValue; import com.yahoo.searchlib.rankingexpression.evaluation.TensorValue; import com.yahoo.tensor.*; import com.yahoo.tensor.functions.*; -import java.util.Collections; import java.util.LinkedHashMap; import java.util.Arrays; import java.util.ArrayList; @@ -893,7 +892,7 @@ List<String> bracedIdentifierList() : String element; } { - ( element = identifier() { return Collections.singletonList(element); } ) + ( element = identifier() { return List.of(element); } ) | ( <LBRACE> list = identifierList() <RBRACE> { return list; } ) } diff --git a/searchlib/src/test/java/com/yahoo/searchlib/aggregation/GroupTestCase.java b/searchlib/src/test/java/com/yahoo/searchlib/aggregation/GroupTestCase.java index e306d27b6ee..60309db9787 100644 --- a/searchlib/src/test/java/com/yahoo/searchlib/aggregation/GroupTestCase.java +++ b/searchlib/src/test/java/com/yahoo/searchlib/aggregation/GroupTestCase.java @@ -10,7 +10,6 @@ import com.yahoo.vespa.objects.BufferSerializer; import com.yahoo.vespa.objects.Identifiable; import org.junit.Test; -import java.util.Arrays; import java.util.List; import static org.junit.Assert.assertEquals; @@ -56,7 +55,7 @@ public class GroupTestCase { group.addOrderBy(bar, false); assertEquals(2, group.getOrderByExpressions().size()); assertSame(bar, group.getOrderByExpressions().get(1)); - assertEquals(Arrays.asList(1, -2), group.getOrderByIndexes()); + assertEquals(List.of(1, -2), group.getOrderByIndexes()); } @Test diff --git a/searchlib/src/test/java/com/yahoo/searchlib/aggregation/GroupingTestCase.java b/searchlib/src/test/java/com/yahoo/searchlib/aggregation/GroupingTestCase.java index 66b8a07ac95..a0e6fd32ddc 100644 --- a/searchlib/src/test/java/com/yahoo/searchlib/aggregation/GroupingTestCase.java +++ b/searchlib/src/test/java/com/yahoo/searchlib/aggregation/GroupingTestCase.java @@ -1,14 +1,12 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.searchlib.aggregation; -import com.yahoo.searchlib.expression.FloatResultNode; import com.yahoo.searchlib.expression.NullResultNode; import com.yahoo.searchlib.expression.StringBucketResultNode; import com.yahoo.vespa.objects.BufferSerializer; import org.junit.Test; -import java.util.Arrays; -import java.util.Collections; +import java.util.List; import static org.junit.Assert.*; @@ -30,7 +28,7 @@ public class GroupingTestCase { assertEquals(9, grouping.getId()); Grouping other = new Grouping(6); - assertFalse(grouping.equals(other)); + assertNotEquals(grouping, other); other.setId(9); assertEquals(grouping, other); @@ -46,7 +44,7 @@ public class GroupingTestCase { assertTrue(grouping.getAll()); Grouping other = new Grouping(); - assertFalse(grouping.equals(other)); + assertNotEquals(grouping, other); other.setAll(true); assertEquals(grouping, other); @@ -62,7 +60,7 @@ public class GroupingTestCase { assertEquals(69, grouping.getTopN()); Grouping other = new Grouping(); - assertFalse(grouping.equals(other)); + assertNotEquals(grouping, other); other.setTopN(69); assertEquals(grouping, other); @@ -78,7 +76,7 @@ public class GroupingTestCase { assertEquals(69, grouping.getFirstLevel()); Grouping other = new Grouping(); - assertFalse(grouping.equals(other)); + assertNotEquals(grouping, other); other.setFirstLevel(69); assertEquals(grouping, other); @@ -94,7 +92,7 @@ public class GroupingTestCase { assertEquals(69, grouping.getLastLevel()); Grouping other = new Grouping(); - assertFalse(grouping.equals(other)); + assertNotEquals(grouping, other); other.setLastLevel(69); assertEquals(grouping, other); @@ -117,7 +115,7 @@ public class GroupingTestCase { assertEquals(root, grouping.getRoot()); Grouping other = new Grouping(); - assertFalse(grouping.equals(other)); + assertNotEquals(grouping, other); other.setRoot(root); assertEquals(grouping, other); @@ -128,7 +126,7 @@ public class GroupingTestCase { @Test public void requireThatLevelAccessorsWork() { Grouping grouping = new Grouping(); - assertEquals(Collections.emptyList(), grouping.getLevels()); + assertEquals(List.of(), grouping.getLevels()); try { grouping.addLevel(null); fail(); @@ -137,10 +135,10 @@ public class GroupingTestCase { } GroupingLevel level = new GroupingLevel(); grouping.addLevel(level); - assertEquals(Arrays.asList(level), grouping.getLevels()); + assertEquals(List.of(level), grouping.getLevels()); Grouping other = new Grouping(); - assertFalse(grouping.equals(other)); + assertNotEquals(grouping, other); other.addLevel(level); assertEquals(grouping, other); @@ -155,8 +153,8 @@ public class GroupingTestCase { @Test public void requireThatEqualsIsImplemented() { - assertFalse(new Grouping().equals(new Object())); - assertTrue(new Grouping().equals(new Grouping())); + assertNotEquals(new Grouping(), new Object()); + assertEquals(new Grouping(), new Grouping()); } @Test diff --git a/searchlib/src/test/java/com/yahoo/searchlib/aggregation/MergeTestCase.java b/searchlib/src/test/java/com/yahoo/searchlib/aggregation/MergeTestCase.java index 610352ff236..838a4d738ac 100755..100644 --- a/searchlib/src/test/java/com/yahoo/searchlib/aggregation/MergeTestCase.java +++ b/searchlib/src/test/java/com/yahoo/searchlib/aggregation/MergeTestCase.java @@ -13,7 +13,6 @@ import com.yahoo.searchlib.expression.MultiplyFunctionNode; import com.yahoo.searchlib.expression.StringResultNode; import org.junit.Test; -import java.util.Arrays; import java.util.List; import static org.junit.Assert.assertEquals; @@ -725,20 +724,20 @@ public class MergeTestCase { } private static void assertMerge(Grouping request, Group lhs, Group rhs, Group expect) { - assertMerge(Arrays.asList(request.clone().setRoot(lhs.clone()), + assertMerge(List.of(request.clone().setRoot(lhs.clone()), request.clone().setRoot(rhs.clone())), expect); } private static void assertMerge(Grouping request, Group a, Group b, Group c, Group expect) { - assertMerge(Arrays.asList(request.clone().setRoot(a.clone()), + assertMerge(List.of(request.clone().setRoot(a.clone()), request.clone().setRoot(b.clone()), request.clone().setRoot(c.clone())), expect); } private static void assertMerge(Grouping lhs, Grouping rhs, Group expect) { - assertMerge(Arrays.asList(lhs, rhs), expect); + assertMerge(List.of(lhs, rhs), expect); } private static void assertMerge(List<Grouping> groupingList, Group expect) { diff --git a/searchlib/src/test/java/com/yahoo/searchlib/aggregation/hll/NormalSketchTest.java b/searchlib/src/test/java/com/yahoo/searchlib/aggregation/hll/NormalSketchTest.java index d5269611b53..8e54c4598a0 100644 --- a/searchlib/src/test/java/com/yahoo/searchlib/aggregation/hll/NormalSketchTest.java +++ b/searchlib/src/test/java/com/yahoo/searchlib/aggregation/hll/NormalSketchTest.java @@ -4,7 +4,6 @@ package com.yahoo.searchlib.aggregation.hll; import com.yahoo.vespa.objects.BufferSerializer; import org.junit.Test; -import java.util.Arrays; import java.util.List; import static org.junit.Assert.assertEquals; @@ -98,7 +97,7 @@ public class NormalSketchTest { NormalSketch sketch = new NormalSketch(10); // Aggregate multiple values - sketch.aggregate(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); + sketch.aggregate(List.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); for (int i = 0; i < 10; i++) { assertBucketEquals(sketch, i, 23); } diff --git a/searchlib/src/test/java/com/yahoo/searchlib/aggregation/hll/SketchUtils.java b/searchlib/src/test/java/com/yahoo/searchlib/aggregation/hll/SketchUtils.java index 9bec86c928b..5bf5294a828 100644 --- a/searchlib/src/test/java/com/yahoo/searchlib/aggregation/hll/SketchUtils.java +++ b/searchlib/src/test/java/com/yahoo/searchlib/aggregation/hll/SketchUtils.java @@ -1,7 +1,7 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.searchlib.aggregation.hll; -import java.util.Arrays; +import java.util.List; import static org.junit.Assert.assertEquals; @@ -16,13 +16,13 @@ public class SketchUtils { public static SparseSketch createSparseSketch(Integer... values) { SparseSketch sketch = new SparseSketch(); - sketch.aggregate(Arrays.asList(values)); + sketch.aggregate(List.of(values)); return sketch; } public static NormalSketch createNormalSketch(Integer... values) { NormalSketch sketch = new NormalSketch(); - sketch.aggregate(Arrays.asList(values)); + sketch.aggregate(List.of(values)); return sketch; } diff --git a/searchlib/src/test/java/com/yahoo/searchlib/expression/IntegerResultNodeTestCase.java b/searchlib/src/test/java/com/yahoo/searchlib/expression/IntegerResultNodeTestCase.java index c765714a4ab..45d809dcd8a 100644 --- a/searchlib/src/test/java/com/yahoo/searchlib/expression/IntegerResultNodeTestCase.java +++ b/searchlib/src/test/java/com/yahoo/searchlib/expression/IntegerResultNodeTestCase.java @@ -4,7 +4,6 @@ package com.yahoo.searchlib.expression; import org.junit.Test; import java.lang.reflect.InvocationTargetException; -import java.util.Arrays; import java.util.List; import static org.junit.Assert.assertArrayEquals; @@ -18,7 +17,7 @@ import static org.junit.Assert.assertTrue; public class IntegerResultNodeTestCase extends ResultNodeTest { List<NumericResultNode> getResultNodes(long startvalue) { - return Arrays.asList(new Int8ResultNode((byte)startvalue), + return List.of(new Int8ResultNode((byte)startvalue), new Int16ResultNode((short)startvalue), new Int32ResultNode((int)startvalue), new IntegerResultNode(startvalue)); diff --git a/searchlib/src/test/java/com/yahoo/searchlib/expression/ObjectVisitorTestCase.java b/searchlib/src/test/java/com/yahoo/searchlib/expression/ObjectVisitorTestCase.java index 3c224d06cc3..1346577569b 100755..100644 --- a/searchlib/src/test/java/com/yahoo/searchlib/expression/ObjectVisitorTestCase.java +++ b/searchlib/src/test/java/com/yahoo/searchlib/expression/ObjectVisitorTestCase.java @@ -4,6 +4,7 @@ package com.yahoo.searchlib.expression; import com.yahoo.vespa.objects.ObjectDumper; import org.junit.Test; + import java.util.Arrays; import static org.junit.Assert.assertEquals; @@ -18,38 +19,46 @@ public class ObjectVisitorTestCase { assertDump("test: <NULL>\n", null); assertDump("test: 1\n", 1); assertDump("test: 'foo'\n", "foo"); - assertDump("test: List {\n" + - " [0]: 'foo'\n" + - " [1]: 69\n" + - " [2]: <NULL>\n" + - "}\n", + assertDump(""" + test: List { + [0]: 'foo' + [1]: 69 + [2]: <NULL> + } + """, Arrays.asList("foo", 69, null)); - assertDump("test: String[] {\n" + - " [0]: 'foo'\n" + - " [1]: 'bar'\n" + - " [2]: 'baz'\n" + - "}\n", + assertDump(""" + test: String[] { + [0]: 'foo' + [1]: 'bar' + [2]: 'baz' + } + """, new String[] { "foo", "bar", "baz" }); - assertDump("test: IntegerResultNode {\n" + - " classId: 16491\n" + - " value: 5\n" + - "}\n", + assertDump(""" + test: IntegerResultNode { + classId: 16491 + value: 5 + } + """, new IntegerResultNode(5)); - assertDump("test: FixedWidthBucketFunctionNode {\n" + - " classId: 16461\n" + - " result: <NULL>\n" + - " args: List {\n" + - " [0]: AttributeNode {\n" + - " classId: 16439\n" + - " result: <NULL>\n" + - " attribute: 'foo'\n" + - " }\n" + - " }\n" + - " width: IntegerResultNode {\n" + - " classId: 16491\n" + - " value: 5\n" + - " }\n" + - "}\n", + assertDump(""" + test: FixedWidthBucketFunctionNode { + classId: 16461 + result: <NULL> + args: List { + [0]: AttributeNode { + classId: 16439 + result: <NULL> + attribute: 'foo' + } + } + width: IntegerResultNode { + classId: 16491 + value: 5 + } + } + """, new FixedWidthBucketFunctionNode(new IntegerResultNode(5), new AttributeNode("foo"))); } diff --git a/searchlib/src/test/java/com/yahoo/searchlib/expression/TimeStampFunctionTestCase.java b/searchlib/src/test/java/com/yahoo/searchlib/expression/TimeStampFunctionTestCase.java index 69cea09df81..188603749e2 100644 --- a/searchlib/src/test/java/com/yahoo/searchlib/expression/TimeStampFunctionTestCase.java +++ b/searchlib/src/test/java/com/yahoo/searchlib/expression/TimeStampFunctionTestCase.java @@ -3,7 +3,7 @@ package com.yahoo.searchlib.expression; import org.junit.Test; -import java.util.Arrays; +import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; @@ -17,7 +17,7 @@ public class TimeStampFunctionTestCase { public void requireThatAccessorsWork() { ExpressionNode arg = new AttributeNode("foo"); for (TimeStampFunctionNode.TimePart part : TimeStampFunctionNode.TimePart.values()) { - for (Boolean gmt : Arrays.asList(true, false)) { + for (Boolean gmt : List.of(true, false)) { TimeStampFunctionNode node = new TimeStampFunctionNode(arg, part, gmt); assertSame(arg, node.getArg()); assertEquals(part, node.getTimePart()); diff --git a/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/FeatureListTestCase.java b/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/FeatureListTestCase.java index 8de36ee1ec1..0af105885ec 100755..100644 --- a/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/FeatureListTestCase.java +++ b/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/FeatureListTestCase.java @@ -8,7 +8,6 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.Reader; import java.io.StringReader; -import java.util.Arrays; import java.util.List; import static org.junit.Assert.assertEquals; @@ -22,37 +21,37 @@ public class FeatureListTestCase { @Test public void requireThatFeatureListFromStringWorks() throws ParseException { assertFromString("attribute(foo).out", - Arrays.asList("attribute(foo).out")); + List.of("attribute(foo).out")); assertFromString("attribute(foo).out attribute ( bar ) . out", - Arrays.asList("attribute(foo).out", "attribute(bar).out")); + List.of("attribute(foo).out", "attribute(bar).out")); assertFromString("foo\n bar\n \t \t \n baz \n", - Arrays.asList("foo", "bar", "baz")); + List.of("foo", "bar", "baz")); assertFromString("attribute attribute(foo) attribute(foo).out attribute(bar).out.out", - Arrays.asList("attribute", "attribute(foo)", "attribute(foo).out", "attribute(bar).out.out")); + List.of("attribute", "attribute(foo)", "attribute(foo).out", "attribute(bar).out.out")); } @Test public void requireThatFeatureListFromReaderWorks() throws ParseException { assertFromReader(new StringReader("attribute(foo).out"), - Arrays.asList("attribute(foo).out")); + List.of("attribute(foo).out")); assertFromReader(new StringReader("attribute(foo).out attribute ( bar ) . out"), - Arrays.asList("attribute(foo).out", "attribute(bar).out")); + List.of("attribute(foo).out", "attribute(bar).out")); assertFromReader(new StringReader("foo\n bar\n \t \t \n baz \n"), - Arrays.asList("foo", "bar", "baz")); + List.of("foo", "bar", "baz")); assertFromReader(new StringReader("attribute attribute(foo) attribute(foo).out attribute(bar).out.out"), - Arrays.asList("attribute", "attribute(foo)", "attribute(foo).out", "attribute(bar).out.out")); + List.of("attribute", "attribute(foo)", "attribute(foo).out", "attribute(bar).out.out")); } @Test public void requireThatFeatureListFromFileWorks() throws ParseException, FileNotFoundException { assertFromFile(new File("src/test/files/features01.expression"), - Arrays.asList("attribute(foo).out")); + List.of("attribute(foo).out")); assertFromFile(new File("src/test/files/features02.expression"), - Arrays.asList("attribute(foo).out", "attribute(bar).out")); + List.of("attribute(foo).out", "attribute(bar).out")); assertFromFile(new File("src/test/files/features03.expression"), - Arrays.asList("foo", "bar", "baz")); + List.of("foo", "bar", "baz")); assertFromFile(new File("src/test/files/features04.expression"), - Arrays.asList("attribute", "attribute(foo)", "attribute(foo).out", "attribute(bar).out.out")); + List.of("attribute", "attribute(foo)", "attribute(foo).out", "attribute(bar).out.out")); } public void assertFromString(String input, List<String> expected) throws ParseException { diff --git a/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/RankingExpressionTestCase.java b/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/RankingExpressionTestCase.java index 8d60f893c7c..13714af8324 100755..100644 --- a/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/RankingExpressionTestCase.java +++ b/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/RankingExpressionTestCase.java @@ -23,7 +23,6 @@ import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Optional; @@ -121,28 +120,28 @@ public class RankingExpressionTestCase { @Test public void testSerialization() throws ParseException { List<ExpressionFunction> functions = new ArrayList<>(); - functions.add(new ExpressionFunction("foo", Arrays.asList("arg1", "arg2"), new RankingExpression("min(arg1, pow(arg2, 2))"))); - functions.add(new ExpressionFunction("bar", Arrays.asList("arg1", "arg2"), new RankingExpression("arg1 * arg1 + 2 * arg1 * arg2 + arg2 * arg2"))); - functions.add(new ExpressionFunction("baz", Arrays.asList("arg1", "arg2"), new RankingExpression("foo(1, 2) / bar(arg1, arg2)"))); + functions.add(new ExpressionFunction("foo", List.of("arg1", "arg2"), new RankingExpression("min(arg1, pow(arg2, 2))"))); + functions.add(new ExpressionFunction("bar", List.of("arg1", "arg2"), new RankingExpression("arg1 * arg1 + 2 * arg1 * arg2 + arg2 * arg2"))); + functions.add(new ExpressionFunction("baz", List.of("arg1", "arg2"), new RankingExpression("foo(1, 2) / bar(arg1, arg2)"))); functions.add(new ExpressionFunction("cox", null, new RankingExpression("10 + 08 * 1977"))); - assertSerialization(Arrays.asList( + assertSerialization(List.of( "rankingExpression(foo@e2dc17a89864aed0.12232eb692c6c502) + rankingExpression(foo@af74e3fd9070bd18.a368ed0a5ba3a5d0) * rankingExpression(foo@dbab346efdad5362.e5c39e42ebd91c30)", "min(5,pow(rankingExpression(foo@d1d1417259cdc651.573bbcd4be18f379),2))", "min(6,pow(7,2))", "min(1,pow(2,2))", "min(3,pow(4,2))", "min(rankingExpression(foo@84951be88255b0ec.d0303e061b36fab8),pow(8,2))"), "foo(1,2) + foo(3,4) * foo(5, foo(foo(6, 7), 8))", functions); - assertSerialization(Arrays.asList( + assertSerialization(List.of( "rankingExpression(foo@e2dc17a89864aed0.12232eb692c6c502) + rankingExpression(bar@af74e3fd9070bd18.a368ed0a5ba3a5d0)", "min(1,pow(2,2))", "3 * 3 + 2 * 3 * 4 + 4 * 4"), "foo(1, 2) + bar(3, 4)", functions); - assertSerialization(Arrays.asList( + assertSerialization(List.of( "rankingExpression(baz@e2dc17a89864aed0.12232eb692c6c502)", "min(1,pow(2,2))", "rankingExpression(foo@e2dc17a89864aed0.12232eb692c6c502) / rankingExpression(bar@e2dc17a89864aed0.12232eb692c6c502)", "1 * 1 + 2 * 1 * 2 + 2 * 2"), "baz(1, 2)", functions); - assertSerialization(Arrays.asList( + assertSerialization(List.of( "rankingExpression(cox)", "10 + 8 * 1977"), "cox", functions ); @@ -237,8 +236,8 @@ public class RankingExpressionTestCase { String expRhs = "(rankingExpression(log10tweetage) * rankingExpression(log10tweetage) * " + "rankingExpression(log10tweetage)) + 5.0 * attribute(ythl)"; - assertSerialization(Arrays.asList(expLhs + " + " + expRhs, "69"), lhs + " + " + rhs, functions); - assertSerialization(Arrays.asList(expLhs + " - " + expRhs, "69"), lhs + " - " + rhs, functions); + assertSerialization(List.of(expLhs + " + " + expRhs, "69"), lhs + " + " + rhs, functions); + assertSerialization(List.of(expLhs + " - " + expRhs, "69"), lhs + " - " + rhs, functions); } @Test diff --git a/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/rule/ArgumentsTestCase.java b/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/rule/ArgumentsTestCase.java index df91c78c1b4..af6e4f1b9a9 100644 --- a/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/rule/ArgumentsTestCase.java +++ b/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/rule/ArgumentsTestCase.java @@ -3,8 +3,8 @@ package com.yahoo.searchlib.rankingexpression.rule; import org.junit.Test; -import java.util.Arrays; import java.util.Collections; +import java.util.List; import static org.junit.Assert.*; @@ -23,7 +23,7 @@ public class ArgumentsTestCase { var foo = new ReferenceNode("foo"); var bar = new ReferenceNode("bar"); - args = new Arguments(Arrays.asList(foo, bar)); + args = new Arguments(List.of(foo, bar)); assertEquals(2, args.expressions().size()); assertSame(foo, args.expressions().get(0)); assertSame(bar, args.expressions().get(1)); @@ -31,12 +31,12 @@ public class ArgumentsTestCase { @Test public void requireThatHashCodeAndEqualsWork() { - Arguments arg1 = new Arguments(Arrays.asList(new ReferenceNode("foo"), new ReferenceNode("bar"))); - Arguments arg2 = new Arguments(Arrays.asList(new ReferenceNode("foo"), new ReferenceNode("bar"))); - Arguments arg3 = new Arguments(Arrays.asList(new ReferenceNode("foo"))); + Arguments arg1 = new Arguments(List.of(new ReferenceNode("foo"), new ReferenceNode("bar"))); + Arguments arg2 = new Arguments(List.of(new ReferenceNode("foo"), new ReferenceNode("bar"))); + Arguments arg3 = new Arguments(List.of(new ReferenceNode("foo"))); assertEquals(arg1.hashCode(), arg2.hashCode()); - assertTrue(arg1.equals(arg2)); - assertFalse(arg2.equals(arg3)); + assertEquals(arg1, arg2); + assertNotEquals(arg2, arg3); } } diff --git a/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/rule/ReferenceNodeTestCase.java b/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/rule/ReferenceNodeTestCase.java index 7d0e0d6da84..10a37ff28df 100644 --- a/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/rule/ReferenceNodeTestCase.java +++ b/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/rule/ReferenceNodeTestCase.java @@ -3,7 +3,6 @@ package com.yahoo.searchlib.rankingexpression.rule; import org.junit.Test; -import java.util.Arrays; import java.util.List; import static org.junit.Assert.assertEquals; @@ -15,7 +14,7 @@ public class ReferenceNodeTestCase { @Test public void requireThatAccessorsWork() { - ReferenceNode node = new ReferenceNode("foo", Arrays.asList(new ReferenceNode("bar"), new ReferenceNode("baz")), "cox"); + ReferenceNode node = new ReferenceNode("foo", List.of(new ReferenceNode("bar"), new ReferenceNode("baz")), "cox"); assertEquals("foo", node.getName()); List<ExpressionNode> args = node.getArguments().expressions(); assertEquals(2, args.size()); @@ -23,10 +22,10 @@ public class ReferenceNodeTestCase { assertEquals(new ReferenceNode("baz"), args.get(1)); assertEquals("cox", node.getOutput()); - node = node.setArguments(Arrays.<ExpressionNode>asList(new ReferenceNode("bar@"))); + node = node.setArguments(List.of(new ReferenceNode("bar@"))); assertEquals(new ReferenceNode("bar@"), node.getArguments().expressions().get(0)); - node = node.setArguments(Arrays.<ExpressionNode>asList(new ReferenceNode("baz$"))); + node = node.setArguments(List.of(new ReferenceNode("baz$"))); assertEquals(new ReferenceNode("baz$"), node.getArguments().expressions().get(0)); node = node.setOutput("cox'"); diff --git a/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/transform/SimplifierTestCase.java b/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/transform/SimplifierTestCase.java index 0f367bb5425..7736b0e9ac7 100644 --- a/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/transform/SimplifierTestCase.java +++ b/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/transform/SimplifierTestCase.java @@ -12,7 +12,7 @@ import com.yahoo.searchlib.rankingexpression.rule.ConstantNode; import com.yahoo.searchlib.rankingexpression.rule.NegativeNode; import org.junit.Test; -import java.util.Collections; +import java.util.Map; import static org.junit.Assert.*; @@ -24,7 +24,7 @@ public class SimplifierTestCase { @Test public void testSimplify() throws ParseException { Simplifier s = new Simplifier(); - TransformContext c = new TransformContext(Collections.emptyMap(), new MapTypeContext()); + TransformContext c = new TransformContext(Map.of(), new MapTypeContext()); assertEquals("a + b", s.transform(new RankingExpression("a + b"), c).toString()); assertEquals("6.5", s.transform(new RankingExpression("1.0 + 2.0 + 3.5"), c).toString()); assertEquals("6.5", s.transform(new RankingExpression("1.0 + ( 2.0 + 3.5 )"), c).toString()); @@ -48,7 +48,7 @@ public class SimplifierTestCase { @Test public void testNaNExpression() throws ParseException { Simplifier s = new Simplifier(); - TransformContext c = new TransformContext(Collections.emptyMap(), new MapTypeContext()); + TransformContext c = new TransformContext(Map.of(), new MapTypeContext()); assertEquals("0 / 0", s.transform(new RankingExpression("0/0"), c).toString()); assertEquals("1 + 0.0 / 0.0", s.transform(new RankingExpression("1 + (1-1)/(2-2)"), c).toString()); } @@ -56,7 +56,7 @@ public class SimplifierTestCase { @Test public void testSimplifyComplexExpression() throws ParseException { RankingExpression initial = new RankingExpression("sqrt(if (if (INFERRED * 0.9 < INFERRED, GMP, (1 + 1.1) * INFERRED) < INFERRED * INFERRED - INFERRED, if (GMP < 85.80799542793133 * GMP, INFERRED, if (GMP < GMP, tanh(INFERRED), log(76.89956221113943))), tanh(tanh(INFERRED))) * sqrt(sqrt(GMP + INFERRED)) * GMP ) + 13.5 * (1 - GMP) * pow(GMP * 0.1, 2 + 1.1 * 0)"); - TransformContext c = new TransformContext(Collections.emptyMap(), new MapTypeContext()); + TransformContext c = new TransformContext(Map.of(), new MapTypeContext()); RankingExpression simplified = new Simplifier().transform(initial, c); Context context = new MapContext(); @@ -81,7 +81,7 @@ public class SimplifierTestCase { @Test public void testParenthesisPreservation() throws ParseException { Simplifier s = new Simplifier(); - TransformContext c = new TransformContext(Collections.emptyMap(), new MapTypeContext()); + TransformContext c = new TransformContext(Map.of(), new MapTypeContext()); CompositeNode transformed = (CompositeNode)s.transform(new RankingExpression("a + (b + c) / 100000000.0"), c).getRoot(); assertEquals("a + (b + c) / 1.0E8", transformed.toString()); } @@ -89,7 +89,7 @@ public class SimplifierTestCase { @Test public void testOptimizingNegativeConstants() throws ParseException { Simplifier s = new Simplifier(); - TransformContext c = new TransformContext(Collections.emptyMap(), new MapTypeContext()); + TransformContext c = new TransformContext(Map.of(), new MapTypeContext()); assertEquals("-3", s.transform(new RankingExpression("-3"), c).toString()); assertEquals("-9.0", s.transform(new RankingExpression("-3 + -6"), c).toString()); assertEquals("-a", s.transform(new RankingExpression("-a"), c).toString()); diff --git a/searchlib/src/tests/queryeval/flow/queryeval_flow_test.cpp b/searchlib/src/tests/queryeval/flow/queryeval_flow_test.cpp index 181c591ab20..5eb3a2ebf47 100644 --- a/searchlib/src/tests/queryeval/flow/queryeval_flow_test.cpp +++ b/searchlib/src/tests/queryeval/flow/queryeval_flow_test.cpp @@ -7,6 +7,7 @@ constexpr size_t loop_cnt = 64; constexpr size_t max_work = 1; // 500'000'000; +constexpr bool dump_unexpected = false; constexpr bool verbose = false; using namespace search::queryeval; @@ -40,7 +41,7 @@ double dual_ordered_cost_of(const std::vector<FlowStats> &data, InFlow in_flow, any_flow.update_cost(total_cost, child_cost); any_flow.add(item.estimate); } - EXPECT_EQ(total_cost, result); + EXPECT_DOUBLE_EQ(total_cost, result); return result; } @@ -174,7 +175,7 @@ void verify_flow(auto flow, const std::vector<double> &est_list, const std::vect AnyFlow any_flow = AnyFlow::create<decltype(flow)>(InFlow(flow.strict(), flow.flow())); ASSERT_EQ(est_list.size() + 1, expect.size()); for (size_t i = 0; i < est_list.size(); ++i) { - EXPECT_EQ(any_flow.flow(), flow.flow()); + EXPECT_DOUBLE_EQ(any_flow.flow(), flow.flow()); EXPECT_EQ(any_flow.strict(), flow.strict()); EXPECT_DOUBLE_EQ(flow.flow(), expect[i].flow); EXPECT_EQ(flow.strict(), expect[i].strict); @@ -182,7 +183,7 @@ void verify_flow(auto flow, const std::vector<double> &est_list, const std::vect any_flow.add(est_list[i]); flow.add(est_list[i]); } - EXPECT_EQ(any_flow.flow(), flow.flow()); + EXPECT_DOUBLE_EQ(any_flow.flow(), flow.flow()); EXPECT_EQ(any_flow.strict(), flow.strict()); EXPECT_DOUBLE_EQ(flow.flow(), expect.back().flow); EXPECT_EQ(flow.strict(), expect.back().strict); @@ -356,10 +357,10 @@ TEST(FlowTest, optimal_and_flow) { double min_cost = AndFlow::cost_of(data, strict); double max_cost = 0.0; AndFlow::sort(data, strict); - EXPECT_EQ(ordered_cost_of<AndFlow>(data, strict, false), min_cost); + EXPECT_DOUBLE_EQ(ordered_cost_of<AndFlow>(data, strict, false), min_cost); auto check = [&](const std::vector<FlowStats> &my_data) noexcept { double my_cost = ordered_cost_of<AndFlow>(my_data, strict, false); - EXPECT_LE(min_cost, my_cost); + EXPECT_LE(min_cost, my_cost + 1e-9); max_cost = std::max(max_cost, my_cost); }; each_perm(data, check); @@ -379,7 +380,7 @@ TEST(FlowTest, optimal_or_flow) { double min_cost = OrFlow::cost_of(data, strict); double max_cost = 0.0; OrFlow::sort(data, strict); - EXPECT_EQ(ordered_cost_of<OrFlow>(data, strict, false), min_cost); + EXPECT_DOUBLE_EQ(ordered_cost_of<OrFlow>(data, strict, false), min_cost); auto check = [&](const std::vector<FlowStats> &my_data) noexcept { double my_cost = ordered_cost_of<OrFlow>(my_data, strict, false); EXPECT_LE(min_cost, my_cost + 1e-9); @@ -451,7 +452,7 @@ void test_strict_AND_sort_strategy(auto my_sort) { flow.add(item.estimate); total_cost += child_cost; } - EXPECT_EQ(total_cost, ordered_cost_of<AndFlow>(list, true, true)); + EXPECT_DOUBLE_EQ(total_cost, ordered_cost_of<AndFlow>(list, true, true)); fprintf(stderr, " total cost: %10f\n", total_cost); }; auto verify_order = [&](const std::vector<FlowStats> &list){ @@ -515,10 +516,7 @@ void test_strict_AND_sort_strategy(auto my_sort) { }; each_perm(data, check); double rel_err = 0.0; - double cost_range = (max_cost - min_cost); - if (cost_range > 1e-9) { - rel_err = (est_cost - min_cost) / cost_range; - } + rel_err = (est_cost - min_cost) / min_cost; if (rel_err > max_rel_err) { max_rel_err = rel_err; my_worst_order = my_order; @@ -526,7 +524,7 @@ void test_strict_AND_sort_strategy(auto my_sort) { } sum_rel_err += rel_err; errs.push_back(rel_err); - if (verbose && !verify_order(best_order)) { + if (dump_unexpected && !verify_order(best_order)) { fprintf(stderr, " BEST ORDER IS UNEXPECTED:\n"); dump_flow(best_order, best_order); fprintf(stderr, " UNEXPECTED case, my_order:\n"); @@ -551,60 +549,12 @@ TEST(FlowTest, strict_and_with_allow_force_strict_basic_order) { test_strict_AND_sort_strategy(my_sort); } -TEST(FlowTest, strict_and_with_allow_force_strict_incremental_strict_selection) { - auto my_sort = [](auto &data) { - AndFlow::sort(data, true); - for (size_t next = 1; (next + 1) < data.size(); ++next) { - auto [idx, score] = flow::select_forced_strict_and_child(flow::DirectAdapter(), data, next); - if (score >= 0.0) { - break; - } - auto pos = data.begin() + idx; - std::rotate(data.begin() + next, pos, pos + 1); - } - }; - test_strict_AND_sort_strategy(my_sort); -} - -TEST(FlowTest, strict_and_with_allow_force_strict_incremental_strict_selection_with_strict_re_sorting) { - auto my_sort = [](auto &data) { - AndFlow::sort(data, true); - size_t strict_cnt = 1; - for (; strict_cnt < data.size(); ++strict_cnt) { - auto [idx, score] = flow::select_forced_strict_and_child(flow::DirectAdapter(), data, strict_cnt); - if (score >= 0.0) { - break; - } - auto pos = data.begin() + idx; - std::rotate(data.begin() + strict_cnt, pos, pos + 1); - } - std::sort(data.begin(), data.begin() + strict_cnt, - [](const auto &a, const auto &b){ return (a.estimate < b.estimate); }); - }; - test_strict_AND_sort_strategy(my_sort); -} - -TEST(FlowTest, strict_and_with_allow_force_strict_incremental_strict_selection_with_order) { - auto my_sort = [](auto &data) { - AndFlow::sort(data, true); - for (size_t next = 1; next < data.size(); ++next) { - auto [idx, target, score] = flow::select_forced_strict_and_child_with_order(flow::DirectAdapter(), data, next); - if (score >= 0.0) { - break; - } - auto pos = data.begin() + idx; - std::rotate(data.begin() + target, pos, pos + 1); - } - }; - test_strict_AND_sort_strategy(my_sort); -} - -TEST(FlowTest, strict_and_with_allow_force_strict_incremental_strict_selection_with_destructive_order) { +TEST(FlowTest, strict_and_with_allow_force_strict_incremental_strict_selection_destructive_order_max_3_extra_strict) { auto my_sort = [](auto &data) { AndFlow::sort(data, true); - for (size_t next = 1; next < data.size(); ++next) { - auto [idx, target, score] = flow::select_forced_strict_and_child_with_destructive_order(flow::DirectAdapter(), data, next); - if (score >= 0.0) { + for (size_t next = 1; next <= 3 && next < data.size(); ++next) { + auto [idx, target, diff] = flow::select_forced_strict_and_child(flow::DirectAdapter(), data, next); + if (diff >= 0.0) { break; } auto pos = data.begin() + idx; diff --git a/searchlib/src/tests/queryeval/iterator_benchmark/attribute_ctx_builder.cpp b/searchlib/src/tests/queryeval/iterator_benchmark/attribute_ctx_builder.cpp index 6a2b306522d..5a0bda49b98 100644 --- a/searchlib/src/tests/queryeval/iterator_benchmark/attribute_ctx_builder.cpp +++ b/searchlib/src/tests/queryeval/iterator_benchmark/attribute_ctx_builder.cpp @@ -18,30 +18,71 @@ namespace { template <typename AttributeType, bool is_string, bool is_multivalue> void +update_attribute(AttributeType& attr, uint32_t docid, uint32_t value) +{ + if constexpr (is_string) { + if constexpr (is_multivalue) { + attr.append(docid, std::to_string(value), random_int(1, 100)); + } else { + attr.update(docid, std::to_string(value)); + } + } else { + if constexpr (is_multivalue) { + attr.append(docid, value, random_int(1, 100)); + } else { + attr.update(docid, value); + } + } +} + +template <typename AttributeType, bool is_string, bool is_multivalue> +void populate_attribute(AttributeType& attr, uint32_t docid_limit, const HitSpecs& hit_specs) { for (auto spec : hit_specs) { auto docids = random_docids(docid_limit, spec.num_hits); docids->foreach_truebit([&](uint32_t docid) { - if constexpr (is_string) { - if constexpr (is_multivalue) { - attr.append(docid, std::to_string(spec.term_value), random_int(1, 100)); - } else { - attr.update(docid, std::to_string(spec.term_value)); - } - } else { - if constexpr (is_multivalue) { - attr.append(docid, spec.term_value, random_int(1, 100)); - } else { - attr.update(docid, spec.term_value); - } - } + update_attribute<AttributeType, is_string, is_multivalue>(attr, docid, spec.term_value); }); } } +template <typename AttributeType, bool is_string, bool is_multivalue> +void +populate_attribute(AttributeType& attr, const std::vector<uint32_t>& values) +{ + for (uint32_t docid = 1; docid < values.size(); ++docid) { + uint32_t value = values[docid]; + if (value == 0) { + continue; + } + update_attribute<AttributeType, is_string, is_multivalue>(attr, docid, value); + } +} + +template <typename AttributeType, bool is_string, bool is_multivalue> +void +populate_attribute(AttributeType& attr, uint32_t docid_limit, const HitSpecs& hit_specs, bool disjunct_terms) +{ + if (disjunct_terms) { + // Ensure that each term in HitSpecs is matched by a disjunct (random) subset of docids. + std::vector<uint32_t> values(docid_limit, 0); + uint32_t docid = 1; + for (auto spec : hit_specs) { + assert((docid + spec.num_hits) <= docid_limit); + std::fill_n(values.begin() + docid, spec.num_hits, spec.term_value); + docid += spec.num_hits; + } + std::shuffle(values.begin() + 1, values.end(), get_gen()); + populate_attribute<AttributeType, is_string, is_multivalue>(attr, values); + } else { + // For each term in HitSpecs we draw a new random set of docids that will match this term value. + populate_attribute<AttributeType, is_string, is_multivalue>(attr, docid_limit, hit_specs); + } +} + AttributeVector::SP -make_attribute(const Config& cfg, vespalib::stringref field_name, uint32_t num_docs, const HitSpecs& hit_specs) +make_attribute(const Config& cfg, vespalib::stringref field_name, uint32_t num_docs, const HitSpecs& hit_specs, bool disjunct_terms) { auto attr = AttributeFactory::createAttribute(field_name, cfg); attr->addReservedDoc(); @@ -52,16 +93,16 @@ make_attribute(const Config& cfg, vespalib::stringref field_name, uint32_t num_d if (attr->isStringType()) { auto& real = dynamic_cast<StringAttribute&>(*attr); if (is_multivalue) { - populate_attribute<StringAttribute, true, true>(real, docid_limit, hit_specs); + populate_attribute<StringAttribute, true, true>(real, docid_limit, hit_specs, disjunct_terms); } else { - populate_attribute<StringAttribute, true, false>(real, docid_limit, hit_specs); + populate_attribute<StringAttribute, true, false>(real, docid_limit, hit_specs, disjunct_terms); } } else { auto& real = dynamic_cast<IntegerAttribute&>(*attr); if (is_multivalue) { - populate_attribute<IntegerAttribute, false, true>(real, docid_limit, hit_specs); + populate_attribute<IntegerAttribute, false, true>(real, docid_limit, hit_specs, disjunct_terms); } else { - populate_attribute<IntegerAttribute, false, false>(real, docid_limit, hit_specs); + populate_attribute<IntegerAttribute, false, false>(real, docid_limit, hit_specs, disjunct_terms); } } attr->commit(true); @@ -90,9 +131,9 @@ AttributeContextBuilder::AttributeContextBuilder() } void -AttributeContextBuilder::add(const search::attribute::Config& cfg, vespalib::stringref field_name, uint32_t num_docs, const HitSpecs& hit_specs) +AttributeContextBuilder::add(const search::attribute::Config& cfg, vespalib::stringref field_name, uint32_t num_docs, const HitSpecs& hit_specs, bool disjunct_terms) { - auto attr = make_attribute(cfg, field_name, num_docs, hit_specs); + auto attr = make_attribute(cfg, field_name, num_docs, hit_specs, disjunct_terms); _ctx->add(std::move(attr)); } diff --git a/searchlib/src/tests/queryeval/iterator_benchmark/attribute_ctx_builder.h b/searchlib/src/tests/queryeval/iterator_benchmark/attribute_ctx_builder.h index e4a58c91668..7e5236e43be 100644 --- a/searchlib/src/tests/queryeval/iterator_benchmark/attribute_ctx_builder.h +++ b/searchlib/src/tests/queryeval/iterator_benchmark/attribute_ctx_builder.h @@ -19,7 +19,7 @@ private: public: AttributeContextBuilder(); - void add(const search::attribute::Config& cfg, vespalib::stringref field_name, uint32_t num_docs, const HitSpecs& hit_specs); + void add(const search::attribute::Config& cfg, vespalib::stringref field_name, uint32_t num_docs, const HitSpecs& hit_specs, bool disjunct_terms); std::unique_ptr<BenchmarkSearchable> build(); }; diff --git a/searchlib/src/tests/queryeval/iterator_benchmark/benchmark_blueprint_factory.cpp b/searchlib/src/tests/queryeval/iterator_benchmark/benchmark_blueprint_factory.cpp index 516a819aae8..0496a0e6dc8 100644 --- a/searchlib/src/tests/queryeval/iterator_benchmark/benchmark_blueprint_factory.cpp +++ b/searchlib/src/tests/queryeval/iterator_benchmark/benchmark_blueprint_factory.cpp @@ -42,11 +42,11 @@ calc_hits_per_term(uint32_t num_docs, double op_hit_ratio, uint32_t children, Qu } std::unique_ptr<BenchmarkSearchable> -make_searchable(const FieldConfig& cfg, uint32_t num_docs, const HitSpecs& hit_specs) +make_searchable(const FieldConfig& cfg, uint32_t num_docs, const HitSpecs& hit_specs, bool disjunct_terms) { if (cfg.is_attr()) { AttributeContextBuilder builder; - builder.add(cfg.attr_cfg(), field_name, num_docs, hit_specs); + builder.add(cfg.attr_cfg(), field_name, num_docs, hit_specs, disjunct_terms); return builder.build(); } else { uint32_t docid_limit = num_docs + 1; @@ -159,14 +159,14 @@ private: public: MyFactory(const FieldConfig& field_cfg, QueryOperator query_op, uint32_t num_docs, uint32_t default_values_per_document, - double op_hit_ratio, uint32_t children); + double op_hit_ratio, uint32_t children, bool disjunct_children); std::unique_ptr<Blueprint> make_blueprint() override; }; MyFactory::MyFactory(const FieldConfig& field_cfg, QueryOperator query_op, uint32_t num_docs, uint32_t default_values_per_document, - double op_hit_ratio, uint32_t children) + double op_hit_ratio, uint32_t children, bool disjunct_children) : _query_op(query_op), _docid_limit(num_docs + 1), _terms(), @@ -174,9 +174,17 @@ MyFactory::MyFactory(const FieldConfig& field_cfg, QueryOperator query_op, { uint32_t hits_per_term = calc_hits_per_term(num_docs, op_hit_ratio, children, query_op); HitSpecs hit_specs(55555); - hit_specs.add(default_values_per_document, num_docs); + if (!disjunct_children) { + hit_specs.add(default_values_per_document, num_docs); + } _terms = hit_specs.add(children, hits_per_term); - _searchable = make_searchable(field_cfg, num_docs, hit_specs); + if (disjunct_children && default_values_per_document != 0) { + // This ensures that the remaining docids are populated with a "default value". + // Only a single default value is supported. + uint32_t op_num_hits = num_docs * op_hit_ratio; + hit_specs.add(1, num_docs - op_num_hits); + } + _searchable = make_searchable(field_cfg, num_docs, hit_specs, disjunct_children); } std::unique_ptr<Blueprint> @@ -190,9 +198,9 @@ MyFactory::make_blueprint() std::unique_ptr<BenchmarkBlueprintFactory> make_blueprint_factory(const FieldConfig& field_cfg, QueryOperator query_op, uint32_t num_docs, uint32_t default_values_per_document, - double op_hit_ratio, uint32_t children) + double op_hit_ratio, uint32_t children, bool disjunct_children) { - return std::make_unique<MyFactory>(field_cfg, query_op, num_docs, default_values_per_document, op_hit_ratio, children); + return std::make_unique<MyFactory>(field_cfg, query_op, num_docs, default_values_per_document, op_hit_ratio, children, disjunct_children); } } diff --git a/searchlib/src/tests/queryeval/iterator_benchmark/benchmark_blueprint_factory.h b/searchlib/src/tests/queryeval/iterator_benchmark/benchmark_blueprint_factory.h index d3e529fcd65..423f517ffb0 100644 --- a/searchlib/src/tests/queryeval/iterator_benchmark/benchmark_blueprint_factory.h +++ b/searchlib/src/tests/queryeval/iterator_benchmark/benchmark_blueprint_factory.h @@ -21,6 +21,6 @@ public: std::unique_ptr<BenchmarkBlueprintFactory> make_blueprint_factory(const FieldConfig& field_cfg, QueryOperator query_op, uint32_t num_docs, uint32_t default_values_per_document, - double op_hit_ratio, uint32_t children); + double op_hit_ratio, uint32_t children, bool disjunct_children); } diff --git a/searchlib/src/tests/queryeval/iterator_benchmark/common.cpp b/searchlib/src/tests/queryeval/iterator_benchmark/common.cpp index f17403bd33a..c67a5ee1074 100644 --- a/searchlib/src/tests/queryeval/iterator_benchmark/common.cpp +++ b/searchlib/src/tests/queryeval/iterator_benchmark/common.cpp @@ -1,7 +1,6 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "common.h" -#include <random> #include <sstream> using search::attribute::CollectionType; @@ -49,6 +48,8 @@ std::mt19937 gen(default_seed); } +std::mt19937& get_gen() { return gen; } + BitVector::UP random_docids(uint32_t docid_limit, uint32_t count) { diff --git a/searchlib/src/tests/queryeval/iterator_benchmark/common.h b/searchlib/src/tests/queryeval/iterator_benchmark/common.h index 45fd82b091c..bf16e6f51d7 100644 --- a/searchlib/src/tests/queryeval/iterator_benchmark/common.h +++ b/searchlib/src/tests/queryeval/iterator_benchmark/common.h @@ -5,6 +5,7 @@ #include <vespa/searchcommon/attribute/config.h> #include <vespa/searchcommon/common/schema.h> #include <vespa/searchlib/common/bitvector.h> +#include <random> #include <variant> namespace search::queryeval::test { @@ -78,6 +79,8 @@ public: auto end() const { return _specs.end(); } }; +std::mt19937& get_gen(); + BitVector::UP random_docids(uint32_t docid_limit, uint32_t count); int32_t random_int(int32_t a, int32_t b); diff --git a/searchlib/src/tests/queryeval/iterator_benchmark/iterator_benchmark_test.cpp b/searchlib/src/tests/queryeval/iterator_benchmark/iterator_benchmark_test.cpp index b08fde50d7c..c6dae52fd69 100644 --- a/searchlib/src/tests/queryeval/iterator_benchmark/iterator_benchmark_test.cpp +++ b/searchlib/src/tests/queryeval/iterator_benchmark/iterator_benchmark_test.cpp @@ -31,25 +31,22 @@ struct BenchmarkResult { uint32_t hits; FlowStats flow; double actual_cost; - double alt_cost; vespalib::string iterator_name; vespalib::string blueprint_name; - BenchmarkResult() : BenchmarkResult(0, 0, 0, {0, 0, 0}, 0, 0, "", "") {} - BenchmarkResult(double time_ms_in, uint32_t seeks_in, uint32_t hits_in, FlowStats flow_in, double actual_cost_in, double alt_cost_in, + BenchmarkResult() : BenchmarkResult(0, 0, 0, {0, 0, 0}, 0, "", "") {} + BenchmarkResult(double time_ms_in, uint32_t seeks_in, uint32_t hits_in, FlowStats flow_in, double actual_cost_in, const vespalib::string& iterator_name_in, const vespalib::string& blueprint_name_in) : time_ms(time_ms_in), seeks(seeks_in), hits(hits_in), flow(flow_in), actual_cost(actual_cost_in), - alt_cost(alt_cost_in), iterator_name(iterator_name_in), blueprint_name(blueprint_name_in) {} ~BenchmarkResult(); double ns_per_seek() const { return (time_ms / seeks) * 1000.0 * 1000.0; } double ms_per_actual_cost() const { return (time_ms / actual_cost); } - double ms_per_alt_cost() const { return (time_ms / alt_cost); } }; BenchmarkResult::~BenchmarkResult() = default; @@ -128,9 +125,6 @@ public: Stats ms_per_actual_cost_stats() const { return calc_stats([](const auto& res){ return res.ms_per_actual_cost(); }); } - Stats ms_per_alt_cost_stats() const { - return calc_stats([](const auto& res){ return res.ms_per_alt_cost(); }); - } }; std::string @@ -222,7 +216,7 @@ strict_search(BenchmarkBlueprintFactory& factory, uint32_t docid_limit) timer.after(); } FlowStats flow(ctx.blueprint->estimate(), ctx.blueprint->cost(), ctx.blueprint->strict_cost()); - return {timer.min_time() * 1000.0, hits + 1, hits, flow, flow.strict_cost, flow.strict_cost, get_class_name(*ctx.iterator), get_class_name(*ctx.blueprint)}; + return {timer.min_time() * 1000.0, hits + 1, hits, flow, flow.strict_cost, get_class_name(*ctx.iterator), get_class_name(*ctx.blueprint)}; } template <bool do_unpack> @@ -256,9 +250,7 @@ non_strict_search(BenchmarkBlueprintFactory& factory, uint32_t docid_limit, doub } FlowStats flow(ctx.blueprint->estimate(), ctx.blueprint->cost(), ctx.blueprint->strict_cost()); double actual_cost = flow.cost * filter_hit_ratio; - // This is an attempt to calculate an alternative actual cost for strict / posting list iterators that are used in a non-strict context. - double alt_cost = flow.strict_cost + 0.5 * filter_hit_ratio; - return {timer.min_time() * 1000.0, seeks, hits, flow, actual_cost, alt_cost, get_class_name(*ctx.iterator), get_class_name(*ctx.blueprint)}; + return {timer.min_time() * 1000.0, seeks, hits, flow, actual_cost, get_class_name(*ctx.iterator), get_class_name(*ctx.blueprint)}; } BenchmarkResult @@ -413,32 +405,30 @@ to_string(bool val) void print_result_header() { - std::cout << "| chn | f_ratio | o_ratio | a_ratio | f.est | f.cost | f.scost | hits | seeks | time_ms | act_cost | alt_cost | ns_per_seek | ms_per_act_cost | ms_per_alt_cost | iterator | blueprint |" << std::endl; + std::cout << "| chn | f_ratio | o_ratio | a_ratio | f.est | f.cost | f.scost | hits | seeks | time_ms | act_cost | ns_per_seek | ms_per_act_cost | iterator | blueprint |" << std::endl; } void print_result(const BenchmarkResult& res, uint32_t children, double op_hit_ratio, double filter_hit_ratio, uint32_t num_docs) { std::cout << std::fixed << std::setprecision(5) - << "| " << std::setw(4) << children + << "| " << std::setw(5) << children << " | " << std::setw(7) << filter_hit_ratio << " | " << std::setw(7) << op_hit_ratio << " | " << std::setw(7) << ((double) res.hits / (double) num_docs) << " | " << std::setw(6) << res.flow.estimate << std::setprecision(4) - << " | " << std::setw(7) << res.flow.cost + << " | " << std::setw(9) << res.flow.cost << " | " << std::setw(7) << res.flow.strict_cost << " | " << std::setw(8) << res.hits << " | " << std::setw(8) << res.seeks << std::setprecision(3) << " | " << std::setw(8) << res.time_ms << std::setprecision(4) - << " | " << std::setw(8) << res.actual_cost - << " | " << std::setw(8) << res.alt_cost + << " | " << std::setw(9) << res.actual_cost << std::setprecision(2) << " | " << std::setw(11) << res.ns_per_seek() << " | " << std::setw(15) << res.ms_per_actual_cost() - << " | " << std::setw(15) << res.ms_per_alt_cost() << " | " << res.iterator_name << " | " << res.blueprint_name << " |" << std::endl; } @@ -449,8 +439,7 @@ print_result(const BenchmarkCaseResult& result) std::cout << std::fixed << std::setprecision(3) << "summary: time_ms=" << result.time_ms_stats().to_string() << std::endl << " ns_per_seek=" << result.ns_per_seek_stats().to_string() << std::endl - << " ms_per_act_cost=" << result.ms_per_actual_cost_stats().to_string() << std::endl - << " ms_per_alt_cost=" << result.ms_per_alt_cost_stats().to_string() << std::endl << std::endl; + << " ms_per_act_cost=" << result.ms_per_actual_cost_stats().to_string() << std::endl << std::endl; } struct BenchmarkCase { @@ -534,6 +523,7 @@ struct BenchmarkCaseSetup { std::vector<uint32_t> child_counts; std::vector<double> filter_hit_ratios; uint32_t default_values_per_document; + bool disjunct_children; double filter_crossover_factor; BenchmarkCaseSetup(uint32_t num_docs_in, const BenchmarkCase& bcase_in, @@ -545,6 +535,7 @@ struct BenchmarkCaseSetup { child_counts(child_counts_in), filter_hit_ratios({1.0}), default_values_per_document(0), + disjunct_children(false), filter_crossover_factor(0.0) {} ~BenchmarkCaseSetup() {} @@ -561,6 +552,7 @@ struct BenchmarkSetup { bool force_strict; bool unpack_iterator; uint32_t default_values_per_document; + bool disjunct_children; double filter_crossover_factor; BenchmarkSetup(uint32_t num_docs_in, const std::vector<FieldConfig>& field_cfgs_in, @@ -578,6 +570,7 @@ struct BenchmarkSetup { force_strict(false), unpack_iterator(false), default_values_per_document(0), + disjunct_children(false), filter_crossover_factor(0.0) {} BenchmarkSetup(uint32_t num_docs_in, @@ -592,6 +585,7 @@ struct BenchmarkSetup { res.bcase.force_strict = force_strict; res.bcase.unpack_iterator = unpack_iterator; res.default_values_per_document = default_values_per_document; + res.disjunct_children = disjunct_children; if (!bcase.strict_context) { // Simulation of a filter is only relevant in a non-strict context. res.filter_hit_ratios = filter_hit_ratios; @@ -617,7 +611,7 @@ run_benchmark_case(const BenchmarkCaseSetup& setup) for (uint32_t children : setup.child_counts) { auto factory = make_blueprint_factory(setup.bcase.field_cfg, setup.bcase.query_op, setup.num_docs, setup.default_values_per_document, - op_hit_ratio, children); + op_hit_ratio, children, setup.disjunct_children); for (double filter_hit_ratio : setup.filter_hit_ratios) { if (filter_hit_ratio * setup.filter_crossover_factor <= op_hit_ratio) { auto res = benchmark_search(*factory, setup.num_docs + 1, @@ -726,6 +720,22 @@ TEST(IteratorBenchmark, analyze_term_search_in_fast_search_attributes) run_benchmarks(setup, global_summary); } +TEST(IteratorBenchmark, analyze_in_operator_non_strict) +{ + const std::vector<double> hit_ratios = {0.001, 0.01, 0.1, 0.2, 0.4, 0.6, 0.8}; + BenchmarkSetup setup(num_docs, {int32_fs}, {QueryOperator::In}, {false}, hit_ratios, {5, 9, 10, 100, 1000, 10000}); + setup.disjunct_children = true; + run_benchmarks(setup); +} + +TEST(IteratorBenchmark, analyze_in_operator_strict) +{ + const std::vector<double> hit_ratios = {0.001, 0.01, 0.1, 0.2, 0.4, 0.6, 0.8}; + BenchmarkSetup setup(num_docs, {int32_fs}, {QueryOperator::In}, {true}, hit_ratios, {5, 9, 10, 100, 1000, 10000}); + setup.disjunct_children = true; + run_benchmarks(setup); +} + TEST(IteratorBenchmark, analyze_complex_leaf_operators) { std::vector<FieldConfig> field_cfgs = {int32_array_fs}; @@ -764,18 +774,18 @@ TEST(IteratorBenchmark, or_benchmark) TEST(IteratorBenchmark, or_vs_filter_crossover) { - auto fixed_or = make_blueprint_factory(int32_array_fs, QueryOperator::Or, num_docs, 0, 0.1, 100); + auto fixed_or = make_blueprint_factory(int32_array_fs, QueryOperator::Or, num_docs, 0, 0.1, 100, false); auto variable_term = [](double rate) { - return make_blueprint_factory(int32_array_fs, QueryOperator::Term, num_docs, 0, rate, 1); + return make_blueprint_factory(int32_array_fs, QueryOperator::Term, num_docs, 0, rate, 1, false); }; analyze_crossover(*fixed_or, variable_term, num_docs + 1, false, 0.0001); } TEST(IteratorBenchmark, or_vs_filter_crossover_with_allow_force_strict) { - auto fixed_or = make_blueprint_factory(int32_array_fs, QueryOperator::Or, num_docs, 0, 0.1, 100); + auto fixed_or = make_blueprint_factory(int32_array_fs, QueryOperator::Or, num_docs, 0, 0.1, 100, false); auto variable_term = [](double rate) { - return make_blueprint_factory(int32_array_fs, QueryOperator::Term, num_docs, 0, rate, 1); + return make_blueprint_factory(int32_array_fs, QueryOperator::Term, num_docs, 0, rate, 1, false); }; analyze_crossover(*fixed_or, variable_term, num_docs + 1, true, 0.0001); } diff --git a/searchlib/src/vespa/searchlib/queryeval/flow.h b/searchlib/src/vespa/searchlib/queryeval/flow.h index b57e823f4d7..9ac79244755 100644 --- a/searchlib/src/vespa/searchlib/queryeval/flow.h +++ b/searchlib/src/vespa/searchlib/queryeval/flow.h @@ -214,44 +214,39 @@ size_t select_strict_and_child(auto adapter, const auto &children) { return best_idx; } -auto select_forced_strict_and_child_impl(auto adapter, const auto &children, size_t first, auto ordered, auto destructive) { - auto est_until = [&](size_t limit)noexcept{ - double my_est = 1.0; - for (size_t i = 0; i < limit; ++i) { - my_est *= adapter.estimate(children[i]); - } - return my_est; - }; - double est = est_until(first); +auto select_forced_strict_and_child(auto adapter, const auto &children, size_t first) { + double est = 1.0; double cost = 0.0; size_t best_idx = first; size_t best_target = first; double best_diff = std::numeric_limits<double>::max(); + for (size_t i = 0; i < first; ++i) { + est *= adapter.estimate(children[i]); + } for (size_t idx = first; idx < children.size(); ++idx) { auto child = FlowStats::from(adapter, children[idx]); double child_abs_cost = est * child.cost; double forced_cost = forced_strict_cost(child, est); double my_diff = (forced_cost + child.estimate * cost) - (cost + child_abs_cost); size_t target = first; - while (ordered && target > 0) { + while (target > 0) { size_t candidate = target - 1; auto other = FlowStats::from(adapter, children[candidate]); if (other.estimate < child.estimate) { // do not move past someone with lower estimate break; } - if (!destructive && !should_force_strict(other, (est_until(candidate) * child.estimate))) { - // no not move past someone who will lose strictness, - // unless it is explicitly allowed by enabling - // destructive (re-)ordering - break; - } target = candidate; my_diff += (0.2 * child.estimate - 0.2 * other.estimate); if (candidate == 0) { // the first iterator produces its own in-flow my_diff += (0.2 * child.estimate - 0.2 * other.estimate); } + // note that 'my_diff' might overestimate the cost + // (underestimate the benefit) of inserting 'child' before + // 'other' if it leads to 'other' becoming + // non-strict. This will also leave 'other' in a + // potentially unoptimal location. } if (my_diff < best_diff) { best_diff = my_diff; @@ -264,19 +259,6 @@ auto select_forced_strict_and_child_impl(auto adapter, const auto &children, siz return std::make_tuple(best_idx, best_target, best_diff); } -auto select_forced_strict_and_child(auto adapter, const auto &children, size_t first) { - auto [idx, target, diff] = select_forced_strict_and_child_impl(adapter, children, first, std::false_type{}, std::false_type{}); - return std::make_pair(idx, diff); -} - -auto select_forced_strict_and_child_with_order(auto adapter, const auto &children, size_t first) { - return select_forced_strict_and_child_impl(adapter, children, first, std::true_type{}, std::false_type{}); -} - -auto select_forced_strict_and_child_with_destructive_order(auto adapter, const auto &children, size_t first) { - return select_forced_strict_and_child_impl(adapter, children, first, std::true_type{}, std::true_type{}); -} - } // flow template <typename FLOW> |