Skip to content

Commit 1942b88

Browse files
authored
examples and test (#259)
* examples and test * fixes * fixes * cleanup
1 parent 1b010f5 commit 1942b88

File tree

5 files changed

+341
-103
lines changed

5 files changed

+341
-103
lines changed

Java/core/src/test/java/com/amazon/randomcutforest/DynamicPointSetFunctionalTest.java

+126-99
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,20 @@
1515

1616
package com.amazon.randomcutforest;
1717

18+
import static com.amazon.randomcutforest.testutils.ExampleDataSets.generateFan;
19+
import static java.lang.Math.PI;
1820
import static java.lang.Math.cos;
1921
import static java.lang.Math.sin;
22+
import static org.junit.jupiter.api.Assertions.assertEquals;
2023
import static org.junit.jupiter.api.Assertions.assertTrue;
2124

25+
import java.util.List;
26+
2227
import org.junit.jupiter.api.Tag;
28+
import org.junit.jupiter.api.Test;
29+
30+
import com.amazon.randomcutforest.returntypes.DensityOutput;
31+
import com.amazon.randomcutforest.returntypes.Neighbor;
2332

2433
@Tag("functional")
2534
public class DynamicPointSetFunctionalTest {
@@ -40,108 +49,126 @@ public class DynamicPointSetFunctionalTest {
4049
private static double transitionToBaseProbability;
4150
private static int dataSize;
4251

43-
public double[] rotateClockWise(double[] point, double theta) {
44-
assertTrue(point.length == 2);
52+
static double[] rotateClockWise(double[] point, double theta) {
4553
double[] result = new double[2];
4654
result[0] = cos(theta) * point[0] + sin(theta) * point[1];
4755
result[1] = -sin(theta) * point[0] + cos(theta) * point[1];
4856
return result;
4957
}
50-
/*
51-
* @Test public void movingDensity() { int newDimensions = 2; randomSeed = 123;
52-
*
53-
* RandomCutForest newForest = RandomCutForest.builder() .numberOfTrees(100)
54-
* .sampleSize(256) .dimensions(newDimensions) .randomSeed(randomSeed)
55-
* .windowSize(800) .centerOfMassEnabled(true)
56-
* .storeSequenceIndexesEnabled(true) .build();
57-
*
58-
* double[][] data = generateFan(1000, 3);
59-
*
60-
* double[] queryPoint = new double[]{0.7, 0}; for (int degree = 0; degree <
61-
* 360; degree += 2) { for (int j = 0; j < data.length; j++) {
62-
* newForest.update(rotateClockWise(data[j], 2 * PI * degree / 360)); }
63-
* DensityOutput density = newForest.getSimpleDensity(queryPoint); double value
64-
* = density.getDensity(0.001, 2); if ((degree <= 60) || ((degree >= 120) &&
65-
* (degree <= 180)) || ((degree >= 240) && (degree <= 300))) assertTrue(value <
66-
* 0.8); // the fan is above at 90,210,330
67-
*
68-
* if (((degree >= 75) && (degree <= 105)) || ((degree >= 195) && (degree <=
69-
* 225)) || ((degree >= 315) && (degree <= 345))) assertTrue(value > 0.5); //
70-
* fan is close by //intentionally 0.5 is below 0.8 for a robust test
71-
*
72-
* // Testing for directionality // There can be unclear directionality when the
73-
* blades are right above
74-
*
75-
* double bladeAboveInY = density.getDirectionalDensity(0.001, 2).low[1]; double
76-
* bladeBelowInY = density.getDirectionalDensity(0.001, 2).high[1]; double
77-
* bladesToTheLeft = density.getDirectionalDensity(0.001, 2).high[0]; double
78-
* bladesToTheRight = density.getDirectionalDensity(0.001, 2).low[0];
79-
*
80-
*
81-
* assertEquals(value, bladeAboveInY + bladeBelowInY + bladesToTheLeft +
82-
* bladesToTheRight, 1E-6);
83-
*
84-
* // the tests below have a freedom of 10% of the total value if (((degree >=
85-
* 75) && (degree <= 86)) || ((degree >= 195) && (degree <= 206)) || ((degree >=
86-
* 315) && (degree <= 326))) { assertTrue(bladeAboveInY + 0.1 * value >
87-
* bladeBelowInY); assertTrue(bladeAboveInY + 0.1 * value > bladesToTheRight); }
88-
*
89-
* if (((degree >= 94) && (degree <= 105)) || ((degree >= 214) && (degree <=
90-
* 225)) || ((degree >= 334) && (degree <= 345))) { assertTrue(bladeBelowInY +
91-
* 0.1 * value > bladeAboveInY); assertTrue(bladeBelowInY + 0.1 * value >
92-
* bladesToTheRight); }
93-
*
94-
* if (((degree >= 60) && (degree <= 75)) || ((degree >= 180) && (degree <=
95-
* 195)) || ((degree >= 300) && (degree <= 315))) { assertTrue(bladeAboveInY +
96-
* 0.1 * value > bladesToTheLeft); assertTrue(bladeAboveInY + 0.1 * value >
97-
* bladesToTheRight); }
98-
*
99-
* if (((degree >= 105) && (degree <= 120)) || ((degree >= 225) && (degree <=
100-
* 240)) || (degree >= 345)) { assertTrue(bladeBelowInY + 0.1 * value >
101-
* bladesToTheLeft); assertTrue(bladeBelowInY + 0.1 * value > bladesToTheRight);
102-
* }
103-
*
104-
* // fans are farthest to the left at 30,150 and 270 if (((degree >= 15) &&
105-
* (degree <= 45)) || ((degree >= 135) && (degree <= 165)) || ((degree >= 255)
106-
* && (degree <= 285))) { assertTrue(bladesToTheLeft + 0.1 * value >
107-
* bladeAboveInY + bladeBelowInY + bladesToTheRight); assertTrue(bladeAboveInY +
108-
* bladeBelowInY + 0.1 * value > bladesToTheRight); }
109-
*
110-
* }
111-
*
112-
* }
113-
*
114-
* @Test public void movingNeighbors() { int newDimensions = 2; randomSeed =
115-
* 123;
116-
*
117-
* RandomCutForest newForest = RandomCutForest.builder() .numberOfTrees(100)
118-
* .sampleSize(256) .dimensions(newDimensions) .randomSeed(randomSeed)
119-
* .windowSize(800) .centerOfMassEnabled(true)
120-
* .storeSequenceIndexesEnabled(true) .build();
121-
*
122-
* double[][] data = generateFan(1000, 3);
123-
*
124-
* double[] queryPoint = new double[]{0.7, 0}; for (int degree = 0; degree <
125-
* 360; degree += 2) { for (int j = 0; j < data.length; j++) {
126-
* newForest.update(rotateClockWise(data[j], 2 * PI * degree / 360)); }
127-
* List<Neighbor> ans=newForest.getNearNeighborsInSample(queryPoint,1);
128-
* List<Neighbor>
129-
* closeNeighBors=newForest.getNearNeighborsInSample(queryPoint,0.1); Neighbor
130-
* best = null; if (ans!=null) { best = ans.get(0); for (int j = 1; j <
131-
* ans.size(); j++) { assert (ans.get(j).distance >= best.distance); } }
132-
*
133-
* // fan is away at 30, 150 and 270 if (((degree>15) && (degree<45))|| ((degree
134-
* >= 135) && (degree <= 165)) || ((degree >= 255) && (degree <= 285))) {
135-
* assertTrue(closeNeighBors.size()==0); // no close neighbor
136-
* assertTrue(best.distance>0.3); }
137-
*
138-
* // fan is overhead at 90, 210 and 330 if (((degree>75) && (degree<105))||
139-
* ((degree >= 195) && (degree <= 225)) || ((degree >= 315) && (degree <= 345)))
140-
* { assertTrue(closeNeighBors.size()>0);
141-
* assertEquals(closeNeighBors.get(0).distance,best.distance,1E-10); }
142-
*
143-
* }
144-
*
145-
* }
146-
*/
58+
59+
@Test
60+
public void movingDensity() {
61+
int newDimensions = 2;
62+
randomSeed = 123;
63+
64+
RandomCutForest newForest = RandomCutForest.builder().dimensions(newDimensions).randomSeed(randomSeed)
65+
.timeDecay(1.0 / 800).centerOfMassEnabled(true).storeSequenceIndexesEnabled(true).build();
66+
67+
double[][] data = generateFan(1000, 3);
68+
69+
double[] queryPoint = new double[] { 0.7, 0 };
70+
for (int degree = 0; degree < 360; degree += 2) {
71+
for (int j = 0; j < data.length; j++) {
72+
newForest.update(rotateClockWise(data[j], 2 * PI * degree / 360));
73+
}
74+
DensityOutput density = newForest.getSimpleDensity(queryPoint);
75+
double value = density.getDensity(0.001, 2);
76+
if ((degree <= 60) || ((degree >= 120) && (degree <= 180)) || ((degree >= 240) && (degree <= 300)))
77+
assertTrue(value < 0.8); // the fan is above at 90,210,330
78+
79+
if (((degree >= 75) && (degree <= 105)) || ((degree >= 195) && (degree <= 225))
80+
|| ((degree >= 315) && (degree <= 345)))
81+
assertTrue(value > 0.5);
82+
// fan is close by
83+
// intentionally 0.5 is below 0.8 for a robust test
84+
85+
// Testing for directionality
86+
// There can be unclear directionality when the
87+
// blades are right above
88+
89+
double bladeAboveInY = density.getDirectionalDensity(0.001, 2).low[1];
90+
double bladeBelowInY = density.getDirectionalDensity(0.001, 2).high[1];
91+
double bladesToTheLeft = density.getDirectionalDensity(0.001, 2).high[0];
92+
double bladesToTheRight = density.getDirectionalDensity(0.001, 2).low[0];
93+
94+
assertEquals(value, bladeAboveInY + bladeBelowInY + bladesToTheLeft + bladesToTheRight, 1E-6);
95+
96+
// the tests below have a freedom of 10% of the total value
97+
if (((degree >= 75) && (degree <= 85)) || ((degree >= 195) && (degree <= 205))
98+
|| ((degree >= 315) && (degree <= 325))) {
99+
assertTrue(bladeAboveInY + 0.1 * value > bladeBelowInY);
100+
assertTrue(bladeAboveInY + 0.1 * value > bladesToTheRight);
101+
}
102+
103+
if (((degree >= 95) && (degree <= 105)) || ((degree >= 215) && (degree <= 225))
104+
|| ((degree >= 335) && (degree <= 345))) {
105+
assertTrue(bladeBelowInY + 0.1 * value > bladeAboveInY);
106+
assertTrue(bladeBelowInY + 0.1 * value > bladesToTheRight);
107+
}
108+
109+
if (((degree >= 60) && (degree <= 75)) || ((degree >= 180) && (degree <= 195))
110+
|| ((degree >= 300) && (degree <= 315))) {
111+
assertTrue(bladeAboveInY + 0.1 * value > bladesToTheLeft);
112+
assertTrue(bladeAboveInY + 0.1 * value > bladesToTheRight);
113+
}
114+
115+
if (((degree >= 105) && (degree <= 120)) || ((degree >= 225) && (degree <= 240)) || (degree >= 345)) {
116+
assertTrue(bladeBelowInY + 0.1 * value > bladesToTheLeft);
117+
assertTrue(bladeBelowInY + 0.1 * value > bladesToTheRight);
118+
}
119+
120+
// fans are farthest to the left at 30,150 and 270
121+
if (((degree >= 15) && (degree <= 45)) || ((degree >= 135) && (degree <= 165))
122+
|| ((degree >= 255) && (degree <= 285))) {
123+
assertTrue(bladesToTheLeft + 0.1 * value > bladeAboveInY + bladeBelowInY + bladesToTheRight);
124+
assertTrue(bladeAboveInY + bladeBelowInY + 0.1 * value > bladesToTheRight);
125+
}
126+
127+
}
128+
129+
}
130+
131+
@Test
132+
public void movingNeighbors() {
133+
int newDimensions = 2;
134+
randomSeed = 123;
135+
136+
RandomCutForest newForest = RandomCutForest.builder().dimensions(newDimensions).randomSeed(randomSeed)
137+
.timeDecay(1.0 / 800).centerOfMassEnabled(true).storeSequenceIndexesEnabled(true).build();
138+
139+
double[][] data = generateFan(1000, 3);
140+
141+
double[] queryPoint = new double[] { 0.7, 0 };
142+
for (int degree = 0; degree < 360; degree += 2) {
143+
for (int j = 0; j < data.length; j++) {
144+
newForest.update(rotateClockWise(data[j], 2 * PI * degree / 360));
145+
}
146+
List<Neighbor> ans = newForest.getNearNeighborsInSample(queryPoint, 1);
147+
List<Neighbor> closeNeighBors = newForest.getNearNeighborsInSample(queryPoint, 0.1);
148+
Neighbor best = null;
149+
if (ans != null) {
150+
best = ans.get(0);
151+
for (int j = 1; j < ans.size(); j++) {
152+
assert (ans.get(j).distance >= best.distance);
153+
}
154+
}
155+
156+
// fan is away at 30, 150 and 270
157+
if (((degree > 15) && (degree < 45)) || ((degree >= 135) && (degree <= 165))
158+
|| ((degree >= 255) && (degree <= 285))) {
159+
assertTrue(closeNeighBors.size() == 0); // no close neighbor
160+
assertTrue(best.distance > 0.3);
161+
}
162+
163+
// fan is overhead at 90, 210 and 330
164+
if (((degree > 75) && (degree < 105)) || ((degree >= 195) && (degree <= 225))
165+
|| ((degree >= 315) && (degree <= 345))) {
166+
assertTrue(closeNeighBors.size() > 0);
167+
assertEquals(closeNeighBors.get(0).distance, best.distance, 1E-10);
168+
}
169+
170+
}
171+
172+
}
173+
147174
}

Java/examples/src/main/java/com/amazon/randomcutforest/examples/Main.java

+7-3
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@
1515

1616
package com.amazon.randomcutforest.examples;
1717

18-
import java.util.Map;
19-
import java.util.TreeMap;
20-
18+
import com.amazon.randomcutforest.examples.dynamicinference.DynamicDensity;
19+
import com.amazon.randomcutforest.examples.dynamicinference.DynamicNearNeighbor;
2120
import com.amazon.randomcutforest.examples.serialization.JsonExample;
2221
import com.amazon.randomcutforest.examples.serialization.ProtostuffExample;
2322

23+
import java.util.Map;
24+
import java.util.TreeMap;
25+
2426
public class Main {
2527

2628
public static final String ARCHIVE_NAME = "randomcutforest-examples-1.0.jar";
@@ -37,6 +39,8 @@ public Main() {
3739
maxCommandLength = 0;
3840
add(new JsonExample());
3941
add(new ProtostuffExample());
42+
add(new DynamicDensity());
43+
add(new DynamicNearNeighbor());
4044
}
4145

4246
private void add(Example example) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package com.amazon.randomcutforest.examples.dynamicinference;
17+
18+
import com.amazon.randomcutforest.RandomCutForest;
19+
import com.amazon.randomcutforest.examples.Example;
20+
import com.amazon.randomcutforest.returntypes.DensityOutput;
21+
22+
import java.io.BufferedWriter;
23+
import java.io.FileWriter;
24+
25+
import static com.amazon.randomcutforest.testutils.ExampleDataSets.generate;
26+
import static com.amazon.randomcutforest.testutils.ExampleDataSets.rotateClockWise;
27+
import static java.lang.Math.PI;
28+
29+
public class DynamicDensity implements Example {
30+
31+
public static void main(String[] args) throws Exception {
32+
new DynamicDensity().run();
33+
}
34+
35+
@Override
36+
public String command() {
37+
return "dynamic_sampling";
38+
}
39+
40+
@Override
41+
public String description() {
42+
return "shows two potential use of dynamic density computations; estimating density as well " +
43+
"as its directional components";
44+
}
45+
46+
/**
47+
* plot the dynamic_density_example using any tool in gnuplot one can plot the
48+
* directions to higher density via do for [i=0:358:2] {plot
49+
* "dynamic_density_example" index (i+1) u 1:2:3:4 w vectors t ""} or the raw
50+
* density at the points via do for [i=0:358:2] {plot "dynamic_density_example"
51+
* index i w p pt 7 palette t ""}
52+
*
53+
* @throws Exception
54+
*/
55+
@Override
56+
public void run() throws Exception {
57+
int newDimensions = 2;
58+
long randomSeed = 123;
59+
60+
RandomCutForest newForest = RandomCutForest.builder().numberOfTrees(100).sampleSize(256)
61+
.dimensions(newDimensions).randomSeed(randomSeed).timeDecay(1.0 / 800).centerOfMassEnabled(true)
62+
.build();
63+
String name = "dynamic_density_example";
64+
BufferedWriter file = new BufferedWriter(new FileWriter(name));
65+
double[][] data = generate(1000);
66+
double[] queryPoint;
67+
for (int degree = 0; degree < 360; degree += 2) {
68+
for (double[] datum : data) {
69+
newForest.update(rotateClockWise(datum, -2 * PI * degree / 360));
70+
}
71+
for (double[] datum : data) {
72+
queryPoint = rotateClockWise(datum, -2 * PI * degree / 360);
73+
DensityOutput density = newForest.getSimpleDensity(queryPoint);
74+
double value = density.getDensity(0.001, 2);
75+
file.append(queryPoint[0] + " " + queryPoint[1] + " " + value + "\n");
76+
}
77+
file.append("\n");
78+
file.append("\n");
79+
80+
for (double x = -0.95; x < 1; x += 0.1) {
81+
for (double y = -0.95; y < 1; y += 0.1) {
82+
DensityOutput density = newForest.getSimpleDensity(new double[] { x, y });
83+
double aboveInY = density.getDirectionalDensity(0.001, 2).low[1];
84+
double belowInY = density.getDirectionalDensity(0.001, 2).high[1];
85+
double toTheLeft = density.getDirectionalDensity(0.001, 2).high[0];
86+
double toTheRight = density.getDirectionalDensity(0.001, 2).low[0];
87+
double len = Math.sqrt(aboveInY * aboveInY + belowInY * belowInY + toTheLeft * toTheLeft
88+
+ toTheRight * toTheRight);
89+
file.append(x + " " + y + " " + ((toTheRight - toTheLeft) * 0.05 / len) + " "
90+
+ ((aboveInY - belowInY) * 0.05 / len) + "\n");
91+
}
92+
}
93+
file.append("\n");
94+
file.append("\n");
95+
}
96+
file.close();
97+
}
98+
}

0 commit comments

Comments
 (0)