| /* |
| * 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.theta; |
| |
| import org.testng.annotations.Test; |
| |
| public class CornerCaseThetaSetOperationsTest { |
| |
| /* Hash Values |
| * 9223372036854775807 Theta = 1.0 |
| * |
| * 6730918654704304314 hash(3L)[0] >>> 1 GT_MIDP |
| * 4611686018427387904 Theta for p = 0.5f = MIDP |
| * 2206043092153046979 hash(2L)[0] >>> 1 LT_MIDP_V |
| * 1498732507761423037 hash(5L)[0] >>> 1 LTLT_MIDP_V |
| * |
| * 1206007004353599230 hash(6L)[0] >>> 1 GT_LOWP_V |
| * 922337217429372928 Theta for p = 0.1f = LOWP |
| * 593872385995628096 hash(4L)[0] >>> 1 LT_LOWP_V |
| * 405753591161026837 hash(1L)[0] >>> 1 LTLT_LOWP_V |
| */ |
| |
| private static final long GT_MIDP_V = 3L; |
| private static final float MIDP = 0.5f; |
| |
| private static final long GT_LOWP_V = 6L; |
| private static final float LOWP = 0.1f; |
| private static final long LT_LOWP_V = 4L; |
| |
| private static final double LOWP_THETA = LOWP; |
| |
| private enum SkType { |
| EMPTY, // { 1.0, 0, T} Bin: 101 Oct: 05 |
| EXACT, // { 1.0, >0, F} Bin: 110 Oct: 06, specify only value |
| ESTIMATION, // {<1.0, >0, F} Bin: 010 Oct: 02, specify only value |
| DEGENERATE // {<1.0, 0, F} Bin: 000 Oct: 0, specify p, value |
| } |
| |
| //NOTE: 0 values in getSketch are not used. |
| |
| private static void checks( |
| UpdateSketch thetaA, |
| UpdateSketch thetaB, |
| double resultInterTheta, |
| int resultInterCount, |
| boolean resultInterEmpty, |
| double resultAnotbTheta, |
| int resultAnotbCount, |
| boolean resultAnotbEmpty) { |
| CompactSketch csk; |
| |
| Intersection inter = SetOperation.builder().buildIntersection(); |
| |
| csk = inter.intersect(thetaA, thetaB); |
| checkResult("Intersect Stateless Theta, Theta", csk, resultInterTheta, resultInterCount, resultInterEmpty); |
| csk = inter.intersect(thetaA.compact(), thetaB.compact()); |
| checkResult("Intersect Stateless Theta, Theta", csk, resultInterTheta, resultInterCount, resultInterEmpty); |
| |
| AnotB anotb = SetOperation.builder().buildANotB(); |
| |
| csk = anotb.aNotB(thetaA, thetaB); |
| checkResult("AnotB Stateless Theta, Theta", csk, resultAnotbTheta, resultAnotbCount, resultAnotbEmpty); |
| csk = anotb.aNotB(thetaA.compact(), thetaB.compact()); |
| checkResult("AnotB Stateless Theta, Theta", csk, resultAnotbTheta, resultAnotbCount, resultAnotbEmpty); |
| |
| anotb.setA(thetaA); |
| anotb.notB(thetaB); |
| csk = anotb.getResult(true); |
| checkResult("AnotB Stateful Theta, Theta", csk, resultAnotbTheta, resultAnotbCount, resultAnotbEmpty); |
| |
| anotb.setA(thetaA.compact()); |
| anotb.notB(thetaB.compact()); |
| csk = anotb.getResult(true); |
| checkResult("AnotB Stateful Theta, Theta", csk, resultAnotbTheta, resultAnotbCount, resultAnotbEmpty); |
| } |
| |
| |
| @Test |
| public void emptyEmpty() { |
| UpdateSketch thetaA = getSketch(SkType.EMPTY, 0, 0); |
| UpdateSketch thetaB = getSketch(SkType.EMPTY, 0, 0); |
| final double resultInterTheta = 1.0; |
| final int resultInterCount = 0; |
| final boolean resultInterEmpty = true; |
| final double resultAnotbTheta = 1.0; |
| final int resultAnotbCount = 0; |
| final boolean resultAnotbEmpty = true; |
| |
| checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty, |
| resultAnotbTheta, resultAnotbCount, resultAnotbEmpty); |
| } |
| |
| @Test |
| public void emptyExact() { |
| UpdateSketch thetaA = getSketch(SkType.EMPTY, 0, 0); |
| UpdateSketch thetaB = getSketch(SkType.EXACT, 0, GT_MIDP_V); |
| final double resultInterTheta = 1.0; |
| final int resultInterCount = 0; |
| final boolean resultInterEmpty = true; |
| final double resultAnotbTheta = 1.0; |
| final int resultAnotbCount = 0; |
| final boolean resultAnotbEmpty = true; |
| |
| checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty, |
| resultAnotbTheta, resultAnotbCount, resultAnotbEmpty); |
| } |
| |
| @Test |
| public void emptyDegenerate() { |
| UpdateSketch thetaA = getSketch(SkType.EMPTY, 0, 0); |
| UpdateSketch thetaB = getSketch(SkType.DEGENERATE, LOWP, GT_LOWP_V); |
| final double resultInterTheta = 1.0; |
| final int resultInterCount = 0; |
| final boolean resultInterEmpty = true; |
| final double resultAnotbTheta = 1.0; |
| final int resultAnotbCount = 0; |
| final boolean resultAnotbEmpty = true; |
| |
| checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty, |
| resultAnotbTheta, resultAnotbCount, resultAnotbEmpty); |
| } |
| |
| @Test |
| public void EmptyEstimation() { |
| UpdateSketch thetaA = getSketch(SkType.EMPTY, 0, 0); |
| UpdateSketch thetaB = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V); |
| final double resultInterTheta = 1.0; |
| final int resultInterCount = 0; |
| final boolean resultInterEmpty = true; |
| final double resultAnotbTheta = 1.0; |
| final int resultAnotbCount = 0; |
| final boolean resultAnotbEmpty = true; |
| |
| checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty, |
| resultAnotbTheta, resultAnotbCount, resultAnotbEmpty); |
| } |
| |
| /*********************/ |
| |
| @Test |
| public void exactEmpty() { |
| UpdateSketch thetaA = getSketch(SkType.EXACT, 0, GT_MIDP_V); |
| UpdateSketch thetaB = getSketch(SkType.EMPTY, 0, 0); |
| final double resultInterTheta = 1.0; |
| final int resultInterCount = 0; |
| final boolean resultInterEmpty = true; |
| final double resultAnotbTheta = 1.0; |
| final int resultAnotbCount = 1; |
| final boolean resultAnotbEmpty = false; |
| |
| checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty, |
| resultAnotbTheta, resultAnotbCount, resultAnotbEmpty); |
| } |
| |
| @Test |
| public void exactExact() { |
| UpdateSketch thetaA = getSketch(SkType.EXACT, 0, GT_MIDP_V); |
| UpdateSketch thetaB = getSketch(SkType.EXACT, 0, GT_MIDP_V); |
| final double resultInterTheta = 1.0; |
| final int resultInterCount = 1; |
| final boolean resultInterEmpty = false; |
| final double resultAnotbTheta = 1.0; |
| final int resultAnotbCount = 0; |
| final boolean resultAnotbEmpty = true; |
| |
| checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty, |
| resultAnotbTheta, resultAnotbCount, resultAnotbEmpty); |
| } |
| |
| @Test |
| public void exactDegenerate() { |
| UpdateSketch thetaA = getSketch(SkType.EXACT, 0, LT_LOWP_V); |
| UpdateSketch thetaB = getSketch(SkType.DEGENERATE, LOWP, GT_LOWP_V); //entries = 0 |
| final double resultInterTheta = LOWP_THETA; |
| final int resultInterCount = 0; |
| final boolean resultInterEmpty = false; |
| final double resultAnotbTheta = LOWP_THETA; |
| final int resultAnotbCount = 1; |
| final boolean resultAnotbEmpty = false; |
| |
| checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty, |
| resultAnotbTheta, resultAnotbCount, resultAnotbEmpty); |
| } |
| |
| @Test |
| public void exactEstimation() { |
| UpdateSketch thetaA = getSketch(SkType.EXACT, 0, LT_LOWP_V); |
| UpdateSketch thetaB = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V); |
| final double resultInterTheta = LOWP_THETA; |
| final int resultInterCount = 1; |
| final boolean resultInterEmpty = false; |
| final double resultAnotbTheta = LOWP_THETA; |
| final int resultAnotbCount = 0; |
| final boolean resultAnotbEmpty = false; |
| |
| checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty, |
| resultAnotbTheta, resultAnotbCount, resultAnotbEmpty); |
| } |
| |
| /*********************/ |
| |
| @Test |
| public void estimationEmpty() { |
| UpdateSketch thetaA = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V); |
| UpdateSketch thetaB = getSketch(SkType.EMPTY, 0, 0); |
| final double resultInterTheta = 1.0; |
| final int resultInterCount = 0; |
| final boolean resultInterEmpty = true; |
| final double resultAnotbTheta = LOWP_THETA; |
| final int resultAnotbCount = 1; |
| final boolean resultAnotbEmpty = false; |
| |
| checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty, |
| resultAnotbTheta, resultAnotbCount, resultAnotbEmpty); |
| } |
| |
| @Test |
| public void estimationExact() { |
| UpdateSketch thetaA = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V); |
| UpdateSketch thetaB = getSketch(SkType.EXACT, 0, LT_LOWP_V); |
| final double resultInterTheta = LOWP_THETA; |
| final int resultInterCount = 1; |
| final boolean resultInterEmpty = false; |
| final double resultAnotbTheta = LOWP_THETA; |
| final int resultAnotbCount = 0; |
| final boolean resultAnotbEmpty = false; |
| |
| checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty, |
| resultAnotbTheta, resultAnotbCount, resultAnotbEmpty); |
| } |
| |
| @Test |
| public void estimationDegenerate() { |
| UpdateSketch thetaA = getSketch(SkType.ESTIMATION, MIDP, LT_LOWP_V); |
| UpdateSketch thetaB = getSketch(SkType.DEGENERATE, LOWP, GT_LOWP_V); |
| final double resultInterTheta = LOWP_THETA; |
| final int resultInterCount = 0; |
| final boolean resultInterEmpty = false; |
| final double resultAnotbTheta = LOWP_THETA; |
| final int resultAnotbCount = 1; |
| final boolean resultAnotbEmpty = false; |
| |
| checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty, |
| resultAnotbTheta, resultAnotbCount, resultAnotbEmpty); |
| } |
| |
| @Test |
| public void estimationEstimation() { |
| UpdateSketch thetaA = getSketch(SkType.ESTIMATION, MIDP, LT_LOWP_V); |
| UpdateSketch thetaB = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V); |
| final double resultInterTheta = LOWP_THETA; |
| final int resultInterCount = 1; |
| final boolean resultInterEmpty = false; |
| final double resultAnotbTheta = LOWP_THETA; |
| final int resultAnotbCount = 0; |
| final boolean resultAnotbEmpty = false; |
| |
| checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty, |
| resultAnotbTheta, resultAnotbCount, resultAnotbEmpty); |
| } |
| |
| /*********************/ |
| |
| @Test |
| public void DegenerateEmpty() { |
| UpdateSketch thetaA = getSketch(SkType.DEGENERATE, LOWP, GT_LOWP_V); //entries = 0 |
| UpdateSketch thetaB = getSketch(SkType.EMPTY, 0, 0); |
| final double resultInterTheta = 1.0; |
| final int resultInterCount = 0; |
| final boolean resultInterEmpty = true; |
| final double resultAnotbTheta = LOWP_THETA; |
| final int resultAnotbCount = 0; |
| final boolean resultAnotbEmpty = false; |
| |
| checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty, |
| resultAnotbTheta, resultAnotbCount, resultAnotbEmpty); |
| } |
| |
| @Test |
| public void DegenerateExact() { |
| UpdateSketch thetaA = getSketch(SkType.DEGENERATE, LOWP, GT_LOWP_V); //entries = 0 |
| UpdateSketch thetaB = getSketch(SkType.EXACT, 0, LT_LOWP_V); |
| final double resultInterTheta = LOWP_THETA; |
| final int resultInterCount = 0; |
| final boolean resultInterEmpty = false; |
| final double resultAnotbTheta = LOWP_THETA; |
| final int resultAnotbCount = 0; |
| final boolean resultAnotbEmpty = false; |
| |
| checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty, |
| resultAnotbTheta, resultAnotbCount, resultAnotbEmpty); |
| } |
| |
| @Test |
| public void DegenerateDegenerate() { |
| UpdateSketch thetaA = getSketch(SkType.DEGENERATE, MIDP, GT_MIDP_V); //entries = 0 |
| UpdateSketch thetaB = getSketch(SkType.DEGENERATE, LOWP, GT_LOWP_V); |
| final double resultInterTheta = LOWP_THETA; |
| final int resultInterCount = 0; |
| final boolean resultInterEmpty = false; |
| final double resultAnotbTheta = LOWP_THETA; |
| final int resultAnotbCount = 0; |
| final boolean resultAnotbEmpty = false; |
| |
| checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty, |
| resultAnotbTheta, resultAnotbCount, resultAnotbEmpty); |
| } |
| |
| @Test |
| public void DegenerateEstimation() { |
| UpdateSketch thetaA = getSketch(SkType.DEGENERATE, MIDP, GT_MIDP_V); //entries = 0 |
| UpdateSketch thetaB = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V); |
| final double resultInterTheta = LOWP_THETA; |
| final int resultInterCount = 0; |
| final boolean resultInterEmpty = false; |
| final double resultAnotbTheta = LOWP_THETA; |
| final int resultAnotbCount = 0; |
| final boolean resultAnotbEmpty = false; |
| |
| checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty, |
| resultAnotbTheta, resultAnotbCount, resultAnotbEmpty); |
| } |
| |
| //================================= |
| |
| private static void checkResult(String comment, CompactSketch sk, double theta, int entries, boolean empty) { |
| double skTheta = sk.getTheta(); |
| int skEntries = sk.getRetainedEntries(); |
| boolean skEmpty = sk.isEmpty(); |
| |
| boolean thetaOk = skTheta == theta; |
| boolean entriesOk = skEntries == entries; |
| boolean emptyOk = skEmpty == empty; |
| if (!thetaOk || !entriesOk || !emptyOk) { |
| StringBuilder sb = new StringBuilder(); |
| sb.append(comment + ": "); |
| if (!thetaOk) { sb.append("Got: " + skTheta + ", Expected: " + theta + "; "); } |
| if (!entriesOk) { sb.append("Got: " + skEntries + ", Expected: " + entries + "; "); } |
| if (!emptyOk) { sb.append("Got: " + skEmpty + ", Expected: " + empty + "."); } |
| throw new IllegalArgumentException(sb.toString()); |
| } |
| } |
| |
| private static UpdateSketch getSketch(SkType skType, float p, long value) { |
| UpdateSketchBuilder bldr = UpdateSketch.builder(); |
| bldr.setLogNominalEntries(4); |
| UpdateSketch sk; |
| switch(skType) { |
| case EMPTY: { // { 1.0, 0, T} |
| sk = bldr.build(); |
| break; |
| } |
| case EXACT: { // { 1.0, >0, F} |
| sk = bldr.build(); |
| sk.update(value); |
| break; |
| } |
| case ESTIMATION: { // {<1.0, >0, F} |
| bldr.setP(p); |
| sk = bldr.build(); |
| sk.update(value); |
| break; |
| } |
| case DEGENERATE: { // {<1.0, 0, F} |
| bldr.setP(p); |
| sk = bldr.build(); |
| sk.update(value); |
| break; |
| } |
| |
| default: { return null; } // should not happen |
| } |
| return sk; |
| } |
| |
| // private static void println(Object o) { |
| // System.out.println(o.toString()); |
| // } |
| |
| // @Test |
| // public void printHash() { |
| // long seed = DEFAULT_UPDATE_SEED; |
| // long v = 6; |
| // long hash = (hash(v, seed)[0]) >>> 1; |
| // println(v + ", " + hash); |
| // } |
| |
| // @Test |
| // public void printPAsLong() { |
| // float p = 0.5f; |
| // println("p = " + p + ", " + (long)(Long.MAX_VALUE * p)); |
| // } |
| |
| } |