fork download
  1. defmodule MontyExperiments.First.NilMotor do
  2. use GenServer
  3. # require Logger
  4.  
  5. @default_state %{
  6. percepts: %{},
  7. goals: %{},
  8. state: %{},
  9. }
  10.  
  11. def start_link(id, opts \\ []) do
  12. GenServer.start_link(__MODULE__, Map.put(@default_state, :id, id), opts)
  13. end
  14.  
  15. def goal_state(motor, id, goal_state) do
  16. GenServer.cast(motor, {:cortical, self(), id, goal_state})
  17. end
  18.  
  19. def subcortical(motor, id, percept) do
  20. GenServer.cast(motor, {:subcortical, self(), id, percept})
  21. end
  22.  
  23. def init(data) do
  24. {:ok, data}
  25. end
  26.  
  27. def handle_call(msg, _from, data) do
  28. {:reply, {:error, {:unsupported, msg}}, data}
  29. end
  30.  
  31. def handle_cast({:cortical, _pid, id, goal_state}, data) do
  32. _ = IO.puts("cortial -> id: #{id}, goal_state: #{goal_state}")
  33. {:noreply, put_in(data, [:goals, id], goal_state)}
  34. end
  35. def handle_cast({:subcortical, _pid, id, percept}, data) do
  36. _ = IO.puts("subcortial -> id: #{id}, percept: #{percept}")
  37. {:noreply, put_in(data, [:percepts, id], percept)}
  38. end
  39. def handle_cast(msg, data) do
  40. {:noreply, data}
  41. end
  42.  
  43. def handle_info(msg, data) do
  44. {:noreply, data}
  45. end
  46. end
  47.  
  48. defmodule MontyExperiments.First.NilLearning do
  49. use GenServer
  50. # require Logger
  51. alias MontyExperiments.First.NilMotor
  52.  
  53. @default_state %{
  54. subscribers: %{
  55. output: %{},
  56. vote: %{},
  57. bias: %{},
  58. motor: %{},
  59. },
  60. votes: %{},
  61. bias: %{},
  62. goals: %{},
  63. state: %{},
  64. current_guess: nil,
  65. current_goal: nil,
  66. }
  67.  
  68. def start_link(id, opts \\ []) do
  69. GenServer.start_link(__MODULE__, Map.put(@default_state, :id, id), opts)
  70. end
  71.  
  72. def get_hypothesis(lm, timeout \\ :infinity) do
  73. GenServer.call(lm, :get_hypothesis, timeout)
  74. end
  75.  
  76. def subscribe(lm, type, id, subscriber) do
  77. GenServer.cast(lm, {:subscribe, type, id, subscriber})
  78. end
  79.  
  80. def unsubscribe(lm, type, id) do
  81. GenServer.cast(lm, {:unsubscribe, type, id})
  82. end
  83.  
  84. def learn(lm, id, input) do
  85. GenServer.cast(lm, {:learn, self(), id, input})
  86. end
  87.  
  88. def vote(lm, id, vote) do
  89. GenServer.cast(lm, {:vote, self(), id, vote})
  90. end
  91.  
  92. def bias(lm, id, bias, goal) do
  93. GenServer.cast(lm, {:bias, self(), id, bias, goal})
  94. end
  95.  
  96. def init(data) do
  97. {:ok, data}
  98. end
  99.  
  100. def handle_call(:get_hypothesis, _from, data) do
  101. {:reply, {:ok, data.current_guess}, data}
  102. end
  103. def handle_call(msg, _from, data) do
  104. {:reply, {:error, {:unsupported, msg}}, data}
  105. end
  106.  
  107. def handle_cast({:subscribe, type, id, subscriber}, data) do
  108. {:noreply, put_in(data, [:subscribers, type, id], subscriber)}
  109. end
  110. def handle_cast({:unsubscribe, type, id}, data) do
  111. {:noreply, update_in(data, [:subscribers, type], &Map.delete(&1, id))}
  112. end
  113. def handle_cast({:bias, _pid, id, cmp, gs}, data) do
  114. data = data |> put_in([:bias, id], cmp) |> put_in([:goals, id], gs)
  115. {:noreply, data}
  116. end
  117. def handle_cast({:vote, _pid, id, vote}, data) do
  118. {:noreply, put_in(data, [:votes, id], vote)}
  119. end
  120. def handle_cast({:learn, pid, id, cmp}, data) do
  121. # _ = Logger.debug(fn -> %{msg: :learning, pid: pid, id: id, cmp: cmp, data: data} end)
  122. # guess
  123. {:hypothesis, guess, state} = handle_learning(cmp, data.bias, data.state)
  124.  
  125. # publish guess to "voting block" LMs
  126. :ok = Enum.each(data.subscribers.vote, fn {_, lm} -> vote(lm, data.id, guess) end)
  127.  
  128. # generate goal
  129. {:goal, goal, state} = handle_goal_generation(guess, data.goals, state)
  130.  
  131. # apply vote
  132. guess = apply_votes(guess, data.votes)
  133.  
  134. # publish goal to Motor Systems
  135. :ok = Enum.each(data.subscribers.motor, fn {_, ms} -> NilMotor.goal_state(ms, data.id, goal) end)
  136. # publish bias to lower-level LMs
  137. :ok = Enum.each(data.subscribers.bias, fn {_, lm} -> bias(lm, data.id, guess, goal) end)
  138. # publish guess to higher-level LMs
  139. :ok = Enum.each(data.subscribers.output, fn {_, lm} -> learn(lm, data.id, guess) end)
  140.  
  141. {:noreply, %{data | state: state, current_guess: guess, current_goal: goal}}
  142. end
  143. def handle_cast(msg, data) do
  144. {:noreply, data}
  145. end
  146.  
  147. def handle_info(msg, data) do
  148. {:noreply, data}
  149. end
  150.  
  151. def handle_learning(cmp, biases, state) do
  152. {:hypothesis, average(cmp, biases), state}
  153. end
  154.  
  155. def handle_goal_generation(guess, goals, state) do
  156. goals = Enum.map(goals, &elem(&1, 1))
  157. {:goal, Enum.random([guess | goals]), state}
  158. end
  159.  
  160. defp apply_votes(guess, votes), do: average(guess, votes)
  161.  
  162. defp average(guess, other_guesses) do
  163. (Enum.sum(Enum.map(other_guesses, &elem(&1, 1))) + guess) / (Enum.count(other_guesses) + 1)
  164. end
  165. end
  166.  
  167. defmodule MontyExperiments.First.JitterSensor do
  168. use GenServer
  169. # require Logger
  170. alias MontyExperiments.First.NilMotor
  171. alias MontyExperiments.First.NilLearning
  172.  
  173. @default_state %{
  174. subscribers: %{
  175. learn: %{},
  176. motor: %{},
  177. },
  178. delay_ms: 100,
  179. count: 0,
  180. status: :off
  181. }
  182.  
  183. def start_link(id, opts \\ []) do
  184. GenServer.start_link(__MODULE__, Map.put(@default_state, :id, id), opts)
  185. end
  186.  
  187. def subscribe(sensor, type, id, subscriber) do
  188. GenServer.cast(sensor, {:subscribe, type, id, subscriber})
  189. end
  190.  
  191. def unsubscribe(sensor, type, id) do
  192. GenServer.cast(sensor, {:unsubscribe, type, id})
  193. end
  194.  
  195. def on(sensor), do: GenServer.cast(sensor, :on)
  196. def off(sensor), do: GenServer.cast(sensor, :off)
  197.  
  198. def init(data) do
  199. _ = schedule_tick(data)
  200. {:ok, data}
  201. end
  202.  
  203. def handle_call(msg, _from, data) do
  204. {:reply, {:error, {:unsupported, msg}}, data}
  205. end
  206.  
  207. def handle_cast(:on, %{status: :off} = data) do
  208. _ = schedule_tick(data)
  209. {:noreply, %{data | status: :on}}
  210. end
  211. def handle_cast(:on, data) do
  212. {:noreply, data}
  213. end
  214. def handle_cast(:off, data) do
  215. {:noreply, %{data | status: :off}}
  216. end
  217. def handle_cast({:subscribe, type, id, subscriber}, data) do
  218. {:noreply, put_in(data, [:subscribers, type, id], subscriber)}
  219. end
  220. def handle_cast({:unsubscribe, type, id}, data) do
  221. {:noreply, update_in(data, [:subscribers, type], &Map.delete(&1, id))}
  222. end
  223. def handle_cast(msg, data) do
  224. {:noreply, data}
  225. end
  226.  
  227. def handle_info(:tick, %{status: :off} = data) do
  228. {:noreply, data}
  229. end
  230. def handle_info(:tick, %{status: :on} = data) do
  231. data = tick(data)
  232. _ = schedule_tick(data)
  233. {:noreply, data}
  234. end
  235. def handle_info(msg, data) do
  236. {:noreply, data}
  237. end
  238.  
  239. defp tick(%{count: count} = data) do
  240. :ok = Enum.each(data.subscribers.learn, fn {_, pid} -> NilLearning.learn(pid, data.id, data.count) end)
  241. :ok = Enum.each(data.subscribers.motor, fn {_, pid} -> NilMotor.subcortical(pid, data.id, data.count) end)
  242. %{data | count: count + 1}
  243. end
  244.  
  245. defp schedule_tick(data) do
  246. Process.send_after(self(), :tick, calculate_next_tick(data))
  247. end
  248.  
  249. defp calculate_next_tick(%{delay_ms: delay_ms}) do
  250. round(delay_ms + 0.5 * :rand.uniform(delay_ms))
  251. end
  252. end
  253.  
  254. defmodule MontyExperiments.First.Experiment do
  255. alias MontyExperiments.First.{NilMotor, NilLearning, JitterSensor}
  256.  
  257. # NOTE: use :digraph to describe this instead
  258. def config_attempt1 do
  259. %{
  260. delays: 1..5,
  261. base_delay: 100,
  262. sensors: [:s01, :s02, :s03],
  263. motors: [:m01, :m02],
  264. learning: [:l01, :l02, :l03, :l11, :l12, :l13, :l21, :l22, :l23],
  265. sensor_conns: [
  266. {:s01, :learn, :l01},
  267. {:s02, :learn, :l02},
  268. {:s03, :learn, :l03},
  269. {:s01, :motor, :m01},
  270. {:s03, :motor, :m02},
  271. ],
  272. learning_conns: [
  273. {:l01, :output, :l11},
  274. {:l01, :vote, :l02},
  275. {:l01, :vote, :l03},
  276. {:l01, :motor, :m01},
  277.  
  278. {:l02, :output, :l12},
  279. {:l02, :vote, :l01},
  280. {:l02, :vote, :l03},
  281. {:l02, :motor, :m02},
  282.  
  283. {:l03, :output, :l13},
  284. {:l03, :vote, :l01},
  285. {:l03, :vote, :l02},
  286. {:l03, :motor, :m02},
  287.  
  288. {:l11, :output, :l21},
  289. {:l11, :bias, :l01},
  290. {:l11, :vote, :l12},
  291. {:l11, :vote, :l13},
  292. {:l11, :motor, :m01},
  293.  
  294. {:l12, :output, :l22},
  295. {:l12, :bias, :l02},
  296. {:l12, :vote, :l11},
  297. {:l12, :vote, :l13},
  298. {:l12, :motor, :m02},
  299.  
  300. {:l13, :output, :l23},
  301. {:l13, :bias, :l03},
  302. {:l13, :vote, :l11},
  303. {:l13, :vote, :l12},
  304. {:l13, :motor, :m02},
  305.  
  306. {:l21, :bias, :l11},
  307. {:l21, :vote, :l22},
  308. {:l21, :vote, :l23},
  309. {:l21, :motor, :m01},
  310.  
  311. {:l22, :bias, :l12},
  312. {:l22, :vote, :l21},
  313. {:l22, :vote, :l23},
  314. {:l22, :motor, :m02},
  315.  
  316. {:l23, :bias, :l13},
  317. {:l23, :vote, :l21},
  318. {:l23, :vote, :l22},
  319. {:l23, :motor, :m02},
  320. ],
  321. }
  322. end
  323.  
  324. def setup(config) do
  325. sensors = config.sensors |> Enum.map(&{&1, JitterSensor.start_link(&1)}) |> Enum.map(fn {id, {:ok, pid}} -> {id, pid} end) |> Enum.into(%{})
  326. motors = config.motors |> Enum.map(&{&1, NilMotor.start_link(&1)}) |> Enum.map(fn {id, {:ok, pid}} -> {id, pid} end) |> Enum.into(%{})
  327. learning = config.learning |> Enum.map(&{&1, NilLearning.start_link(&1)}) |> Enum.map(fn {id, {:ok, pid}} -> {id, pid} end) |> Enum.into(%{})
  328.  
  329. :ok = Enum.each(config.sensor_conns, fn
  330. {sid, :learn, id} -> JitterSensor.subscribe(sensors[sid], :learn, id, learning[id])
  331. {sid, :motor, id} -> JitterSensor.subscribe(sensors[sid], :motor, id, motors[id])
  332. end)
  333. :ok = Enum.each(config.learning_conns, fn
  334. {lid, :motor, id} -> NilLearning.subscribe(learning[lid], :motor, id, motors[id])
  335. {lid, type, id} -> NilLearning.subscribe(learning[lid], type, id, learning[id])
  336. end)
  337.  
  338. %{config |
  339. sensors: sensors,
  340. motors: motors,
  341. learning: learning,
  342. }
  343. end
  344.  
  345. def teardown(_config) do
  346. end
  347.  
  348. def run(config) do
  349. _ = start_all(config)
  350.  
  351. config.delays
  352. |> Enum.each(fn d ->
  353. delay = d * config.base_delay
  354. _ = IO.puts("sleeping for #{delay}ms...")
  355. :ok = Process.sleep(delay)
  356. IO.inspect(get_hypotheses(config))
  357. end)
  358.  
  359. _ = stop_all(config)
  360. config
  361. end
  362.  
  363. def start_all(config) do
  364. Enum.each(config.sensors, fn {_, pid} -> JitterSensor.on(pid) end)
  365. end
  366.  
  367. def get_hypotheses(config) do
  368. config.learning
  369. |> Enum.map(fn {id, pid} ->
  370. {:ok, hypothesis} = NilLearning.get_hypothesis(pid)
  371. {id, hypothesis}
  372. end)
  373. |> Enum.into(%{})
  374. end
  375.  
  376. def stop_all(config) do
  377. Enum.each(config.sensors, fn {_, pid} -> JitterSensor.off(pid) end)
  378. end
  379. end
  380.  
  381. alias MontyExperiments.First.Experiment
  382.  
  383. Experiment.config_attempt1()
  384. |> Experiment.setup()
  385. |> Experiment.run()
  386.  
Success #stdin #stdout #stderr 0.6s 39292KB
stdin
Standard input is empty
stdout
sleeping for 100ms...
%{
  l01: nil,
  l02: nil,
  l03: nil,
  l11: nil,
  l12: nil,
  l13: nil,
  l21: nil,
  l22: nil,
  l23: nil
}
sleeping for 200ms...
subcortial -> id: s01, percept: 0
subcortial -> id: s01, percept: 1
subcortial -> id: s03, percept: 0
cortial -> id: l01, goal_state: 0.0
cortial -> id: l03, goal_state: 0.0
cortial -> id: l01, goal_state: 1.0
cortial -> id: l13, goal_state: 0.0
cortial -> id: l11, goal_state: 0.0
cortial -> id: l23, goal_state: 0.0
cortial -> id: l11, goal_state: 1.0
cortial -> id: l21, goal_state: 0.0
cortial -> id: l21, goal_state: 1.0
subcortial -> id: s03, percept: 1
cortial -> id: l03, goal_state: 0.5
cortial -> id: l13, goal_state: 0.0
cortial -> id: l23, goal_state: 0.6875
cortial -> id: l02, goal_state: 0.0
cortial -> id: l12, goal_state: 0.5
cortial -> id: l22, goal_state: 0.625
cortial -> id: l02, goal_state: 0.8125
cortial -> id: l12, goal_state: 0.7708333333333334
cortial -> id: l22, goal_state: 0.7152777777777778
subcortial -> id: s01, percept: 2
cortial -> id: l01, goal_state: 1.0
cortial -> id: l11, goal_state: 0.96875
cortial -> id: l21, goal_state: 0.7048611111111112
subcortial -> id: s03, percept: 2
cortial -> id: l03, goal_state: 1.34375
cortial -> id: l13, goal_state: 0.6875
cortial -> id: l23, goal_state: 0.9236111111111112
subcortial -> id: s01, percept: 3
cortial -> id: l01, goal_state: 0.96875
cortial -> id: l11, goal_state: 0.7048611111111112
cortial -> id: l21, goal_state: 0.9404899691358025
subcortial -> id: s03, percept: 3
cortial -> id: l03, goal_state: 0.6875
cortial -> id: l13, goal_state: 1.1617476851851851
cortial -> id: l23, goal_state: 0.9839891975308642
cortial -> id: l02, goal_state: 0.7708333333333334
cortial -> id: l12, goal_state: 1.2624421296296295
cortial -> id: l22, goal_state: 1.147858796296296
cortial -> id: l02, goal_state: 1.2624421296296295
cortial -> id: l12, goal_state: 1.147858796296296
cortial -> id: l22, goal_state: 1.2248505015432098
%{
  l01: 1.3362268518518519,
  l02: 1.9627218364197532,
  l03: 1.5422453703703702,
  l11: 0.9404899691358025,
  l12: 1.2248505015432098,
  l13: 0.9839891975308642,
  l21: 0.8597929526748972,
  l22: 1.0497765560699588,
  l23: 0.8799189814814815
}
sleeping for 300ms...
subcortial -> id: s03, percept: 4
cortial -> id: l03, goal_state: 1.1617476851851851
cortial -> id: l13, goal_state: 1.5096852494855966
cortial -> id: l23, goal_state: 1.340829689643347
subcortial -> id: s01, percept: 4
cortial -> id: l01, goal_state: 0.7048611111111112
cortial -> id: l11, goal_state: 0.9404899691358025
cortial -> id: l21, goal_state: 1.5352312671467765
subcortial -> id: s01, percept: 5
cortial -> id: l01, goal_state: 3.267615633573388
cortial -> id: l11, goal_state: 1.5352312671467765
cortial -> id: l21, goal_state: 1.6640592254420057
subcortial -> id: s03, percept: 5
cortial -> id: l03, goal_state: 3.1704148448216736
cortial -> id: l13, goal_state: 2.003021672810928
cortial -> id: l23, goal_state: 1.8285046998837828
cortial -> id: l02, goal_state: 2.612425250771605
cortial -> id: l12, goal_state: 1.2248505015432098
cortial -> id: l22, goal_state: 2.0084648068368005
cortial -> id: l02, goal_state: 1.2248505015432098
cortial -> id: l12, goal_state: 2.5738819356626754
cortial -> id: l22, goal_state: 2.1886595966478843
subcortial -> id: s03, percept: 6
cortial -> id: l03, goal_state: 3.9142523499418913
cortial -> id: l13, goal_state: 1.8285046998837828
cortial -> id: l23, goal_state: 2.3767365286999462
subcortial -> id: s01, percept: 6
cortial -> id: l01, goal_state: 3.8320296127210027
cortial -> id: l11, goal_state: 2.5800422971183092
cortial -> id: l21, goal_state: 2.5737255672493657
subcortial -> id: s03, percept: 7
cortial -> id: l03, goal_state: 1.8285046998837828
cortial -> id: l13, goal_state: 3.0423476052132017
cortial -> id: l23, goal_state: 2.7320906126647286
subcortial -> id: s01, percept: 7
cortial -> id: l01, goal_state: 2.5800422971183092
cortial -> id: l11, goal_state: 3.3530975239983754
cortial -> id: l21, goal_state: 2.989775688291418
cortial -> id: l02, goal_state: 2.5738819356626754
cortial -> id: l12, goal_state: 3.208464061378712
cortial -> id: l22, goal_state: 3.2013030635300965
cortial -> id: l02, goal_state: 5.100651531765048
cortial -> id: l12, goal_state: 3.9165086573709917
cortial -> id: l22, goal_state: 3.4373179288608564
subcortial -> id: s03, percept: 8
cortial -> id: l03, goal_state: 3.0423476052132017
cortial -> id: l13, goal_state: 2.7320906126647286
cortial -> id: l23, goal_state: 3.686981804805571
subcortial -> id: s01, percept: 8
cortial -> id: l01, goal_state: 5.494887844145709
cortial -> id: l11, goal_state: 3.9786850966411924
cortial -> id: l21, goal_state: 3.8955109956865095
%{
  l01: 4.326487817131019,
  l02: 4.858627526579902,
  l03: 5.0845198739073645,
  l11: 3.8955109956865095,
  l12: 3.4373179288608564,
  l13: 3.686981804805571,
  l21: 3.6732702431176456,
  l22: 3.053061409939001,
  l23: 3.3713584739859486
}
sleeping for 400ms...
subcortial -> id: s01, percept: 9
cortial -> id: l01, goal_state: 6.4477554978432545
cortial -> id: l11, goal_state: 4.655710510882267
cortial -> id: l21, goal_state: 4.1211861337668685
subcortial -> id: s03, percept: 9
cortial -> id: l03, goal_state: 2.7320906126647286
cortial -> id: l13, goal_state: 4.667662225661489
cortial -> id: l23, goal_state: 4.4132937979715825
cortial -> id: l02, goal_state: 3.9165086573709917
cortial -> id: l12, goal_state: 4.611514932415579
cortial -> id: l22, goal_state: 4.644962556319778
cortial -> id: l02, goal_state: 6.82248127815989
cortial -> id: l12, goal_state: 4.644962556319778
cortial -> id: l22, goal_state: 4.929633699207039
subcortial -> id: s03, percept: 10
cortial -> id: l03, goal_state: 4.667662225661489
cortial -> id: l13, goal_state: 4.4132937979715825
cortial -> id: l23, goal_state: 5.176450820408111
subcortial -> id: s01, percept: 10
cortial -> id: l01, goal_state: 4.655710510882267
cortial -> id: l11, goal_state: 4.1211861337668685
cortial -> id: l21, goal_state: 5.420947711861934
subcortial -> id: s01, percept: 11
cortial -> id: l01, goal_state: 8.210473855930967
cortial -> id: l11, goal_state: 6.2944390440922895
cortial -> id: l21, goal_state: 5.722693664811452
subcortial -> id: s03, percept: 11
cortial -> id: l03, goal_state: 4.4132937979715825
cortial -> id: l13, goal_state: 5.176450820408111
cortial -> id: l23, goal_state: 5.994903090483046
cortial -> id: l02, goal_state: 4.644962556319778
cortial -> id: l12, goal_state: 4.929633699207039
cortial -> id: l22, goal_state: 6.241261956050816
cortial -> id: l02, goal_state: 8.620630978025408
cortial -> id: l12, goal_state: 6.241261956050816
cortial -> id: l22, goal_state: 6.555181912096468
subcortial -> id: s03, percept: 12
cortial -> id: l03, goal_state: 5.176450820408111
cortial -> id: l13, goal_state: 5.994903090483046
cortial -> id: l23, goal_state: 6.840033891875495
subcortial -> id: s01, percept: 12
cortial -> id: l01, goal_state: 8.861346832405726
cortial -> id: l11, goal_state: 5.722693664811452
cortial -> id: l21, goal_state: 7.09234351829469
subcortial -> id: s01, percept: 13
cortial -> id: l01, goal_state: 5.722693664811452
cortial -> id: l11, goal_state: 7.09234351829469
cortial -> id: l21, goal_state: 7.416988299660339
subcortial -> id: s03, percept: 13
cortial -> id: l03, goal_state: 5.994903090483046
cortial -> id: l13, goal_state: 7.950788191982319
cortial -> id: l23, goal_state: 7.707485095115589
cortial -> id: l02, goal_state: 6.241261956050816
cortial -> id: l12, goal_state: 6.555181912096468
cortial -> id: l22, goal_state: 7.965172282505509
cortial -> id: l02, goal_state: 10.482586141252755
cortial -> id: l12, goal_state: 8.923070087269881
cortial -> id: l22, goal_state: 8.299720182233008
subcortial -> id: s01, percept: 14
cortial -> id: l01, goal_state: 10.70849414983017
cortial -> id: l11, goal_state: 7.416988299660339
cortial -> id: l21, goal_state: 8.509247278675899
subcortial -> id: s01, percept: 15
cortial -> id: l01, goal_state: 11.75462363933795
cortial -> id: l11, goal_state: 8.509247278675899
cortial -> id: l21, goal_state: 8.77315716433701
subcortial -> id: s03, percept: 14
cortial -> id: l03, goal_state: 7.950788191982319
cortial -> id: l13, goal_state: 7.707485095115589
cortial -> id: l23, goal_state: 9.165705968955175
%{
  l01: 10.719075575509484,
  l02: 10.14959161544595,
  l03: 11.030317442716166,
  l11: 8.77315716433701,
  l12: 8.299720182233008,
  l13: 9.165705968955175,
  l21: 8.2601208138952,
  l22: 7.8080645256696455,
  l23: 8.746194438508397
}
sleeping for 500ms...
cortial -> id: l02, goal_state: 8.923070087269881
cortial -> id: l12, goal_state: 8.299720182233008
cortial -> id: l22, goal_state: 9.36815037625528
subcortial -> id: s03, percept: 15
cortial -> id: l03, goal_state: 7.707485095115589
cortial -> id: l13, goal_state: 10.204320005076205
cortial -> id: l23, goal_state: 9.72677884266841
subcortial -> id: s01, percept: 16
cortial -> id: l01, goal_state: 8.509247278675899
cortial -> id: l11, goal_state: 10.066609016574699
cortial -> id: l21, goal_state: 9.933777443607033
subcortial -> id: s01, percept: 17
cortial -> id: l01, goal_state: 13.466888721803517
cortial -> id: l11, goal_state: 10.954718076654721
cortial -> id: l21, goal_state: 10.229813796967042
cortial -> id: l02, goal_state: 8.299720182233008
cortial -> id: l12, goal_state: 9.36815037625528
cortial -> id: l22, goal_state: 10.666392160796766
subcortial -> id: s03, percept: 16
cortial -> id: l03, goal_state: 10.204320005076205
cortial -> id: l13, goal_state: 9.72677884266841
cortial -> id: l23, goal_state: 10.952865476578367
cortial -> id: l02, goal_state: 13.333196080398384
cortial -> id: l12, goal_state: 11.714409837328054
cortial -> id: l22, goal_state: 11.244289288801262
subcortial -> id: s03, percept: 17
cortial -> id: l03, goal_state: 9.72677884266841
cortial -> id: l13, goal_state: 12.104264829138877
cortial -> id: l23, goal_state: 11.591130914373885
subcortial -> id: s01, percept: 18
cortial -> id: l01, goal_state: 14.114906898483522
cortial -> id: l11, goal_state: 10.229813796967042
cortial -> id: l21, goal_state: 11.870073707325744
subcortial -> id: s03, percept: 18
cortial -> id: l03, goal_state: 12.104264829138877
cortial -> id: l13, goal_state: 12.551483739368507
cortial -> id: l23, goal_state: 12.019146677402288
cortial -> id: l02, goal_state: 14.122144644400631
cortial -> id: l12, goal_state: 12.576597593736295
cortial -> id: l22, goal_state: 12.306542596205034
subcortial -> id: s01, percept: 19
cortial -> id: l01, goal_state: 15.435036853662872
cortial -> id: l11, goal_state: 13.176373477625223
cortial -> id: l21, goal_state: 12.768151603576674
cortial -> id: l02, goal_state: 15.153271298102517
cortial -> id: l12, goal_state: 13.596606098314233
cortial -> id: l22, goal_state: 13.108154438435989
subcortial -> id: s03, percept: 19
cortial -> id: l03, goal_state: 15.509573338701145
cortial -> id: l13, goal_state: 13.538565193999304
cortial -> id: l23, goal_state: 13.437181589979588
cortial -> id: l02, goal_state: 13.596606098314233
cortial -> id: l12, goal_state: 13.108154438435989
cortial -> id: l22, goal_state: 13.621320675596897
subcortial -> id: s03, percept: 20
cortial -> id: l03, goal_state: 16.718590794989794
cortial -> id: l13, goal_state: 14.586865416643818
cortial -> id: l23, goal_state: 13.970754083145067
subcortial -> id: s01, percept: 20
cortial -> id: l01, goal_state: 13.176373477625223
cortial -> id: l11, goal_state: 12.768151603576674
cortial -> id: l21, goal_state: 14.370328740224442
subcortial -> id: s01, percept: 21
cortial -> id: l01, goal_state: 12.768151603576674
cortial -> id: l11, goal_state: 14.370328740224442
cortial -> id: l21, goal_state: 14.713087139674792
subcortial -> id: s03, percept: 21
cortial -> id: l03, goal_state: 14.586865416643818
cortial -> id: l13, goal_state: 15.264140832203566
cortial -> id: l23, goal_state: 14.938845611528043
cortial -> id: l02, goal_state: 13.108154438435989
cortial -> id: l12, goal_state: 15.301309269772727
cortial -> id: l22, goal_state: 15.322940916396897
cortial -> id: l02, goal_state: 15.301309269772727
cortial -> id: l12, goal_state: 15.322940916396897
cortial -> id: l22, goal_state: 15.683998134110597
subcortial -> id: s03, percept: 22
cortial -> id: l03, goal_state: 18.469422805764022
cortial -> id: l13, goal_state: 14.938845611528043
cortial -> id: l23, goal_state: 16.017579582313545
subcortial -> id: s01, percept: 22
cortial -> id: l01, goal_state: 18.356543569837395
cortial -> id: l11, goal_state: 16.215433122036103
cortial -> id: l21, goal_state: 16.28826640725411
subcortial -> id: s01, percept: 23
cortial -> id: l01, goal_state: 16.215433122036103
cortial -> id: l11, goal_state: 16.28826640725411
cortial -> id: l21, goal_state: 16.675614843868065
subcortial -> id: s03, percept: 23
cortial -> id: l03, goal_state: 14.938845611528043
cortial -> id: l13, goal_state: 17.288176384846867
cortial -> id: l23, goal_state: 17.016711913212884
%{
  l01: 18.758342155863176,
  l02: 17.777337289961068,
  l03: 19.104797817660756,
  l11: 16.675614843868065,
  l12: 15.683998134110597,
  l13: 17.016711913212884,
  l21: 16.125730853430735,
  l22: 15.111976961771143,
  l23: 16.458774963730516
}
stderr
warning: variable "msg" is unused (if the variable is not meant to be used, prefix it with an underscore)
  prog.ex:39

warning: variable "msg" is unused (if the variable is not meant to be used, prefix it with an underscore)
  prog.ex:43

warning: variable "id" is unused (if the variable is not meant to be used, prefix it with an underscore)
  prog.ex:120

warning: variable "pid" is unused (if the variable is not meant to be used, prefix it with an underscore)
  prog.ex:120

warning: variable "msg" is unused (if the variable is not meant to be used, prefix it with an underscore)
  prog.ex:143

warning: variable "msg" is unused (if the variable is not meant to be used, prefix it with an underscore)
  prog.ex:147

warning: variable "msg" is unused (if the variable is not meant to be used, prefix it with an underscore)
  prog.ex:223

warning: variable "msg" is unused (if the variable is not meant to be used, prefix it with an underscore)
  prog.ex:235