May 17, 2025

Stick man as demonstration for symbol grounding on the text terminal

The advantage of using a text terminal as the only output device is, that the source code for the rendering engine will become very compact. The following demo has only 40 lines of code in Python and generates random stick figures including a textual annotation. Its inner working is the same like in the two previous examples, at first a random scene is shown on the screen and then this scene gets annotated with [tags]. So its a minimalist “sensor to text” prototype.

In the concrete case, an ASCII art human body is shown on the screen which contains of the upper body and the lower body. Each part can have different configuration which is forming the overall tagging language. Similar to all multimodal generators, there is a rendered output in combination with the textual annotation. For example, the arms are in the up position and in parallel the tag on the screen is also “arm:up”
The reason for this symbol grounding demonstration is, that the tags are helping to reduce the complexity. From a technical perspective, a single picture consists of 5x5 cells and each can store an ASCII character from 0 to 127. So the amount of possible states is 5x5x127=3127. But the amount of sense making states given by the tag vocabulary is much smaller. The software has only 5 different states for the upper body and 3 possible states for the lower body, so the amount of possible tags is 5x3=15 The rendered output by the random generator fluctuates between one of these 15 states. The mapping from scene to text can be interpreted as a compression technique. Instead of analyzing all possible low level ASCII pictures, only the subset of annotated pictures is recognized.
----
# unicode stick figure
"""
output:
  O  
--|--
  |  
 / \
/   \
0 {'arm': 'sideways', 'legs': 'straddle'}
  O  
 /|\
/ | \
 | |
 | |
1 {'arm': 'bend', 'legs': 'down'}
\ O /
 \|/
  |  
 | |
 | |
2 {'arm': 'up', 'legs': 'down'}
  O  
| | |
| | |
 / \
/   \
3 {'arm': 'down', 'legs': 'straddle'}

"""
import random

class Game:
  def __init__(self):
    for trial in range(4):
      # new random number
      arm=random.randint(0,4)
      legs=random.randint(0,2)
      print(self.getscreen(arm,legs))
      print(trial,self.gettag(arm,legs))
  def getcat(self,catdict,value): # return: category in dict
    for i in catdict:
      if value<=i: return catdict[i]
  def getscreen(self,arm,legs): # return: text with drawing
    # input: arm [0..4], legs [0..2]
    result=""
    upper=[ # backslash \ collides with " in list
      ["  O  ","  O  ","  O  ","  O  ","\ O /"], # (close,down,smallside,sideways,up)
      [" /|\ ","| | |"," /|\ ","--|--"," \|/ "],
      [" ||| ","| | |","/ | \ ","  |  ","  |  "],
    ]
    lower=[
      [" / \ "," | | "," / \ "], # (close, down, straddle)
      [" | | "," | | ","/   \ "],
    ]
    for i in range(3):
      result+=upper[i][arm]+"\n"
    for i in range(2):
      result+=lower[i][legs]+"\n"
    result = result[:-1] # remove last "\n"
    return result
  def gettag(self,arm,legs): # tagging
    return {
      "arm":self.getcat({0:"close", 1:"down", 2:"bend", 3:"sideways", 4:"up"},arm), # arm
      "legs":self.getcat({0:"close", 1:"down", 2:"straddle"},legs), # legs
    }

if __name__ == '__main__':
  g=Game()

No comments:

Post a Comment