/* --------------------------------------------------------------------- * 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.datagen; import gnu.trove.list.TIntList; import gnu.trove.list.array.TIntArrayList; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import org.numenta.nupic.util.ArrayUtils; import org.numenta.nupic.util.Tuple; /** * Utilities for generating and manipulating sequences, for use in * experimentation and tests. * * @author David Ray */ public class SequenceMachine { private PatternMachine patternMachine; /** * Represents the end of a pattern or sequence when inserted in * a {@link Collection}, otherwise the primitive form of "None" * is -1 */ public static final Set<Integer> NONE = new HashSet<Integer>() { private static final long serialVersionUID = 1L; public String toString() { return "None"; } }; /** * Constructs a new {@code SequenceMachine} * @param pMachine */ public SequenceMachine(PatternMachine pMachine) { this.patternMachine = pMachine; } /** * Generates a series of sequences which may optionally contain shared ranges. * * @param numSequences * @param sequenceLength * @param sharedRange * @return */ public List<Integer> generateNumbers(int numSequences, int sequenceLength, Tuple sharedRange) { List<Integer> numbers = new ArrayList<>(); TIntList sharedNumbers = null; int sharedStart = 0; int sharedEnd = 0; if(sharedRange != null && sharedRange.size() == 2) { int sharedLength = (sharedEnd = (int)sharedRange.get(1)) - (sharedStart = (int)sharedRange.get(0)); sharedNumbers = new TIntArrayList(ArrayUtils.xrange( numSequences * sequenceLength, numSequences * sequenceLength + sharedLength, 1)); } for(int i = 0;i < numSequences;i++) { int start = i * sequenceLength; int[] newNumbers = ArrayUtils.xrange(start, start + sequenceLength, 1); ArrayUtils.shuffle(newNumbers); if(sharedRange != null) { ArrayUtils.replace(sharedStart, sharedEnd, newNumbers, sharedNumbers.toArray()); } numbers.addAll(Arrays.asList(ArrayUtils.toBoxed(newNumbers))); numbers.add(-1); } return numbers; } /** * Generate a sequence from a list of numbers. * * @param numbers * @return */ public List<Set<Integer>> generateFromNumbers(List<Integer> numbers) { List<Set<Integer>> sequence = new ArrayList<Set<Integer>>(); for(Integer i : numbers) { if(i == -1) { sequence.add(NONE); }else{ Set<Integer> pattern = patternMachine.get(i); sequence.add(pattern); } } return sequence; } /** * Add spatial noise to each pattern in the sequence. * * @param sequence List of patterns * @param amount Amount of spatial noise * @return Sequence with noise added to each non-empty pattern */ public List<Set<Integer>> addSpatialNoise(List<Set<Integer>> sequence, double amount) { List<Set<Integer>> newSequence = new ArrayList<Set<Integer>>(); for(Set<Integer> pattern : sequence) { if(!pattern.equals(NONE)) { pattern = patternMachine.addNoise(pattern, amount); } newSequence.add(pattern); } return newSequence; } /** * Pretty print a sequence. * * @param sequence the sequence of numbers to print * @param verbosity the extent of output chatter * @return */ public String prettyPrintSequence(List<Set<Integer>> sequence, int verbosity) { String text = ""; for(int i = 0;i < sequence.size();i++) { Set<Integer> pattern = sequence.get(i); if(pattern == NONE) { text += "<reset>"; if(i < sequence.size() - 1) { text += "\n"; } }else{ text += patternMachine.prettyPrintPattern(pattern, verbosity); } } return text; } }