/* --------------------------------------------------------------------- * Numenta Platform for Intelligent Computing (NuPIC) * Copyright (C) 2014, Numenta, Inc. Unless you have an agreement * with Numenta, Inc., for a separate license for this software code, the * following terms and conditions apply: * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero Public License version 3 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero Public License for more details. * * You should have received a copy of the GNU Affero Public License * along with this program. If not, see http://www.gnu.org/licenses. * * http://numenta.org/licenses/ * --------------------------------------------------------------------- */ package org.numenta.nupic.network; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.numenta.nupic.algorithms.Anomaly.KEY_MODE; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.BiFunction; import java.util.stream.Stream; import org.junit.Test; import org.numenta.nupic.Parameters; import org.numenta.nupic.Parameters.KEY; import org.numenta.nupic.algorithms.Anomaly; import org.numenta.nupic.algorithms.Anomaly.Mode; import org.numenta.nupic.algorithms.CLAClassifier; import org.numenta.nupic.algorithms.SpatialPooler; import org.numenta.nupic.algorithms.TemporalMemory; import org.numenta.nupic.datagen.ResourceLocator; import org.numenta.nupic.encoders.MultiEncoder; import org.numenta.nupic.model.Connections; import org.numenta.nupic.network.sensor.FileSensor; import org.numenta.nupic.network.sensor.HTMSensor; import org.numenta.nupic.network.sensor.ObservableSensor; import org.numenta.nupic.network.sensor.Publisher; import org.numenta.nupic.network.sensor.Sensor; import org.numenta.nupic.network.sensor.SensorParams; import org.numenta.nupic.network.sensor.SensorParams.Keys; import org.numenta.nupic.util.FastRandom; import org.numenta.nupic.util.MersenneTwister; import static org.numenta.nupic.network.NetworkTestHarness.*; import rx.Observer; import rx.Subscriber; import rx.observers.TestObserver; public class NetworkTest extends ObservableTestBase { private int[][] dayMap = new int[][] { new int[] { 1, 1, 0, 0, 0, 0, 0, 1 }, // Sunday new int[] { 1, 1, 1, 0, 0, 0, 0, 0 }, // Monday new int[] { 0, 1, 1, 1, 0, 0, 0, 0 }, // Tuesday new int[] { 0, 0, 1, 1, 1, 0, 0, 0 }, // Wednesday new int[] { 0, 0, 0, 1, 1, 1, 0, 0 }, // Thursday new int[] { 0, 0, 0, 0, 1, 1, 1, 0 }, // Friday new int[] { 0, 0, 0, 0, 0, 1, 1, 1 }, // Saturday }; private BiFunction<Inference, Integer, Integer> dayOfWeekPrintout = createDayOfWeekInferencePrintout(); @Test public void testResetMethod() { Parameters p = NetworkTestHarness.getParameters(); Network network = new Network("ResetTestNetwork", p) .add(Network.createRegion("r1") .add(Network.createLayer("l1", p).add(new TemporalMemory()))); try { network.reset(); assertTrue(network.lookup("r1").lookup("l1").hasTemporalMemory()); }catch(Exception e) { fail(); } network = new Network("ResetMethodTestNetwork", p) .add(Network.createRegion("r1") .add(Network.createLayer("l1", p).add(new SpatialPooler()))); try { network.reset(); assertFalse(network.lookup("r1").lookup("l1").hasTemporalMemory()); }catch(Exception e) { fail(); } } @Test public void testResetRecordNum() { Parameters p = NetworkTestHarness.getParameters(); Network network = new Network("ResetRecordNumNetwork", p) .add(Network.createRegion("r1") .add(Network.createLayer("l1", p).add(new TemporalMemory()))); network.observe().subscribe(new Observer<Inference>() { @Override public void onCompleted() {} @Override public void onError(Throwable e) { e.printStackTrace(); } @Override public void onNext(Inference output) { // System.out.println("output = " + Arrays.toString(output.getSDR())); } }); network.compute(new int[] { 2,3,4 }); network.compute(new int[] { 2,3,4 }); assertEquals(1, network.lookup("r1").lookup("l1").getRecordNum()); network.resetRecordNum(); assertEquals(0, network.lookup("r1").lookup("l1").getRecordNum()); } @Test public void testAdd() { Parameters p = NetworkTestHarness.getParameters(); Network network = Network.create("test", NetworkTestHarness.getParameters()); // Add Layers to regions but regions not yet added to Network Region r1 = Network.createRegion("r1").add(Network.createLayer("l", p).add(new SpatialPooler())); Region r2 = Network.createRegion("r2").add(Network.createLayer("l", p).add(new SpatialPooler())); Region r3 = Network.createRegion("r3").add(Network.createLayer("l", p).add(new SpatialPooler())); Region r4 = Network.createRegion("r4").add(Network.createLayer("l", p).add(new SpatialPooler())); Region r5 = Network.createRegion("r5").add(Network.createLayer("l", p).add(new SpatialPooler())); Region[] regions = new Region[] { r1, r2, r3, r4, r5 }; for(Region r : regions) { assertNull(network.lookup(r.getName())); } // Add the regions to the network for(Region r : regions) { network.add(r); } String[] names = new String[] { "r1","r2","r3","r4","r5" }; int i = 0; for(Region r : regions) { assertNotNull(network.lookup(r.getName())); assertEquals(names[i++], r.getName()); } } @Test public void testConnect() { Parameters p = NetworkTestHarness.getParameters(); Network network = Network.create("test", NetworkTestHarness.getParameters()); Region r1 = Network.createRegion("r1").add(Network.createLayer("l", p).add(new SpatialPooler())); Region r2 = Network.createRegion("r2").add(Network.createLayer("l", p).add(new SpatialPooler())); Region r3 = Network.createRegion("r3").add(Network.createLayer("l", p).add(new SpatialPooler())); Region r4 = Network.createRegion("r4").add(Network.createLayer("l", p).add(new SpatialPooler())); Region r5 = Network.createRegion("r5").add(Network.createLayer("l", p).add(new SpatialPooler())); try { network.connect("r1", "r2"); fail(); }catch(Exception e) { assertEquals("Region with name: r2 not added to Network.", e.getMessage()); } Region[] regions = new Region[] { r1, r2, r3, r4, r5 }; for(Region r : regions) { network.add(r); } for(int i = 1;i < regions.length;i++) { try { network.connect(regions[i - 1].getName(), regions[i].getName()); }catch(Exception e) { fail(); } } Region upstream = r1; Region tail = r1; while((tail = tail.getUpstreamRegion()) != null) { upstream = tail; } // Assert that the connect method sets the upstream region on all regions assertEquals(regions[4], upstream); Region downstream = r5; Region head = r5; while((head = head.getDownstreamRegion()) != null) { downstream = head; } // Assert that the connect method sets the upstream region on all regions assertEquals(regions[0], downstream); assertEquals(network.getHead(), downstream); } String onCompleteStr = null; @Test public void testBasicNetworkHaltGetsOnComplete() { Parameters p = NetworkTestHarness.getParameters(); p = p.union(NetworkTestHarness.getNetworkDemoTestEncoderParams()); p.set(KEY.RANDOM, new MersenneTwister(42)); p.set(KEY.INFERRED_FIELDS, getInferredFieldsMap("consumption", CLAClassifier.class)); // Create a Network Network network = Network.create("test network", p) .add(Network.createRegion("r1") .add(Network.createLayer("1", p) .alterParameter(KEY.AUTO_CLASSIFY, Boolean.TRUE) .add(Anomaly.create()) .add(new TemporalMemory()) .add(new SpatialPooler()) .add(Sensor.create(FileSensor::create, SensorParams.create( Keys::path, "", ResourceLocator.path("rec-center-hourly.csv")))))); final List<String> lines = new ArrayList<>(); // Listen to network emissions network.observe().subscribe(new Subscriber<Inference>() { @Override public void onCompleted() { onCompleteStr = "On completed reached!"; } @Override public void onError(Throwable e) { e.printStackTrace(); } @Override public void onNext(Inference i) { // System.out.println(Arrays.toString(i.getSDR())); // System.out.println(i.getRecordNum() + "," + // i.getClassifierInput().get("consumption").get("inputValue") + "," + i.getAnomalyScore()); lines.add(i.getRecordNum() + "," + i.getClassifierInput().get("consumption").get("inputValue") + "," + i.getAnomalyScore()); if(i.getRecordNum() == 9) { network.halt(); } } }); // Start the network network.start(); // Test network output try { Region r1 = network.lookup("r1"); r1.lookup("1").getLayerThread().join(); }catch(Exception e) { e.printStackTrace(); } assertEquals(10, lines.size()); int i = 0; for(String l : lines) { String[] sa = l.split("[\\s]*\\,[\\s]*"); assertEquals(3, sa.length); assertEquals(i++, Integer.parseInt(sa[0])); } assertEquals("On completed reached!", onCompleteStr); } String onCompleteStr2 = null; @Test public void testBasicNetworkHalt_ThenRestart() { Parameters p = NetworkTestHarness.getParameters(); p = p.union(NetworkTestHarness.getNetworkDemoTestEncoderParams()); p.set(KEY.RANDOM, new MersenneTwister(42)); p.set(KEY.INFERRED_FIELDS, getInferredFieldsMap("consumption", CLAClassifier.class)); // Create a Network Network network = Network.create("test network", p) .add(Network.createRegion("r1") .add(Network.createLayer("1", p) .alterParameter(KEY.AUTO_CLASSIFY, Boolean.TRUE) .add(Anomaly.create()) .add(new TemporalMemory()) .add(new SpatialPooler()) .add(Sensor.create(FileSensor::create, SensorParams.create( Keys::path, "", ResourceLocator.path("rec-center-hourly.csv")))))); final List<String> lines = new ArrayList<>(); // Listen to network emissions network.observe().subscribe(new Subscriber<Inference>() { @Override public void onCompleted() { onCompleteStr2 = "On completed reached!"; } @Override public void onError(Throwable e) { e.printStackTrace(); } @Override public void onNext(Inference i) { lines.add(i.getRecordNum() + "," + i.getClassifierInput().get("consumption").get("inputValue") + "," + i.getAnomalyScore()); if(i.getRecordNum() == 9) { network.halt(); } } }); // Start the network network.start(); // Test network output try { Region r1 = network.lookup("r1"); r1.lookup("1").getLayerThread().join(); }catch(Exception e) { e.printStackTrace(); } assertEquals(10, lines.size()); int i = 0; for(String l : lines) { String[] sa = l.split("[\\s]*\\,[\\s]*"); assertEquals(3, sa.length); assertEquals(i++, Integer.parseInt(sa[0])); System.out.println(l); } assertEquals("On completed reached!", onCompleteStr2); /////////////////////// // Now Restart // /////////////////////// onCompleteStr2 = null; // Listen to network emissions network.observe().subscribe(new Subscriber<Inference>() { @Override public void onCompleted() { onCompleteStr2 = "On completed reached!"; } @Override public void onError(Throwable e) { e.printStackTrace(); } @Override public void onNext(Inference i) { // System.out.println("second listener: " + i.getRecordNum()); lines.add(i.getRecordNum() + "," + i.getClassifierInput().get("consumption").get("inputValue") + "," + i.getAnomalyScore()); if(i.getRecordNum() == 19) { network.halt(); } } }); network.restart(); // Test network output try { Region r1 = network.lookup("r1"); r1.lookup("1").getLayerThread().join(); }catch(Exception e) { e.printStackTrace(); } assertEquals(20, lines.size()); i = 0; for(String l : lines) { String[] sa = l.split("[\\s]*\\,[\\s]*"); assertEquals(3, sa.length); assertEquals(i++, Integer.parseInt(sa[0])); System.out.println(l); } assertEquals("On completed reached!", onCompleteStr2); } boolean expectedDataFlag = true; String failMessage; @Test public void testBasicNetworkHalt_ThenRestart_TighterExpectation() { final int NUM_CYCLES = 600; final int INPUT_GROUP_COUNT = 7; // Days of Week /////////////////////////////////////// // Run until CYCLE 284, then halt // /////////////////////////////////////// Network network = getLoadedDayOfWeekNetwork(); int cellsPerCol = (int)network.getParameters().get(KEY.CELLS_PER_COLUMN); network.observe().subscribe(new Observer<Inference>() { @Override public void onCompleted() {} @Override public void onError(Throwable e) { e.printStackTrace(); } @Override public void onNext(Inference inf) { /** see {@link #createDayOfWeekInferencePrintout()} */ int cycle = dayOfWeekPrintout.apply(inf, cellsPerCol); if(cycle == 284) { System.out.println("halting publisher = " + network.getPublisher()); network.halt(); } } }); Publisher pub = network.getPublisher(); network.start(); int cycleCount = 0; for(;cycleCount < NUM_CYCLES;cycleCount++) { for(double j = 0;j < INPUT_GROUP_COUNT;j++) { pub.onNext("" + j); } network.reset(); if(cycleCount == 284) { break; } } // Test network output try { Region r1 = network.lookup("r1"); r1.lookup("1").getLayerThread().join(2000); }catch(Exception e) { e.printStackTrace(); } // Announce new start System.out.println("\n\n\n Network Restart \n\n\n"); /////////////////////// // Now Restart // /////////////////////// // 1. Re-Attach Observer // 2. Restart Network network.observe().subscribe(new Observer<Inference>() { @Override public void onCompleted() {} @Override public void onError(Throwable e) { e.printStackTrace(); } @Override public void onNext(Inference inf) { /** see {@link #createDayOfWeekInferencePrintout()} */ dayOfWeekPrintout.apply(inf, cellsPerCol); //////////////////////////////////////////////////////////// // Ensure the records pick up precisely where we left off // //////////////////////////////////////////////////////////// if(inf.getRecordNum() == 1975) { expectedDataFlag = true; } } }); network.halt(); try { network.lookup("r1").lookup("1").getLayerThread().join(3000); // Add a little more wait time Thread.sleep(3000); }catch(Exception e) { e.printStackTrace(); } network.restart(); Publisher newPub = network.getPublisher(); // Assert that we have a new Publisher being created in the background upon restart() assertFalse(pub == newPub); for(;cycleCount < NUM_CYCLES;cycleCount++) { for(double j = 0;j < INPUT_GROUP_COUNT;j++) { newPub.onNext("" + j); } network.reset(); } newPub.onComplete(); try { Region r1 = network.lookup("r1"); r1.lookup("1").getLayerThread().join(); }catch(Exception e) { e.printStackTrace(); } if(!expectedDataFlag) { fail(failMessage); } } @Test public void testBasicNetworkRunAWhileThenHalt() { onCompleteStr = null; Parameters p = NetworkTestHarness.getParameters(); p = p.union(NetworkTestHarness.getNetworkDemoTestEncoderParams()); p.set(KEY.RANDOM, new MersenneTwister(42)); p.set(KEY.INFERRED_FIELDS, getInferredFieldsMap("consumption", CLAClassifier.class)); // Create a Network Network network = Network.create("test network", p) .add(Network.createRegion("r1") .add(Network.createLayer("1", p) .alterParameter(KEY.AUTO_CLASSIFY, Boolean.TRUE) .add(Anomaly.create()) .add(new TemporalMemory()) .add(new SpatialPooler()) .add(Sensor.create(FileSensor::create, SensorParams.create( Keys::path, "", ResourceLocator.path("rec-center-hourly.csv")))))); final List<String> lines = new ArrayList<>(); // Listen to network emissions network.observe().subscribe(new Subscriber<Inference>() { @Override public void onCompleted() { onCompleteStr = "On completed reached!"; } @Override public void onError(Throwable e) { e.printStackTrace(); } @Override public void onNext(Inference i) { // System.out.println(Arrays.toString(i.getSDR())); // System.out.println(i.getRecordNum() + "," + // i.getClassifierInput().get("consumption").get("inputValue") + "," + i.getAnomalyScore()); lines.add(i.getRecordNum() + "," + i.getClassifierInput().get("consumption").get("inputValue") + "," + i.getAnomalyScore()); if(i.getRecordNum() == 1000) { network.halt(); } } }); // Start the network network.start(); // Test network output try { Region r1 = network.lookup("r1"); r1.lookup("1").getLayerThread().join(); }catch(Exception e) { e.printStackTrace(); } assertEquals(1001, lines.size()); int i = 0; for(String l : lines) { String[] sa = l.split("[\\s]*\\,[\\s]*"); assertEquals(3, sa.length); assertEquals(i++, Integer.parseInt(sa[0])); } assertEquals("On completed reached!", onCompleteStr); } ManualInput netInference = null; ManualInput topInference = null; ManualInput bottomInference = null; @Test public void testRegionHierarchies() { Parameters p = NetworkTestHarness.getParameters(); p.setPotentialRadius(16); p = p.union(NetworkTestHarness.getNetworkDemoTestEncoderParams()); p.set(KEY.RANDOM, new MersenneTwister(42)); p.set(KEY.INFERRED_FIELDS, getInferredFieldsMap("consumption", CLAClassifier.class)); Network network = Network.create("test network", p) .add(Network.createRegion("r1") .add(Network.createLayer("2", p) .add(Anomaly.create()) .add(new TemporalMemory()) .add(new SpatialPooler()))) .add(Network.createRegion("r2") .add(Network.createLayer("1", p) .alterParameter(KEY.AUTO_CLASSIFY, Boolean.TRUE) .add(new TemporalMemory()) .add(new SpatialPooler()) .add(Sensor.create(FileSensor::create, SensorParams.create( Keys::path, "", ResourceLocator.path("rec-center-hourly.csv")))))) .connect("r1", "r2"); Region r1 = network.lookup("r1"); Region r2 = network.lookup("r2"); network.observe().subscribe(new Subscriber<Inference>() { @Override public void onCompleted() {} @Override public void onError(Throwable e) { e.printStackTrace(); } @Override public void onNext(Inference i) { netInference = (ManualInput)i; if(r1.getHead().getInference().getPredictiveCells().size() > 0 && r2.getHead().getInference().getPredictiveCells().size() > 0) { network.halt(); } } }); r1.observe().subscribe(new Subscriber<Inference>() { @Override public void onCompleted() {} @Override public void onError(Throwable e) { e.printStackTrace(); } @Override public void onNext(Inference i) { topInference = (ManualInput)i; } }); r2.observe().subscribe(new Subscriber<Inference>() { @Override public void onCompleted() {} @Override public void onError(Throwable e) { e.printStackTrace(); } @Override public void onNext(Inference i) { bottomInference = (ManualInput)i; } }); network.start(); // Let run for 5 secs. try { r2.lookup("1").getLayerThread().join();//5000); // System.out.println("top ff = " + Arrays.toString(topInference.getFeedForwardSparseActives())); // System.out.println("bot ff = " + Arrays.toString(bottomInference.getFeedForwardSparseActives())); // System.out.println("top pred = " + topInference.getPredictiveCells()); // System.out.println("bot pred = " + bottomInference.getPredictiveCells()); // System.out.println("top active = " + topInference.getActiveCells()); // System.out.println("bot active = " + bottomInference.getActiveCells()); assertTrue(!topInference.getPredictiveCells().equals(bottomInference.getPredictiveCells())); assertTrue(topInference.getPredictiveCells().size() > 0); assertTrue(bottomInference.getPredictiveCells().size() > 0); }catch(Exception e) { e.printStackTrace(); } } /** * Test that a null {@link Assembly.Mode} results in exception */ @Test public void testFluentBuildSemantics() { Parameters p = NetworkTestHarness.getParameters(); p = p.union(NetworkTestHarness.getNetworkDemoTestEncoderParams()); p.set(KEY.RANDOM, new MersenneTwister(42)); Map<String, Object> anomalyParams = new HashMap<>(); anomalyParams.put(KEY_MODE, Mode.LIKELIHOOD); try { // Idea: Build up ResourceLocator paths in fluent style such as: // Layer.using( // ResourceLocator.addPath("...") // Adds a search path for later mentioning terminal resources (i.e. files) // .addPath("...") // .addPath("...")) // .add(new SpatialPooler()) // ... Network.create("test network", p) // Add Network.add() method for chaining region adds .add(Network.createRegion("r1") // Add version of createRegion(String name) for later connecting by name .add(Network.createLayer("2/3", p) // so that regions can be added and connecting in one long chain. .using(new Connections()) // Test adding connections before elements which use them .add(Sensor.create(FileSensor::create, SensorParams.create( Keys::path, "", ResourceLocator.path("rec-center-hourly.csv")))) .add(new SpatialPooler()) .add(new TemporalMemory()) .add(Anomaly.create(anomalyParams)) ) .add(Network.createLayer("1", p) // Add another Layer, and the Region internally connects it to the .add(new SpatialPooler()) // previously added Layer .using(new Connections()) // Test adding connections after one element and before another .add(new TemporalMemory()) .add(Anomaly.create(anomalyParams)) )) .add(Network.createRegion("r2") .add(Network.createLayer("2/3", p) .add(new SpatialPooler()) .using(new Connections()) // Test adding connections after one element and before another .add(new TemporalMemory()) .add(Anomaly.create(anomalyParams)) )) .add(Network.createRegion("r3") .add(Network.createLayer("1", p) .add(new SpatialPooler()) .add(new TemporalMemory()) .add(Anomaly.create(anomalyParams)) .using(new Connections()) // Test adding connections after elements which use them. )) .connect("r1", "r2") .connect("r2", "r3"); }catch(Exception e) { e.printStackTrace(); } } @Test public void testNetworkComputeWithNoSensor() { Parameters p = NetworkTestHarness.getParameters(); p = p.union(NetworkTestHarness.getDayDemoTestEncoderParams()); p.set(KEY.GLOBAL_INHIBITION, true); p.set(KEY.COLUMN_DIMENSIONS, new int[] { 30 }); p.set(KEY.SYN_PERM_INACTIVE_DEC, 0.008); p.set(KEY.SYN_PERM_ACTIVE_INC, 0.1); p.set(KEY.SYN_PERM_TRIM_THRESHOLD, 0.05); p.set(KEY.SYN_PERM_CONNECTED, 0.1); p.set(KEY.PERMANENCE_INCREMENT, 0.10); p.set(KEY.PERMANENCE_DECREMENT, 0.10); p.set(KEY.MAX_BOOST, 1.0); p.set(KEY.DUTY_CYCLE_PERIOD, 7); p.set(KEY.RANDOM, new MersenneTwister(42)); p.set(KEY.INFERRED_FIELDS, getInferredFieldsMap("dayOfWeek", CLAClassifier.class)); Map<String, Object> params = new HashMap<>(); params.put(KEY_MODE, Mode.PURE); Network n = Network.create("test network", p) .add(Network.createRegion("r1") .add(Network.createLayer("1", p) .alterParameter(KEY.AUTO_CLASSIFY, Boolean.TRUE)) .add(Network.createLayer("2", p) .add(Anomaly.create(params))) .add(Network.createLayer("3", p) .add(new TemporalMemory())) .add(Network.createLayer("4", p) .add(new SpatialPooler()) .add(MultiEncoder.builder().name("").build())) .connect("1", "2") .connect("2", "3") .connect("3", "4")); Region r1 = n.lookup("r1"); r1.lookup("3").using(r1.lookup("4").getConnections()); // How to share Connections object between Layers r1.observe().subscribe(new Subscriber<Inference>() { @Override public void onCompleted() {} @Override public void onError(Throwable e) { e.printStackTrace(); } @Override public void onNext(Inference i) { // UNCOMMENT TO VIEW STABILIZATION OF PREDICTED FIELDS // Set<Cell> prevPred = i.getPreviousPredictiveCells(); // if(prevPred == null) { // prevPred = Collections.emptySet(); // } // System.out.println("Day: " + r1.getInput() + " - predictions: " + Arrays.toString(SDR.cellsAsColumnIndices(prevPred, 6)) + // " - " + Arrays.toString(i.getFeedForwardSparseActives()) + " - " + // ((int)Math.rint(((Number)i.getClassification("dayOfWeek").getMostProbableValue(1)).doubleValue()))); } }); final int NUM_CYCLES = 400; final int INPUT_GROUP_COUNT = 7; // Days of Week Map<String, Object> multiInput = new HashMap<>(); for(int i = 0;i < NUM_CYCLES;i++) { for(double j = 0;j < INPUT_GROUP_COUNT;j++) { multiInput.put("dayOfWeek", j); r1.compute(multiInput); } n.reset(); } // Test that we get proper output after prediction stabilization TestObserver<Inference> tester; r1.observe().subscribe(tester = new TestObserver<Inference>() { @Override public void onCompleted() {} @Override public void onNext(Inference i) { int nextDay = ((int)Math.rint(((Number)i.getClassification("dayOfWeek").getMostProbableValue(1)).doubleValue())); assertEquals(6, nextDay); } }); multiInput.put("dayOfWeek", 5.0); n.compute(multiInput); // Check for exception during the TestObserver's onNext() execution. checkObserver(tester); } @Test public void testSynchronousBlockingComputeCall() { Parameters p = NetworkTestHarness.getParameters(); p = p.union(NetworkTestHarness.getDayDemoTestEncoderParams()); p.set(KEY.COLUMN_DIMENSIONS, new int[] { 30 }); p.set(KEY.SYN_PERM_INACTIVE_DEC, 0.1); p.set(KEY.SYN_PERM_ACTIVE_INC, 0.1); p.set(KEY.SYN_PERM_TRIM_THRESHOLD, 0.05); p.set(KEY.SYN_PERM_CONNECTED, 0.4); p.set(KEY.MAX_BOOST, 10.0); p.set(KEY.DUTY_CYCLE_PERIOD, 7); p.set(KEY.RANDOM, new MersenneTwister(42)); p.set(KEY.INFERRED_FIELDS, getInferredFieldsMap("dayOfWeek", CLAClassifier.class)); Map<String, Object> params = new HashMap<>(); params.put(KEY_MODE, Mode.PURE); Network n = Network.create("test network", p) .add(Network.createRegion("r1") .add(Network.createLayer("1", p) .alterParameter(KEY.AUTO_CLASSIFY, Boolean.TRUE) .add(new TemporalMemory()) .add(new SpatialPooler()) .add(MultiEncoder.builder().name("").build()))); boolean gotResult = false; final int NUM_CYCLES = 400; final int INPUT_GROUP_COUNT = 7; // Days of Week Map<String, Object> multiInput = new HashMap<>(); for(int i = 0;i < NUM_CYCLES;i++) { for(double j = 0;j < INPUT_GROUP_COUNT;j++) { multiInput.put("dayOfWeek", j); Inference inf = n.computeImmediate(multiInput); if(inf.getPredictiveCells().size() > 6) { assertTrue(inf.getPredictiveCells() != null); // Make sure we've gotten all the responses assertEquals((i * 7) + (int)j, inf.getRecordNum()); gotResult = true; break; } } if(gotResult) { break; } } assertTrue(gotResult); } @Test public void testThreadedStartFlagging() { Parameters p = NetworkTestHarness.getParameters(); p = p.union(NetworkTestHarness.getDayDemoTestEncoderParams()); p.set(KEY.COLUMN_DIMENSIONS, new int[] { 30 }); p.set(KEY.SYN_PERM_INACTIVE_DEC, 0.1); p.set(KEY.SYN_PERM_ACTIVE_INC, 0.1); p.set(KEY.SYN_PERM_TRIM_THRESHOLD, 0.05); p.set(KEY.SYN_PERM_CONNECTED, 0.4); p.set(KEY.MAX_BOOST, 10.0); p.set(KEY.DUTY_CYCLE_PERIOD, 7); p.set(KEY.RANDOM, new MersenneTwister(42)); p.set(KEY.INFERRED_FIELDS, getInferredFieldsMap("consumption", CLAClassifier.class)); Map<String, Object> params = new HashMap<>(); params.put(KEY_MODE, Mode.PURE); Network n = Network.create("test network", p) .add(Network.createRegion("r1") .add(Network.createLayer("1", p) .alterParameter(KEY.AUTO_CLASSIFY, Boolean.TRUE)) .add(Network.createLayer("2", p) .add(Anomaly.create(params))) .add(Network.createLayer("3", p) .add(new TemporalMemory())) .add(Network.createLayer("4", p) .add(new SpatialPooler()) .add(MultiEncoder.builder().name("").build())) .connect("1", "2") .connect("2", "3") .connect("3", "4")); assertFalse(n.isThreadedOperation()); n.start(); assertFalse(n.isThreadedOperation()); ////////////////////////////////////////////////////// // Add a Sensor which should allow Network to start // ////////////////////////////////////////////////////// p = NetworkTestHarness.getParameters(); p = p.union(NetworkTestHarness.getNetworkDemoTestEncoderParams()); p.set(KEY.INFERRED_FIELDS, getInferredFieldsMap("consumption", CLAClassifier.class)); n = Network.create("test network", p) .add(Network.createRegion("r1") .add(Network.createLayer("1", p) .alterParameter(KEY.AUTO_CLASSIFY, Boolean.TRUE)) .add(Network.createLayer("2", p) .add(Anomaly.create(params))) .add(Network.createLayer("3", p) .add(new TemporalMemory())) .add(Network.createLayer("4", p) .add(new SpatialPooler()) .add(Sensor.create(FileSensor::create, SensorParams.create( Keys::path, "", ResourceLocator.path("rec-center-hourly.csv"))))) .connect("1", "2") .connect("2", "3") .connect("3", "4")); assertFalse(n.isThreadedOperation()); n.start(); assertTrue(n.isThreadedOperation()); try { p = NetworkTestHarness.getParameters(); p = p.union(NetworkTestHarness.getNetworkDemoTestEncoderParams()); p.set(KEY.INFERRED_FIELDS, getInferredFieldsMap("consumption", CLAClassifier.class)); n = Network.create("test network", p) .add(Network.createRegion("r1") .add(Network.createLayer("1", p) .alterParameter(KEY.AUTO_CLASSIFY, Boolean.TRUE) .add(new TemporalMemory()) .add(new SpatialPooler()) .add(Sensor.create(FileSensor::create, SensorParams.create( Keys::path, "", ResourceLocator.path("rec-center-hourly.csv")))))); n.start(); n.computeImmediate(new HashMap<String, Object>()); // SHOULD FAIL HERE WITH EXPECTED EXCEPTION fail(); }catch(Exception e) { assertEquals("Cannot call computeImmediate() when Network has been started.", e.getMessage()); } } double anomaly = 1; boolean completed = false; @Test public void testObservableWithCoordinateEncoder() { Publisher manual = Publisher.builder() .addHeader("timestamp,consumption,location") .addHeader("datetime,float,geo") .addHeader("T,,").build(); Sensor<ObservableSensor<String[]>> sensor = Sensor.create( ObservableSensor::create, SensorParams.create(Keys::obs, "", manual)); Parameters p = NetworkTestHarness.getParameters().copy(); p = p.union(NetworkTestHarness.getGeospatialTestEncoderParams()); p.set(KEY.RANDOM, new MersenneTwister(42)); HTMSensor<ObservableSensor<String[]>> htmSensor = (HTMSensor<ObservableSensor<String[]>>)sensor; Network network = Network.create("test network", p) .add(Network.createRegion("r1") .add(Network.createLayer("1", p) .add(Anomaly.create()) .add(new TemporalMemory()) .add(new SpatialPooler()) .add(htmSensor))); network.start(); network.observe().subscribe(new Observer<Inference>() { @Override public void onCompleted() { assertEquals(0, anomaly, 0); completed = true; } @Override public void onError(Throwable e) { e.printStackTrace(); } @Override public void onNext(Inference output) { //System.out.println(output.getRecordNum() + ": input = " + Arrays.toString(output.getEncoding()));//output = " + Arrays.toString(output.getSDR()) + ", " + output.getAnomalyScore()); if(output.getAnomalyScore() < anomaly) { anomaly = output.getAnomalyScore(); // System.out.println("anomaly = " + anomaly); } } }); int x = 0; for(int i = 0;i < 100;i++) { x = i % 10; manual.onNext("7/12/10 13:10,35.3,40.6457;-73.7" + x + "692;" + x); //5 = meters per second } manual.onComplete(); Layer<?> l = network.lookup("r1").lookup("1"); try { l.getLayerThread().join(); }catch(Exception e) { e.printStackTrace(); } assertTrue(completed); } String errorMessage = null; @Test public void testObservableWithCoordinateEncoder_NEGATIVE() { Publisher manual = Publisher.builder() .addHeader("timestamp,consumption,location") .addHeader("datetime,float,geo") .addHeader("T,,").build(); Sensor<ObservableSensor<String[]>> sensor = Sensor.create( ObservableSensor::create, SensorParams.create(Keys::obs, "", manual)); Parameters p = NetworkTestHarness.getParameters().copy(); p = p.union(NetworkTestHarness.getGeospatialTestEncoderParams()); p.set(KEY.RANDOM, new MersenneTwister(42)); p.set(KEY.INFERRED_FIELDS, getInferredFieldsMap("", CLAClassifier.class)); HTMSensor<ObservableSensor<String[]>> htmSensor = (HTMSensor<ObservableSensor<String[]>>)sensor; Network network = Network.create("test network", p) .add(Network.createRegion("r1") .add(Network.createLayer("1", p) .alterParameter(KEY.AUTO_CLASSIFY, Boolean.TRUE) .add(Anomaly.create()) .add(new TemporalMemory()) .add(new SpatialPooler()) .add(htmSensor))); TestObserver<Inference> tester; network.observe().subscribe(tester = new TestObserver<Inference>() { @Override public void onCompleted() { //Should never happen here. assertEquals(0, anomaly, 0); completed = true; super.onCompleted(); } @Override public void onError(Throwable e) { super.onError(e); errorMessage = e.getMessage(); network.halt(); } @Override public void onNext(Inference output) {} }); network.start(); int x = 0; for(int i = 0;i < 100;i++) { x = i % 10; manual.onNext("7/12/10 13:10,35.3,40.6457;-73.7" + x + "692;" + x); //1st "x" is attempt to vary coords, 2nd "x" = meters per second } manual.onComplete(); Layer<?> l = network.lookup("r1").lookup("1"); try { l.getLayerThread().join(); }catch(Exception e) { assertEquals(InterruptedException.class, e.getClass()); } // Assert onNext condition never gets set assertFalse(completed); assertEquals("Cannot autoclassify with raw array input or " + "Coordinate based encoders... Remove auto classify setting.", errorMessage); assertTrue(hasErrors(tester)); } @Test public void testPotentialRadiusFollowsInputWidth() { Parameters p = NetworkTestHarness.getParameters(); p = p.union(NetworkTestHarness.getNetworkDemoTestEncoderParams()); p.set(KEY.INPUT_DIMENSIONS, new int[] { 200 }); p.set(KEY.RANDOM, new MersenneTwister(42)); Network network = Network.create("test network", p) .add(Network.createRegion("r1") .add(Network.createLayer("2", p) .add(Anomaly.create()) .add(new TemporalMemory()) .add(new SpatialPooler()) .close())); Region r1 = network.lookup("r1"); Layer<?> layer2 = r1.lookup("2"); int width = layer2.calculateInputWidth(); assertEquals(200, width); assertEquals(200, layer2.getConnections().getPotentialRadius()); } /////////////////////////////////////////////////////////////////////////////////// // Tests of Calculate Input Width for inter-regional and inter-layer calcs // /////////////////////////////////////////////////////////////////////////////////// @Test public void testCalculateInputWidth_NoPrevLayer_UpstreamRegion_with_TM() { Parameters p = NetworkTestHarness.getParameters(); p = p.union(NetworkTestHarness.getNetworkDemoTestEncoderParams()); p.set(KEY.RANDOM, new MersenneTwister(42)); p.set(KEY.INFERRED_FIELDS, getInferredFieldsMap("consumption", CLAClassifier.class)); Network network = Network.create("test network", p) .add(Network.createRegion("r1") .add(Network.createLayer("2", p) .add(Anomaly.create()) .add(new TemporalMemory()) .add(new SpatialPooler()))) .add(Network.createRegion("r2") .add(Network.createLayer("1", p) .alterParameter(KEY.AUTO_CLASSIFY, Boolean.TRUE) .add(new TemporalMemory()) .add(new SpatialPooler()) .add(Sensor.create(FileSensor::create, SensorParams.create( Keys::path, "", ResourceLocator.path("rec-center-hourly.csv")))))) .connect("r1", "r2"); Region r1 = network.lookup("r1"); Layer<?> layer2 = r1.lookup("2"); int width = layer2.calculateInputWidth(); assertEquals(65536, width); } @Test public void testCalculateInputWidth_NoPrevLayer_UpstreamRegion_without_TM() { Parameters p = NetworkTestHarness.getParameters(); p = p.union(NetworkTestHarness.getNetworkDemoTestEncoderParams()); p.set(KEY.RANDOM, new MersenneTwister(42)); p.set(KEY.INFERRED_FIELDS, getInferredFieldsMap("consumption", CLAClassifier.class)); Network network = Network.create("test network", p) .add(Network.createRegion("r1") .add(Network.createLayer("2", p) .add(Anomaly.create()) .add(new TemporalMemory()) .add(new SpatialPooler()))) .add(Network.createRegion("r2") .add(Network.createLayer("1", p) .alterParameter(KEY.AUTO_CLASSIFY, Boolean.TRUE) .add(new SpatialPooler()) .add(Sensor.create(FileSensor::create, SensorParams.create( Keys::path, "", ResourceLocator.path("rec-center-hourly.csv")))))) .connect("r1", "r2"); Region r1 = network.lookup("r1"); Layer<?> layer2 = r1.lookup("2"); int width = layer2.calculateInputWidth(); assertEquals(2048, width); } @Test public void testCalculateInputWidth_NoPrevLayer_NoPrevRegion_andTM() { Parameters p = NetworkTestHarness.getParameters(); p = p.union(NetworkTestHarness.getNetworkDemoTestEncoderParams()); p.set(KEY.RANDOM, new MersenneTwister(42)); Network network = Network.create("test network", p) .add(Network.createRegion("r1") .add(Network.createLayer("2", p) .add(Anomaly.create()) .add(new TemporalMemory()) .close())); Region r1 = network.lookup("r1"); Layer<?> layer2 = r1.lookup("2"); int width = layer2.calculateInputWidth(); assertEquals(65536, width); } @Test public void testCalculateInputWidth_NoPrevLayer_NoPrevRegion_andSPTM() { Parameters p = NetworkTestHarness.getParameters(); p = p.union(NetworkTestHarness.getNetworkDemoTestEncoderParams()); p.set(KEY.RANDOM, new MersenneTwister(42)); Network network = Network.create("test network", p) .add(Network.createRegion("r1") .add(Network.createLayer("2", p) .add(Anomaly.create()) .add(new TemporalMemory()) .add(new SpatialPooler()) .close())); Region r1 = network.lookup("r1"); Layer<?> layer2 = r1.lookup("2"); int width = layer2.calculateInputWidth(); assertEquals(8, width); assertEquals(8, layer2.getConnections().getPotentialRadius()); } @Test public void testCalculateInputWidth_NoPrevLayer_NoPrevRegion_andNoTM() { Parameters p = NetworkTestHarness.getParameters(); p = p.union(NetworkTestHarness.getNetworkDemoTestEncoderParams()); p.set(KEY.RANDOM, new MersenneTwister(42)); Network network = Network.create("test network", p) .add(Network.createRegion("r1") .add(Network.createLayer("2", p) .add(Anomaly.create()) .add(new SpatialPooler()) .close())); Region r1 = network.lookup("r1"); Layer<?> layer2 = r1.lookup("2"); int width = layer2.calculateInputWidth(); assertEquals(8, width); assertEquals(8, layer2.getConnections().getPotentialRadius()); } @Test public void testCalculateInputWidth_WithPrevLayer_WithTM() { Parameters p = NetworkTestHarness.getParameters(); p = p.union(NetworkTestHarness.getNetworkDemoTestEncoderParams()); p.set(KEY.RANDOM, new MersenneTwister(42)); Network network = Network.create("test network", p) .add(Network.createRegion("r1") .add(Network.createLayer("1", p) .add(Anomaly.create()) .add(new SpatialPooler())) .add(Network.createLayer("2", p) .add(Anomaly.create()) .add(new TemporalMemory()) .add(new SpatialPooler())) .connect("1", "2")); Region r1 = network.lookup("r1"); Layer<?> layer1 = r1.lookup("1"); int width = layer1.calculateInputWidth(); assertEquals(65536, width); } @Test public void testCalculateInputWidth_WithPrevLayer_NoTM() { Parameters p = NetworkTestHarness.getParameters(); p = p.union(NetworkTestHarness.getNetworkDemoTestEncoderParams()); p.set(KEY.RANDOM, new MersenneTwister(42)); Network network = Network.create("test network", p) .add(Network.createRegion("r1") .add(Network.createLayer("1", p) .add(Anomaly.create()) .add(new SpatialPooler())) .add(Network.createLayer("2", p) .add(new SpatialPooler())) .connect("1", "2")); Region r1 = network.lookup("r1"); Layer<?> layer1 = r1.lookup("1"); int width = layer1.calculateInputWidth(); assertEquals(2048, width); } @Test public void closeTest() { Parameters p = NetworkTestHarness.getParameters(); p = p.union(NetworkTestHarness.getNetworkDemoTestEncoderParams()); p.set(KEY.RANDOM, new MersenneTwister(42)); Region region1 = Network.createRegion("region1"); Layer<?> layer1 = Network.createLayer("layer1", p); region1.add(layer1); Region region2 = Network.createRegion("region2"); Layer<?> layer2 = Network.createLayer("layer2", p); region2.add(layer2); Network network = Network.create("test network", p); // Calling close on an empty Network should not throw any Exceptions network.close(); // Calling close on a Network with a single unclosed Region network.add(region1); network.close(); assertTrue("Region 1 did not close, after closing Network", region1.isClosed()); assertTrue("Layer 1 did not close, after closing Network", layer1.isClosed()); // Calling close on a Network with two regions, one of which is closed network.add(region2); network.close(); assertTrue("Region 1 did not close, after closing Network with 2 Regions", region1.isClosed()); assertTrue("Layer 1 did not close, after closing Network with 2 Regions", layer1.isClosed()); assertTrue("Region 2 did not close, after closing Network with 2 Regions", region2.isClosed()); assertTrue("Layer 2 did not close, after closing Network with 2 Regions", layer2.isClosed()); } @Test public void testLearn() { Region region = Network.createRegion("Region 1"); Layer<?> layer = Network.createLayer("Layer 2/3", Parameters.getAllDefaultParameters()); Network network = Network.create("Network 1", Parameters.getAllDefaultParameters()); region.add(layer); network.add(region); // Close must be called to have this work region.close(); network.setLearn(true); assertTrue(network.isLearn()); //true assertTrue(region.isLearn()); //true assertTrue(layer.isLearn()); //true network.setLearn(false); assertFalse(network.isLearn()); //false assertFalse(region.isLearn()); //false assertFalse(layer.isLearn()); } //////////////////////////////////////// // Utility Methods // //////////////////////////////////////// Publisher pub = null; private Network getLoadedDayOfWeekNetwork() { Parameters p = NetworkTestHarness.getParameters().copy(); p = p.union(NetworkTestHarness.getDayDemoTestEncoderParams()); p.set(KEY.RANDOM, new FastRandom(42)); p.set(KEY.INFERRED_FIELDS, getInferredFieldsMap("dayOfWeek", CLAClassifier.class)); Sensor<ObservableSensor<String[]>> sensor = Sensor.create( ObservableSensor::create, SensorParams.create(Keys::obs, new Object[] {"name", PublisherSupplier.builder() .addHeader("dayOfWeek") .addHeader("number") .addHeader("B").build() })); Network network = Network.create("test network", p).add(Network.createRegion("r1") .add(Network.createLayer("1", p) .alterParameter(KEY.AUTO_CLASSIFY, true) .add(Anomaly.create()) .add(new TemporalMemory()) .add(new SpatialPooler()) .add(sensor))); return network; } private BiFunction<Inference, Integer, Integer> createDayOfWeekInferencePrintout() { return new BiFunction<Inference, Integer, Integer>() { private int cycles = 1; public Integer apply(Inference inf, Integer cellsPerColumn) { // Classification<Object> result = inf.getClassification("dayOfWeek"); double day = mapToInputData((int[])inf.getLayerInput()); if(day == 1.0) { // System.out.println("\n========================="); // System.out.println("CYCLE: " + cycles); cycles++; } // System.out.println("RECORD_NUM: " + inf.getRecordNum()); // System.out.println("ScalarEncoder Input = " + day); // System.out.println("ScalarEncoder Output = " + Arrays.toString(inf.getEncoding())); // System.out.println("SpatialPooler Output = " + Arrays.toString(inf.getFeedForwardActiveColumns())); // // if(inf.getPreviousPredictiveCells() != null) // System.out.println("TemporalMemory Previous Prediction = " + // Arrays.toString(SDR.cellsAsColumnIndices(inf.getPreviousPredictiveCells(), cellsPerColumn))); // // System.out.println("TemporalMemory Actives = " + Arrays.toString(SDR.asColumnIndices(inf.getSDR(), cellsPerColumn))); // // System.out.print("CLAClassifier prediction = " + // stringValue((Double)result.getMostProbableValue(1)) + " --> " + ((Double)result.getMostProbableValue(1))); // // System.out.println(" | CLAClassifier 1 step prob = " + Arrays.toString(result.getStats(1)) + "\n"); return cycles; } }; } private double mapToInputData(int[] encoding) { for(int i = 0;i < dayMap.length;i++) { if(Arrays.equals(encoding, dayMap[i])) { return i + 1; } } return -1; } public Stream<String> makeStream() { return Stream.of( "7/2/10 0:00,21.2", "7/2/10 1:00,16.4", "7/2/10 2:00,4.7", "7/2/10 3:00,4.7", "7/2/10 4:00,4.6", "7/2/10 5:00,23.5", "7/2/10 6:00,47.5", "7/2/10 7:00,45.4", "7/2/10 8:00,46.1", "7/2/10 9:00,41.5", "7/2/10 10:00,43.4", "7/2/10 11:00,43.8", "7/2/10 12:00,37.8", "7/2/10 13:00,36.6", "7/2/10 14:00,35.7", "7/2/10 15:00,38.9", "7/2/10 16:00,36.2", "7/2/10 17:00,36.6", "7/2/10 18:00,37.2", "7/2/10 19:00,38.2", "7/2/10 20:00,14.1"); } }