Current section
Files
Jump to
Current section
Files
lib/sdr.ex
defmodule Sdr do
@moduledoc """
SDR is an Elixir library for Sparse Distributed Representations
"""
defp factorial(n), do: factorial(n, 1)
defp factorial(0, acc), do: acc
defp factorial(n, acc) when n > 0, do: factorial(n - 1, acc * n)
@doc """
Capacity of a SDR.
## Examples
```elixir
iex(1)> Sdr.capacity(2048, 6)
101733385755251712
```
"""
def capacity(n, w) do
factorial(n) |> div(factorial(w) * factorial(n-w))
end
@doc """
Sparsity of a SDR.
## Examples
```elixir
iex(1)> Sdr.sparsity(2048, 6)
0.0029296875
```
"""
def sparsity(n, w) do
w / n
end
@doc """
Overlap of two SDRs.
## Examples
```elixir
iex(1)> Sdr.overlap(MapSet.new([1, 2]), MapSet.new([2, 3]))
#MapSet<[2]>
```
Use MapSet.size/1 to get the length of the MapSet. Use MapSet.to_list/1 to convert it to a list.
"""
def overlap(m1, m2) do
MapSet.intersection(m1, m2)
end
@doc """
Overlap of two random similar SDRs given their number of bits n and the number of on bits w.
"""
def overlapr(n, w) do
MapSet.intersection(MapSet.new(1..w, fn _x -> :crypto.rand_uniform(0,n) end), MapSet.new(1..w, fn _x -> :crypto.rand_uniform(0,n) end))
end
@doc """
Union of two SDRs.
## Examples
```elixir
iex(1)> Sdr.union(MapSet.new([1, 2]), MapSet.new([2, 3]))
#MapSet<[1, 2, 3]>
```
Use MapSet.size/1 to get the length of the MapSet. Use MapSet.to_list/1 to convert it to a list.
"""
def union(m1, m2) do
MapSet.union(m1, m2)
end
@doc """
Union of two random similar SDRs given their number of bits n and the number of on bits w.
"""
def unionr(n, w) do
MapSet.union(MapSet.new(1..w, fn _x -> :crypto.rand_uniform(0,n) end), MapSet.new(1..w, fn _x -> :crypto.rand_uniform(0,n) end))
end
@doc """
Linear encoder.
## Examples
```elixir
iex(1)> Sdr.simple(0, 100, 1, 21, 72)
#MapSet<[72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92]>
```
```elixir
iex(1)> Sdr.simple(0, 100, 1, 21, 73)
#MapSet<[73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93]>
```
Use MapSet.size/1 to get the length of the MapSet. Use MapSet.to_list/1 to convert it to a list.
"""
def simple(min, max, lc, w, v) do
range = max - min
split = range / lc
g = w - 1
_n = trunc(split + g)
i = trunc(:math.floor(split * (v-min)) / range)
MapSet.new(0..g, fn x -> i + x end)
end
@doc """
Hash encoder.
## Examples
```elixir
iex(1)> Sdr.hash(0, 100, 1, 3, 72)
#MapSet<["32BB90E8976AAB5298D5DA10FE66F21D", "AD61AB143223EFBC24C7D2583BE69251", "D2DDEA18F00665CE8623E36BD4E3C7C5"]>
```
Use MapSet.size/1 to get the length of the MapSet. Use MapSet.to_list/1 to convert it to a list.
"""
def hash(min, max, lc, w, v) do
range = max - min
split = range / lc
g = w - 1
_n = trunc(split + g)
i = trunc(:math.floor(split * (v-min)) / range)
MapSet.new(0..g, fn x -> :crypto.hash(:md5, Integer.to_string(i + x)) |> Base.encode16 end)
end
end