/** * {@inheritDoc} */ public override Tuple Decode(int[] encoded, string parentFieldName) { // Get the scalar values from the underlying scalar encoder DecodeResult decodeResult = (DecodeResult)_encoder.Decode(encoded, parentFieldName); Map <string, RangeList> fields = decodeResult.GetFields(); if (fields.Keys.Count == 0) { return(decodeResult); } // Convert each range into normal space RangeList inRanges = fields.Values.ToArray()[0]; RangeList outRanges = new RangeList(new List <MinMax>(), ""); foreach (MinMax minMax in inRanges.GetRanges()) { MinMax scaledMinMax = new MinMax(Math.Pow(10, minMax.Min()), Math.Pow(10, minMax.Max())); outRanges.Add(scaledMinMax); } // Generate a text description of the ranges string desc = ""; int numRanges = outRanges.Count; for (int i = 0; i < numRanges; i++) { MinMax minMax = outRanges.GetRange(i); if (minMax.Min() != minMax.Max()) { desc += string.Format("{0:#.00}-{1:#.00}", minMax.Min(), minMax.Max()); } else { desc += string.Format("{0:#.00}", minMax.Min()); } if (i < numRanges - 1) { desc += ", "; } } outRanges.SetDescription(desc); string fieldName; if (!parentFieldName.Equals("")) { fieldName = string.Format("{0}.{1}", parentFieldName, GetName()); } else { fieldName = GetName(); } Map <string, RangeList> outFields = new Map <string, RangeList>(); outFields.Add(fieldName, outRanges); List <string> fieldNames = new List <string>(); fieldNames.Add(fieldName); return(new DecodeResult(outFields, fieldNames)); }
/** * Returns a {@link DecodeResult} which is a tuple of range names * and lists of {@link RangeLists} in the first entry, and a list * of descriptions for each range in the second entry. * * @param encoded the encoded bit vector * @param parentFieldName the field the vector corresponds with * @return */ public override Tuple Decode(int[] encoded, string parentFieldName) // returns DecodeResult { // For now, we simply assume any top-down output greater than 0 // is ON. Eventually, we will probably want to incorporate the strength // of each top-down output. if (encoded == null || encoded.Length < 1) { return(null); } int[] tmpOutput = Arrays.CopyOf(encoded, encoded.Length); // ------------------------------------------------------------------------ // First, assume the input pool is not sampled 100%, and fill in the // "holes" in the encoded representation (which are likely to be present // if this is a coincidence that was learned by the SP). // Search for portions of the output that have "holes" int maxZerosInARow = GetHalfWidth(); for (int wi = 0; wi < maxZerosInARow; wi++) { int[] searchStr = new int[wi + 3]; Arrays.Fill(searchStr, 1); ArrayUtils.SetRangeTo(searchStr, 1, -1, 0); int subLen = searchStr.Length; // Does this search string appear in the output? if (IsPeriodic()) { for (int j = 0; j < GetN(); j++) { int[] outputIndices = ArrayUtils.Range(j, j + subLen); outputIndices = ArrayUtils.Modulo(outputIndices, GetN()); if (Arrays.AreEqual(searchStr, ArrayUtils.Sub(tmpOutput, outputIndices))) { ArrayUtils.SetIndexesTo(tmpOutput, outputIndices, 1); } } } else { for (int j = 0; j < GetN() - subLen + 1; j++) { if (Arrays.AreEqual(searchStr, ArrayUtils.Sub(tmpOutput, ArrayUtils.Range(j, j + subLen)))) { ArrayUtils.SetRangeTo(tmpOutput, j, j + subLen, 1); } } } } LOGGER.Debug("raw output:" + Arrays.ToString( ArrayUtils.Sub(encoded, ArrayUtils.Range(0, GetN())))); LOGGER.Debug("filtered output:" + Arrays.ToString(tmpOutput)); // ------------------------------------------------------------------------ // Find each run of 1's. //int[] nz = tmpOutput.Where(n => n > 0).ToArray(); int[] nz = ArrayUtils.Where(tmpOutput, x => x > 0); // int[] nz = ArrayUtils.Where(tmpOutput, new Condition.Adapter<Integer>() { // @Override // public boolean eval(int n) // { // return n > 0; // } //}); List <Tuple> runs = new List <Tuple>(); //will be tuples of (startIdx, runLength) Array.Sort(nz); int[] run = new int[] { nz[0], 1 }; int i = 1; while (i < nz.Length) { if (nz[i] == run[0] + run[1]) { run[1] += 1; } else { runs.Add(new Tuple(run[0], run[1])); run = new int[] { nz[i], 1 }; } i += 1; } runs.Add(new Tuple(run[0], run[1])); // If we have a periodic encoder, merge the first and last run if they // both go all the way to the edges if (IsPeriodic() && runs.Count > 1) { int l = runs.Count - 1; if (((int)runs[0].Get(0)) == 0 && ((int)runs[l].Get(0)) + ((int)runs[l].Get(1)) == GetN()) { runs[l] = new Tuple((int)runs[l].Get(0), ((int)runs[l].Get(1)) + ((int)runs[0].Get(1))); runs = runs.SubList(1, runs.Count); } } // ------------------------------------------------------------------------ // Now, for each group of 1's, determine the "left" and "right" edges, where // the "left" edge is inset by halfwidth and the "right" edge is inset by // halfwidth. // For a group of width w or less, the "left" and "right" edge are both at // the center position of the group. int left = 0; int right = 0; List <MinMax> ranges = new List <MinMax>(); foreach (Tuple tupleRun in runs) { int start = (int)tupleRun.Get(0); int runLen = (int)tupleRun.Get(1); if (runLen <= GetW()) { left = right = start + runLen / 2; } else { left = start + GetHalfWidth(); right = start + runLen - 1 - GetHalfWidth(); } double inMin, inMax; // Convert to input space. if (!IsPeriodic()) { inMin = (left - GetPadding()) * GetResolution() + GetMinVal(); inMax = (right - GetPadding()) * GetResolution() + GetMinVal(); } else { inMin = (left - GetPadding()) * GetRange() / GetNInternal() + GetMinVal(); inMax = (right - GetPadding()) * GetRange() / GetNInternal() + GetMinVal(); } // Handle wrap-around if periodic if (IsPeriodic()) { if (inMin >= GetMaxVal()) { inMin -= GetRange(); inMax -= GetRange(); } } // Clip low end if (inMin < GetMinVal()) { inMin = GetMinVal(); } if (inMax < GetMinVal()) { inMax = GetMinVal(); } // If we have a periodic encoder, and the max is past the edge, break into // 2 separate ranges if (IsPeriodic() && inMax >= GetMaxVal()) { ranges.Add(new MinMax(inMin, GetMaxVal())); ranges.Add(new MinMax(GetMinVal(), inMax - GetRange())); } else { if (inMax > GetMaxVal()) { inMax = GetMaxVal(); } if (inMin > GetMaxVal()) { inMin = GetMaxVal(); } ranges.Add(new MinMax(inMin, inMax)); } } string desc = GenerateRangeDescription(ranges); string fieldName; // Return result if (parentFieldName != null && !string.IsNullOrWhiteSpace(parentFieldName)) { fieldName = string.Format("%s.%s", parentFieldName, GetName()); } else { fieldName = GetName(); } RangeList inner = new RangeList(ranges, desc); Map <string, RangeList> fieldsDict = new Map <string, RangeList>(); fieldsDict.Add(fieldName, inner); return(new DecodeResult(fieldsDict, new List <string> { fieldName })); }