Qustion about periodic scalar encoder

Hello.

In this source code: https://github.com/numenta/nupic/blob/master/src/nupic/encoders/scalar.py provided example for encoding week days:

 monday (1)   -> 11000000000001
 tuesday(2)   -> 01110000000000
 wednesday(3) -> 00011100000000
 ...
 sunday (7)   -> 10000000000011

I looked at the source code and tried to write my own encoder, but it doesn’t work like in the example above:

monday (1)   -> [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
uesday(2)    -> [0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
wednesday(3) -> [0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]
sunday (7)   -> [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1]

Unfortunately, I can’t figure out what the problem is =(
How to achieve the result as in the example above?

Here is source of my encoder:

function encoder(min, max, val, n, w) {
  const range = max - min
  const centr = Math.round((val - min) * n / range)
  const halfw = (w - 1) / 2
  const start = centr - halfw < 0
  	? n + (centr - halfw)
    : 0 + (centr - halfw)
  
  const sdr = []
  for (let i = 0; i < n; i++) {
    sdr.push(0)
  }
  
  for (let i = start; i < start + w; i++) {
    sdr[i % n] = 1
  }
}

And you can run or edit it here:

Thank you!

After few hours of experiments, im found that if im add “+ 1 / range” - last value (sunday) represent correct bit array:

function encoder(min, max, val, n, w) {
  const range = max - min 
  const resolution = n / range + 1 / range // <--------
  const centr = Math.round((val - min) * resolution)
  const halfw = (w - 1) / 2
  const start = centr - halfw < 0
  	? n + (centr - halfw)
    : 0 + (centr - halfw)
  
  const sdr = []
  for (let i = 0; i < n; i++) {
    sdr.push(0)
  }
  
  for (let i = start; i < start + w; i++) {
    sdr[i % n] = 1
  }

  return sdr.join('')
}

Output:

"11000000000001"
"01110000000000"
"00011100000000"
"00000111000000"
"00000000111000"
"00000000001110"
"10000000000011"

Please tell me, now my scalar-periodic encoder works properly?

It still doesn’t look right. Your example shows 14 bits with the bins 3 bits wide. So, there should be exactly 1 bit of overlap between adjacent states with the whole pattern shifting by 2 each time the date advances. Right in the middle the transition from the fourth to fifth states shows a shift of 3 bits, and there are two bits of overlap between the first and last states.

What I would recommend is something like the following:

function sdrDayOfWeek(day, nbits, width) {
  var sdr = UInt8Array(nbits);
  sdr.fill(0);
  const nbitsPerDay = Math.floor(nbits/7);
  const offset = day*nbitsPerDay;
  for (var i=offset; i<offset+width; ++i) {
    sdr[i%nbits] = 1;
  }
  return sdr;
}
1 Like

@CollinsEM thank you for answer! Im slightly modified you solution, but output of this encoder different from expected (numenta encoder):

You can run it here: https://jsfiddle.net/p6n34dky/

function encoder(min, max, val, n, w) {
  const range = max - min
  const bitsPerDay = Math.floor(n / range)
  const offset = (val - min) * bitsPerDay
  
  const sdr = new Array(n).fill(0)
  
  for (let i = offset; i < offset + w; ++i) {
    sdr[i % n] = 1
  }
  
  return sdr
}

Output:

"11100000000000"
"00111000000000"
"00001110000000"
"00000011100000"
"00000000111000"
"00000000001110"
"10000000000011"

Expected:

 monday (1)   -> 11000000000001
 tuesday(2)   -> 01110000000000
 wednesday(3) -> 00011100000000
 ...
 sunday (7)   -> 10000000000011

P.S. I’m not sure if this is a problem, but still, I want to figure it out.

I personally prefer the output as shown by your program here (i.e. the first state is the first w bits). Also, in the expected output that you show, there is still an overlap of two bits between Sunday and Monday, and no bits of overlap between Thursday and Friday. If your intent is to represent all days equally, then this is undesirable behavior.

The modified code presented in your most recent post will provide equal amount of overlap between consecutive states (with wrap around) as long as the total number of bits is some integer multiple of the number of distinct states. (If the number of bits is not an integer multiple of the states, then the last state will fail to wrap-around and overlap with the first.)