An example of anonymous procedure (lambda expression) in NetLogo (2)

In the last article, I took an example using NetLogo's anonymous procedure (Lambda expressions). This time, as a continuation, I show another simple example. The problem is to find out pairs of right parenthesis and left parenthesis in multiple parentheses structures, as shown in Fig.1. The parentheses structure is given in a text format to the variable paren as shown in (a). The actual structure is as shown in (b). The result of detection of the pairs of left and right parenthesis is illustrated in (c).

This problem can be easily solved using a stack, as is well known. Here, referring to the documents [1] and [2], as shown in Fig. 2, the stack is represented by a list, and the operations of push and pop for it are given by lambda expressions (line 4-line 5). In pop, use the procedure getLast to get (and then to remove) the top element from the list. So far, it is still in preparation.

The actual parentheses check is performed by the foreach in line 5. First, please pay attention to "runresult paren". The variable paren is given the text as described above, but this input form has the ability to create this into a lambda expression for converting text to list. Therefore, runresult is applied. As a result, this part becomes a list. Foreach works on each element of this list, that is, on "(" or on ")". The variable "n" in the lambda expression in line 5 corresponds to one element of the list.

In the procedure "tinit", if the list element is "(", the value obtained by counting up the variable lpc is given to it as a label, and that element is pushed to the stack. On the other hand, if the list element is ")", get the label attached to the "(" at the top of the stack, and then set that label to the ")". This process determines the pair of parentheses. Since push is a lambda expression that does not return a value, it is evaluated by run, whereras,  pop is a lambda expression that returns a value, so it is evaluated by runresult.

Well, "(" and ")" are both turtle agents. In order to display it in an easy-to-understand manner, the shape was defined independently. NetLogo provides a shape editor that allows users to freely define necessary shapes as shown in Fig.3.

[1] Alan G. Isaac, https://subversion.american.edu/aisaac/notes/netlogo-intro.xhtml#tasks-vs-procedures
[2] NetLogo Dictionary, https://ccl.northwestern.edu/netlogo/docs/


An example of anonymous procedure (lambda expression) in NetLogo (1)

Let's take advantage of the anonymous procedure in NetLogo programming. This anonymous procedure is called lambda expression in other languages ​​such as Java. An example is shown in Fig.1. Thirty turtles are randomly arranged. Their types are red, pink and white. The problem is to connect the same colored turtles with a line, under the condition that only turtles of the same color in the range of radius 3 are targeted. The result is shown in the figure on the right.

There should be various NetLogo code to achieve this solution. Here, I created a source program like Fig.2.  I added sight as a new property of turtle (Line 1). This is to give turtles the ability to detect the existence of other turtles around them. This sight is given detection capabilities by calling procedure "getSight 3" (line 9). Here, "3" means to detect within the range of radius 3. This sight is quite different from other properties, such as color. The value of color is a constant like "red + 2", but the value of sight is an anonymous procedure (or lambda expression) as shown in line 14.

That is, in the setup procedure below, the value of sight is not determined, but instead a method is given to determine it. The specific value of sight is determined in the go procedure. The command "runresult sight" (line 18) evaluates the lambda expression sight here. The result should be a set of turtles of the same color, within a radius of 3. Then they are connected in a straight line by the command "create-links-with".

Find out all the properties that turtles have. For example, Fig. 3 shows properties for the turtle whose id (who) is 8. As mentioned above, you can confirm that a "procedure (reporter)" is set to sight (at the last row) unlike other properties. In this way, you can handle the procedure as if it were a value, enabling flexible processing in various situations.


Neural Networkでエージェントの頭脳を作る(agent-based modeling)


 Agent-Basedモデリングの有名な例のひとつにWolf-Sheep Predatorがあります。ここではNetLogoによるモデリングを扱います。これによって、下記のような動作をする3者の個体数がどのように推移するかを観測できます。
  1. 地面(茶色)には、所々にgrass(草、緑色)が生えている。
  2. grassは、sheep(羊、白色)に食べられるが、一定時間後には再生する。
  3. sheepはgrassを食べてエネルギーを得る。
  4. wolf(狼、黒色)はsheepを食べてエネルギーを得る。
  5. sheepとwolfは、動くたびに一定のエネルギーを消費する。
  6. sheepとwolfは、エネルギーがゼロになると死滅する。
  7. sheepとwolfは、一定の確率で子を産む。
 従来のモデルでは、多数のwolfとsheepがそれぞれランダムに(緩やかにある方向へ)移動していました。しかし、下記の論文[1]には、wolfとsheepに頭脳(Neural Network)を持たせて、周りの状況に応じた適切な方向へ移動させる改良がなされています。Neural Network自体は、Wolf-Sheep Predatorとは独立した別モデルとして作られています。両者を連携させるために、NetLogo6以降で導入されたLevelSpaceという拡張機能[2]を使っています。

 各個体のNeural Networkは、Fig.1に示すように、9ノードからなる入力層、9ノードからなる中間層、3ノードからなる出力層で構成されます。この論文と共に、NetLogoのソースプログラムも公開されているのです。しかし、コメントがなく、ラムダ式をふんだんに使っており、ちょっと難解でした。本稿では、当方でそれを解読した結果に基づいて述べます。

 もう少し詳しくみてみましょう。Fig.2はあるsheep(sheep #3)のある時点での頭脳を示しています。入力層で"1"となってノードは(横に赤字項目がある)、周囲からそこへ刺激があったことを意味します。すなわち、以下の3項目です。
  • 左方向(一定範囲のcone vision内)にgrassを見た。
  • 右方向(一定範囲のcone vision内)にgrassを見た。
  • 正面方向(一定範囲のcone vision内)にwolfを見た。
 最終段の出力層は、softmaxによる出力です。「左へ向かう」、「直進する」、「右へ向かう」のうち、最も強い「右へ向かう go right」という判断がなされました。このsheepにとっては、左右方向に草があり、正面方向にwolfを見たのですから、これは確かに、妥当な判断と言えます。

 ここまでは、少ない個体数で想定しましたが、次に、sheepが100匹、wolfが50匹という少し大きな世界をモデリングします。この場合は、150個の独立したニューラルネットワークが同時に動きます。(途中で生死により増減します。)それらすべてを表示するのは現実的はありませんので、Neural Networkの表示を消してシミュレーションを実行しました。その様子をFig.3に示します。図の中のグラフから分かるように、この世界では、周期的に変化はしますが、wolf、sheep、grassの個体数のバランスが長期的に保たれているように見えます。



[1] Bryan Head, Arthur Hjorth, Corey Brady, and Uri Wilensky, "EVOLVING AGENT COGNITION WITH NETLOGO LEVELSPACE", Proceedings of the 2015 Winter Simulation Conference, pp.3122 - 3123.
[2] Extensions LevelSpace, https://ccl.northwestern.edu/netlogo/docs/


Tasks changed for NetLogo 6.0

Anonymous procedures have also been used in NetLogo [1]. A small NetLogo 5.0 code below shows two ways to supply arguments when calling the setup procedure. The keyword task indicates that there is an anonymous procedure next to it. The first case simply gives one number, "inital-value".  However, in the second case we have given the executable code "randam 4". This means that this anonymous procedure consists of a single statement that generates a random number.

The procedure setup called in these two cases is common to both, as shown in the figure below. The arguments of task shown in the above figure are passed to the argument setup-task. That is, the code of the executable procedure is passed to setup as if it were a value. In setup, runresult gives us the execution results of the passed procedure. This allows us to configure the contents of setup very flexibly. Not only that, but it also seems to be a mechanism to improve the effective performance.

By the way, this task is no longer available in NetLogo 6.0 [2]. The task has been changed to arrow syntax as shown in the following figure. This is good because it is the same as Java or JavaScript Lambda Expressions.

[1] Uri Wilensky and William Rand, "An Intoroduction to Agent-Based Modeling"(chapter 8 : Advance Topics and Applications),The MIT Press 
[2] Transition Guide in https://ccl.northwestern.edu/netlogo/docs/