| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 org.apache.datasketches.tuple.adouble; |
| |
| import static org.testng.Assert.assertEquals; |
| import static org.testng.Assert.assertTrue; |
| import static org.testng.Assert.fail; |
| |
| import org.apache.datasketches.SketchesArgumentException; |
| import org.apache.datasketches.theta.UpdateSketch; |
| import org.apache.datasketches.theta.UpdateSketchBuilder; |
| import org.apache.datasketches.tuple.AnotB; |
| import org.apache.datasketches.tuple.CompactSketch; |
| import org.apache.datasketches.tuple.Sketch; |
| import org.apache.datasketches.tuple.SketchIterator; |
| import org.apache.datasketches.tuple.UpdatableSketch; |
| import org.apache.datasketches.tuple.UpdatableSketchBuilder; |
| import org.apache.datasketches.tuple.adouble.DoubleSummary.Mode; |
| import org.testng.Assert; |
| import org.testng.annotations.Test; |
| |
| /** |
| * @author Lee Rhodes |
| */ |
| @SuppressWarnings("javadoc") |
| public class AdoubleAnotBTest { |
| private static final DoubleSummary.Mode mode = Mode.Sum; |
| private final Results results = new Results(); |
| |
| @SuppressWarnings("deprecation") |
| private static void threeMethodsWithTheta( |
| final AnotB<DoubleSummary> aNotB, |
| final Sketch<DoubleSummary> skA, |
| final Sketch<DoubleSummary> skB, |
| final org.apache.datasketches.theta.Sketch skThetaB, |
| final Results results) |
| { |
| CompactSketch<DoubleSummary> result; |
| |
| //Deprecated v2.0.0., Stateless, A = Tuple, B = Tuple |
| //Old behavior is tolerant of nulls |
| aNotB.update(skA, skB); |
| result = aNotB.getResult(); |
| results.check(result); |
| |
| //Stateless A = Tuple, B = Tuple |
| if (skA == null || skB == null) { |
| try { |
| result = AnotB.aNotB(skA, skB); |
| fail(); |
| } |
| catch (final SketchesArgumentException e) { } |
| } else { |
| result = AnotB.aNotB(skA, skB); |
| results.check(result); |
| } |
| |
| //Stateless A = Tuple, B = Theta |
| if (skA == null || skThetaB == null) { |
| try { result = AnotB.aNotB(skA, skThetaB); fail(); } |
| catch (final SketchesArgumentException e) { } |
| } else { |
| result = AnotB.aNotB(skA, skThetaB); |
| results.check(result); |
| } |
| |
| //Stateful A = Tuple, B = Tuple |
| if (skA == null) { |
| try { aNotB.setA(skA); fail(); } |
| catch (final SketchesArgumentException e) { } |
| } else { |
| aNotB.setA(skA); |
| aNotB.notB(skB); |
| result = aNotB.getResult(true); |
| results.check(result); |
| } |
| |
| //Stateful A = Tuple, B = Theta |
| if (skA == null) { |
| try { aNotB.setA(skA); fail(); } |
| catch (final SketchesArgumentException e) { } |
| } else { |
| aNotB.setA(skA); |
| aNotB.notB(skThetaB); |
| result = aNotB.getResult(false); |
| results.check(result); |
| result = aNotB.getResult(true); |
| results.check(result); |
| } |
| } |
| |
| private static class Results { |
| private int retEnt = 0; |
| private boolean empty = true; |
| private double expect = 0.0; |
| private double tol = 0.0; |
| private double sum = 0.0; |
| |
| Results() {} |
| |
| Results set(final int retEnt, final boolean empty, |
| final double expect, final double tol, final double sum) { |
| this.retEnt = retEnt; //retained Entries |
| this.empty = empty; |
| this.expect = expect; //expected estimate |
| this.tol = tol; //tolerance |
| this.sum = sum; |
| return this; |
| } |
| |
| void check(final CompactSketch<DoubleSummary> result) { |
| assertEquals(result.getRetainedEntries(), retEnt); |
| assertEquals(result.isEmpty(), empty); |
| if (result.getTheta() < 1.0) { |
| final double est = result.getEstimate(); |
| assertEquals(est, expect, expect * tol); |
| assertTrue(result.getUpperBound(1) > est); |
| assertTrue(result.getLowerBound(1) <= est); |
| } else { |
| assertEquals(result.getEstimate(), expect, 0.0); |
| assertEquals(result.getUpperBound(1), expect, 0.0); |
| assertEquals(result.getLowerBound(1), expect, 0.0); |
| } |
| final SketchIterator<DoubleSummary> it = result.iterator(); |
| while (it.next()) { |
| Assert.assertEquals(it.getSummary().getValue(), sum); |
| } |
| } |
| } //End class Results |
| |
| private static UpdatableSketch<Double, DoubleSummary> buildUpdatableTuple() { |
| return new UpdatableSketchBuilder<>(new DoubleSummaryFactory(mode)).build(); |
| } |
| |
| private static UpdateSketch buildUpdateTheta() { |
| return new UpdateSketchBuilder().build(); |
| } |
| |
| /*****************************************/ |
| |
| @SuppressWarnings("deprecation") |
| @Test |
| public void aNotBNullEmptyCombinations() { |
| final AnotB<DoubleSummary> aNotB = new AnotB<>(); |
| // calling getResult() before calling update() should yield an empty set |
| final CompactSketch<DoubleSummary> result = aNotB.getResult(); |
| results.set(0, true, 0.0, 0.0, 0.0).check(result); |
| |
| final UpdatableSketch<Double, DoubleSummary> sketch = buildUpdatableTuple(); |
| final UpdateSketch skTheta = buildUpdateTheta(); |
| |
| threeMethodsWithTheta(aNotB, null, null, null, results); |
| threeMethodsWithTheta(aNotB, sketch, null, null, results); |
| threeMethodsWithTheta(aNotB, null, sketch, null, results); |
| threeMethodsWithTheta(aNotB, sketch, sketch, null, results); |
| threeMethodsWithTheta(aNotB, null, null, skTheta, results); |
| threeMethodsWithTheta(aNotB, sketch, null, skTheta, results); |
| threeMethodsWithTheta(aNotB, null, sketch, skTheta, results); |
| threeMethodsWithTheta(aNotB, sketch, sketch, skTheta, results); |
| } |
| |
| @Test |
| public void aNotBCheckDoubleSetAs() { |
| final UpdatableSketch<Double, DoubleSummary> skA = buildUpdatableTuple(); |
| skA.update(1, 1.0); |
| skA.update(2, 1.0); |
| final UpdatableSketch<Double, DoubleSummary> skA2 = buildUpdatableTuple(); |
| final AnotB<DoubleSummary> aNotB = new AnotB<>(); |
| aNotB.setA(skA); |
| assertEquals(aNotB.getResult(false).isEmpty(), false); |
| aNotB.setA(skA2); |
| assertEquals(aNotB.getResult(false).isEmpty(), true); |
| } |
| |
| @Test |
| public void aNotBEmptyExact() { |
| final UpdatableSketch<Double, DoubleSummary> sketchA = buildUpdatableTuple(); |
| final UpdatableSketch<Double, DoubleSummary> sketchB = buildUpdatableTuple(); |
| sketchB.update(1, 1.0); |
| sketchB.update(2, 1.0); |
| final UpdateSketch skThetaB = buildUpdateTheta(); |
| skThetaB.update(1); |
| skThetaB.update(2); |
| |
| final AnotB<DoubleSummary> aNotB = new AnotB<>(); |
| results.set(0, true, 0.0, 0.0, 0.0); |
| threeMethodsWithTheta(aNotB, sketchA, sketchB, skThetaB, results); |
| } |
| |
| @Test |
| public void aNotBExactEmpty() { |
| final UpdatableSketch<Double, DoubleSummary> sketchA = buildUpdatableTuple(); |
| sketchA.update(1, 1.0); |
| sketchA.update(2, 1.0); |
| final UpdatableSketch<Double, DoubleSummary> sketchB = buildUpdatableTuple(); |
| final UpdateSketch skThetaB = buildUpdateTheta(); |
| |
| final AnotB<DoubleSummary> aNotB = new AnotB<>(); |
| results.set(2, false, 2.0, 0.0, 1.0); |
| threeMethodsWithTheta(aNotB, sketchA, sketchB, skThetaB, results); |
| |
| // same thing, but compact sketches |
| threeMethodsWithTheta(aNotB, sketchA.compact(), sketchB.compact(), skThetaB.compact(), results); |
| } |
| |
| @Test |
| public void aNotBExactOverlap() { |
| final UpdatableSketch<Double, DoubleSummary> sketchA = buildUpdatableTuple(); |
| sketchA.update(1, 1.0); |
| sketchA.update(1, 1.0); |
| sketchA.update(2, 1.0); |
| sketchA.update(2, 1.0); |
| |
| final UpdatableSketch<Double, DoubleSummary> sketchB = buildUpdatableTuple(); |
| sketchB.update(2, 1.0); |
| sketchB.update(2, 1.0); |
| sketchB.update(3, 1.0); |
| sketchB.update(3, 1.0); |
| |
| final UpdateSketch skThetaB = buildUpdateTheta(); |
| skThetaB.update(2); |
| skThetaB.update(3); |
| |
| final AnotB<DoubleSummary> aNotB = new AnotB<>(); |
| results.set(1, false, 1.0, 0.0, 2.0); |
| threeMethodsWithTheta(aNotB, sketchA, sketchB, skThetaB, results); |
| } |
| |
| @Test |
| public void aNotBEstimationOverlap() { |
| final UpdatableSketch<Double, DoubleSummary> sketchA = buildUpdatableTuple(); |
| for (int i = 0; i < 8192; i++) { |
| sketchA.update(i, 1.0); |
| } |
| |
| final UpdatableSketch<Double, DoubleSummary> sketchB = buildUpdatableTuple(); |
| for (int i = 0; i < 4096; i++) { |
| sketchB.update(i, 1.0); |
| } |
| |
| final UpdateSketch skThetaB = buildUpdateTheta(); |
| for (int i = 0; i < 4096; i++) { |
| skThetaB.update(i); |
| } |
| |
| final AnotB<DoubleSummary> aNotB = new AnotB<>(); |
| results.set(2123, false, 4096.0, 0.03, 1.0); |
| threeMethodsWithTheta(aNotB, sketchA, sketchB, skThetaB, results); |
| |
| // same thing, but compact sketches |
| threeMethodsWithTheta(aNotB, sketchA.compact(), sketchB.compact(), skThetaB.compact(), results); |
| } |
| |
| @Test |
| public void aNotBEstimationOverlapLargeB() { |
| final UpdatableSketch<Double, DoubleSummary> sketchA = buildUpdatableTuple(); |
| for (int i = 0; i < 10_000; i++) { |
| sketchA.update(i, 1.0); |
| } |
| |
| final UpdatableSketch<Double, DoubleSummary> sketchB = buildUpdatableTuple(); |
| for (int i = 0; i < 100_000; i++) { |
| sketchB.update(i + 8000, 1.0); |
| } |
| |
| final UpdateSketch skThetaB = buildUpdateTheta(); |
| for (int i = 0; i < 100_000; i++) { |
| skThetaB.update(i + 8000); |
| } |
| |
| final int expected = 8_000; |
| final AnotB<DoubleSummary> aNotB = new AnotB<>(); |
| results.set(376, false, expected, 0.1, 1.0); |
| threeMethodsWithTheta(aNotB, sketchA, sketchB, skThetaB, results); |
| |
| // same thing, but compact sketches |
| threeMethodsWithTheta(aNotB, sketchA.compact(), sketchB.compact(), skThetaB.compact(), results); |
| } |
| |
| } |