Growing a Language with Clojure and Instaparse

Creating your own programming language with Clojure and Instaparse is like building rainbows with s-expressions.  The Instaparse library is an elegant way of building executable parsers trees with pattern matching and standard EBNF notation for context-free grammars. Since this is my first foray into parser trees and grammars, I thought I would share my learnings in this post.

Starting with a Single Word

Let’s start with the simplest example:  a number.  When we start up our REPL in our brand new language, we want to be able to enter an integer, and have evaluate as an integer.

MyCoolLang> 1
1

Using the instaparse library, we define a number to be a regex matching an integer.

(ns coollang.parser
  (:require [instaparse.core :as insta]))
 
(def parser
  (insta/parser
   "number = #'[0-9]+'"))
 
(parser "1") ;=>; [:number "1"]

We now have a parser tree node that is of a type number. Pretty nice so far, but more rainbows are coming. You can make elegant transformations on the parser tree, and does them in a bottom up fashion, so you can use it for evaluation as well. In our simple number example, we are applying the read-string function on the :number node to turn it into a int.

(def transform-options
  {:number read-string})
 
(defn parse [input]
  (->> (parser input) (insta/transform transform-options)))
 
(parse "1") ;=> 1

Adding on spaces and vectors

Let’s build on a bit more. When someone enters in a sequence of numbers separated by spaces, it will be defined as a vector.

MyCoolLang> 1 2 3 4
[1 2 3 4]

We need to add the notion of spaces, spaces with numbers, and vectors into our grammar, as well as the rules
for evaluating these new nodes. Notice that we use the <> notation to hide the definition in the parser tree. The + means one or more times. The * means 0 or more times, and the | means or.

(def parser
  (insta/parser
   "expr = number | vector
    vector = snumber+ number
    <snumber> = (number space)*
    <space> = <#'[ ]+'>
    number = #'[0-9]+'"))
 
(parser "1 2 3 4") ;=> [:expr [:vector [:number "1"] [:number "2"] [:number "3"] [:number "4"]]]
 
(def transform-options
  {:number read-string
   :vector (comp vec list)
   :expr identity})
 
(defn parse [input]
  (->> (parser input) (insta/transform transform-options)))
 
(parse "1 2 3 4") ;=> [1 2 3 4]

Adding in operations

Pretty cool. We have numbers and vectors. Let’s see if we can do something fun like do some simple math on these vectors or numbers. We want it so when we type in + and some numbers, it adds them up.

MyCoolLang> + 1 2 3 4
10

Of course we need to further expand our grammar and rules.

(def parser
  (insta/parser
   "expr = number | vector | operation
    operation = operator space+ vector
    operator = '+' | '-' | '*' | '/'
    vector = snumber+ number
    <snumber> = (number space)*
    <space> = <#'[ ]+'>
    number = #'[0-9]+'"))
 
(parser "+ 1 2 3 4") ;=> [:expr
 ;                        [:operation
 ;                         [:operator "+"]
 ;                           [:vector [:number "1"] [:number "2"] [:number "3"] [:number "4"]]]
 
(defn choose-operator [op]
  (case op
    "+" +
    "-" -
    "*" *
    "/" /))
 
(def transform-options
  {:number read-string
   :vector (comp vec list)
   :operator choose-operator
   :operation apply
   :expr identity})
 
(defn parse [input]
  (->> (parser input) (insta/transform transform-options)))
 
(parse "+ 1 2 3 4") ;=> 10

Add a REPL

All we need now is a cool REPL to start working in:
We just need a main function to call our REPL, (Read – Evaluate – Print – Loop), and we are all set.

(ns coollang.repl
  (:require [coollang.parser :as parser]))
 
(defn repl []
  (do
    (print "MyCoolLang> ")
    (flush))
  (let [input (read-line)]
    (println (parser/parse input))
    (recur)))
 
(defn -main [&amp; args]
  (println "Hello MyCoolLang!")
  (println "===============")
  (flush)
  (repl))

Closing and Inspiration

I have enjoyed playing around and learning about creating programming languages with Clojure and instaparse.
It truly is a beautiful library. If you need any more inspiration to start creating your own programming language, may I recommend:

Now go forth and create!

Why Open a Coworking Space?

So I am in the midst of doing something a bit crazy and a bit wonderful at the same time. I am opening a coworking space in Loveland, OH called Locolo. It is a bit crazy because it has very little chance of being profitable, I have very little free time in my life to devote to such an undertaking, and I work full-time with awesome folks so I wouldn’t even be there during the day. Despite these very pragmatic reasons for not doing it, somewhere along the way I said F*** IT, I am doing it anyway. This blog post is an attempt to explain why.

Locolo

I want a coworking space to exist.

Coworking has changed my life. About three years ago, I became independent and starting doing development work out of my house. I found myself feeling increasingly lonely and isolated, working alone at my kitchen table day after day. I heard of a coworking space close to downtown called Cincy CoWorks, started by the visionaries Gerard Sychay and Bill Barnett. I joined and started going down there to work a few days a week. It was wonderful. Work became fun again. They day was peppered with serendipitous encounters and conversations the sparked my imagination and curiosity. I got involved in the Ruby community, usergroups, and eventually became part of the EdgeCase (and now Neo) company that makes me happy every day. In fact, the people that I met coworking are still an important part of my life today. So when I heard that Cincy Coworks suspended operations, I was a bit sad. I was sad that there was no longer an environment where the coworking magic could live. I had a small thought germinate in the back of my head then, that I would like to open a coworking space one day.

Someone told me it could not be done.

Sometimes there are clear catalysts in life. For me, it was someone telling me that a successful coworking space in Cincinnati could not be done. They may be right. I don’t know. But I do know, that the moment I heard that, something changed. I have this little part of me that can’t stand it when someone tells me I can’t do something. In fact, it is most likely one of the reasons that went into software development in the first place. That little part of me went a grabbed that small thought about starting a coworking place and dragged it out to the front where I couldn’t ignore it any more and said – DO IT.

A Lean Experiment

Serendipity happens. I had just finished reading Eric Ries’s book, The Lean Startup. It is a great book and highly recommend it. The main idea is using scientific methods for businesses. It got me thinking about what a coworking MVP, (minimun viable product), would be. I started looking around at spaces in Loveland just for fun, and stumbled into to one that would be perfect. I discovered The Loveland Art Studios on Main, a old school building turned into mostly art studios, but also housed a gym, spinning center, and training field for kids. The rent was very reasonable, had a 6 month lease, and already had wifi throughout the building. It was too perfect to pass up. I defined a hypothesis and experiment on the spot.

Hypothesis: There are enough people in the North and East part of Cincinnati interested to support a self-sustaining coworking space.
Experiment: Open a small coworking space for 6 months
Metrics: Monthly income – Monthly expenses

If at the end of the 6 months, the hypothesis is proven incorrect, I will accept my outcome and close up shop. However, even if the experiment is not successful, I will be capturing metrics on this and other experiments to save as artifacts to share with others that come after me. Hopefully, it will make it better and easier for the next person to launch coworking spaces. If you are interested in monthly updates on my metrics and experiments, ping me, and I will happily add you to my monthly distribution list.

Doing something you believe in

I don’t think this part needs much explaining. Doing something you believe in is worthwhile just in itself. Enough said.

Getting involved in the community is magic

Starting up a coworking space is all about building community. The very act of building something together creates magic. I am so thankful for all the people that have pitched in a helped me with their advice, encouragement, and assistance so far. Shout outs to Bill Barnett, Gerard Sychay, Paul Heinrich, Jacki Keys, Elizabeth Naramore, Chris Moore, Rob Biederhorn, Mason Stewart, and others. You all rock. really.

An Excuse for a Biscuit Tasting

biscuits

One of the fun perks of running a coworks is you get to have Open Houses and other excuses to eat biscuits. When I say “biscuits”, I mean biscuits in the British form, that translates into American as “delicious cookies”. So if you are in Cincinnati, sign up for the Open House of Locolo. Where you can not only see the space and meet awesome people, but also rate various cookies on important factors such as dunkablility and crunchiness.

Thanks & Toodles for now,

Carin

drone

The Joy of Flying AR Drones with Clojure

Clojure is fun.  Flying AR Parrot Drones are fun.  Put them together and there is pure joy.

Ever since I found out that you could program and control your drone over UDP, I couldn’t wait to try it out in Clojure.  I had dreams of controlling it with my Emacs REPL.  That dream came true and it has been a true joy to fly in a function language. This blog post shows some of the features that the clj-drone project has so far.  There is still a bit of work to go to make it complete.  But, I wanted to share and hopefully encourage others to start playing with it too.

The Simple Take-off and Landing

(ns clj-drone.example.simple
  (:require [clj-drone.core :refer :all]))
 
(drone-initialize)
;Use ip and port for non-standard drone ip/port
;(initialize ip port)
(drone :take-off)
(Thread/sleep 10000)
(drone :land)

Here is a video of executing the entire program in nrepl/ emacs

Controlling the Drone with Emacs/ Clojure REPL

Running the program all at once to control the drone is fun. But, I prefer to have more control over it in flight. I find being able to execute commands with keystrokes in emacs, the best way to do it. Here is a short video demonstrating control via the REPL. (Note: I am just doing simple take off / up and landings because of the constraints of flying indoors in my kitchen. There are many more moves you can do if you have more space.)

(ns clj-drone.example.moves
  (:require [clj-drone.core :refer :all]))
 
(drone-initialize)
;Use ip and port for non-standard drone ip/port
;(initialize ip port)
(drone-do-for 4 :take-off)
(drone-do-for 2 :up 0.3)
(drone-do-for 3.75 :fly 0.2 0 0 0.5) ; sprial
(drone :hover)
(drone :land)

Looking at the Navigation Data

You can also hook into the navigation feed. There are many drone states and properties to look at. There is a list of all the ones currently available on the github project site. There are also many more, including targeting information, that have yet to be added. There is a logging function that will pair down the navigation properties that you are interested in. The navigation data map as an atom, so it can be de-referenced anywhere in your program. Here is a short video of what the navigation logging data looks like when it is turned on.

(ns clj-drone.example.nav-test
  (:require [clj-drone.core :refer :all]
            [clj-drone.navdata :refer :all]))
 
;; logging is configured to go to the logs/drone.log file
 
(set-log-data [:seq-num :flying :battery-percent :control-state :roll :pitch :yaw
                :velocity-x :velocity-y :velocity-z])
(drone-initialize)
(drone-init-navdata)
(drone :take-off)
(drone :land)
(end-navstream)

Auto-piloting with goals and beliefs

Inspired by reading John McCarthy’s paper on Ascribing Mental Qualities to Machines, the drone can also auto-pilot itself based on goals and beliefs about its streaming navigation data. You define belief-actions and then goals. Finally, you set a vector of the current goals for the drone to process. You can see an example here of the AR drone having three goals: Take off, Get to a cruising altitude, and then land. It does it solely by inspecting and acting on the streaming navigation data.
Code for the program is here: https://github.com/gigasquid/clj-drone/blob/master/examples/nav_goals.clj

Go Fly!

I have had a lot of fun so far working on this project. I hope that you get a chance to play with it too. The project is still very young, so stay tuned for updates and, of course, pull requests are always welcome :)

Hobby Languages for Clojurists

I spend most of my work day in Ruby and CoffeeScript. However, my true love belongs to Clojure, which I consider my “hobby” language right now. I started to wonder, what are the “hobby” languages for people who spend most of their work day with Clojure. My informal twitter poll revealed selection as diverse and interesting as the Clojurists themselves.

Developers Who Enjoy Clojure Also Enjoy:
(In no particular order)

and of course MORE Clojure

7 McCarthy Papers in 7ish Weeks #5 & #6 – SDFW Tic-Tac-Toe

SDFW Tic Tac Toe

This holiday edition blog post covers two McCarthy papers instead of just one.  We will be talking about Free Will – Even for Robots and the companion paper Simple Deterministic Free Will.

In which we deftly sidestep the philosophers

We know that computers and programs are completely deterministic.  A philosophical question is whether we, as humans are ruled by determinism, (although complex it may be), or not.  If we take the decision that humans are deterministic, then we can argue that either there is no free will – or that free will is “compatible” with determinism.  Philosophers, of course, could discuss such questions interminably, trying to get a theory to fit for all people and all occasions.  Thankfully, McCarthy takes a very admirable and practical view on free will.  Let’s try out something simple for a computer program and see how it works.  He explores a philosophy ”Compatibilist’s” view, which regards a person to have free will if his actions are decided by an internal process, even if this process itself is deterministic.  But by exploring this view with computer programs, he makes clear:

… I don’t need to take a position on determinism itself.

 

Simple Deterministic Free Will

So what would Free Will look like for a machine. How do we go about defining it? McCarthy proposes the idea of Simple Deterministic Free Will. The main idea is that the mechanism of free will is broken up into two parts. The first part looks at the possible actions and the consequences of those actions, and the second part decides which of those actions are preferable and does them. He gives the example of a chess program:

People and chess programs carry thinking about choice beyond the first level. Thus “If I make this move, my opponent (or nature regarded as an opponent) will have the following choices, each of which will give me further choices.” Examining such trees of possibilities is an aspect of free will in the world, but the simplest form of free will in a deterministic world does not involve branching more than once.

So perhaps we could find an example that is simpler than chess to work with …

…it would be interesting to design the simplest possible system exhibiting deterministic free will. A program for tic-tac-toe is simpler than a chess program, but the usual program does consider choices.

Simple Deterministic Free Will Tic Tac Toe

So to explore McCarthy’s idea of Simple Deterministic Free Will, I decided to try to construct a game of Tic Tac Toe with SDFW principles. Coincidentally, my six year old daughter, just learned how to play Tic Tac Toe as well. I wanted to construct a program that would “reason” about the game as would a child. Even though the game of Tic Tac Toe is simple enough to have all the possibility trees of moves completely solved, this is not how a my daughter approaches the game. Each time it is her move, she only looks one move ahead to see if she can win three in a row, or if she needs to block her opponent from winning the next move.

My Tic Tac Toe Program has Beliefs

It has three beliefs to be precise. It believes that no one is going to win, or it is going to win, or its opponent is going to win.

(def beliefs
  { :win "I am going to win."
    :lose "My opponent is going to win."
    :noone "No one is going to win."})

McCarthy thinks that ascribing programs beliefs can be useful. One of the reasons is that it helps us as humans, reason and debug our programs. I definitely saw the value of this when I was trying to debug my tic tac toe game. After it failed to block my winning move, I could see what its false belief was – ah – it thought that “No one is going to win”. I wrote another failing unit test to fix its bad belief.

My Tic Tac Toe Program Looks to See What Its Possible Actions and Preferences Are

It looks at the board and computes all its possible next moves. Then it computes all the possible next moves of its opponent. It looks at the consequences of these moves by assigning a belief from one of its three beliefs. Next, it ranks the moves according to the preference of its beliefs.

(def belief-action-preferences
  { (beliefs :win) 1
    (beliefs :lose) 2
    (beliefs :noone) 3})

It then chooses the move to take that has the highest rank. If it believes that no-one is going to win, I opted to have it choose a random move from the list of possible choices. But this randomness is completely arbitrary on my part and not necessary to SDFW at all.

Why ClojureScript is Awesome

I coded the core tic-tac-toe program in Clojure, but then I thought that having a web page UI would be nice for my daughter to play with. So, I just took the game logic and moved it to ClojureScript. Let me say that again slower… I used the same code on the server on the browser. Awesome. Using the lein-cljsbuild crossover support, I was able to simply configure my UI ClojureScript code to access my regular clojure game engine. Very cool. I was also very pleased to work with the https://github.com/levand/domina DOM manipulation library for ClojureScript.

End Result

It was a fun project that let me play with ClojureScript, explore McCarthy’s free will for robots, have some very interesting conversations about free will with my co-wokers and code and coffee friends, and make a game for my daughter to play and enjoy. If you are interested in checking out the program for yourself – http://gigasquid.github.com/sdfw-tic-tac-toe/. The last belief is displayed at the bottom. I have only tried it on Chrome, so beware. Finally, if you find any false beliefs, feel free to submit a pull request to https://github.com/gigasquid/sdfw-tic-tac-toe.

P.S. If you are wondering, I drew the awesome graphics all by myself.

7 McCarthy Papers in 7ish Weeks – #4

Reading Artificial Intelligence, Logic, and Formalizing Common Sense, led me surprisingly to reflect on, not only logic and philosophy, but also the history and present state of AI.

Fist let’s look at the kind of AI that McCarthy is describing in paper. He talks of a program that can use common sense knowledge about the world around it and have this knowledge structured well enough that it can be reasoned about mathematically. In fact, he describes four levels of logic:

  1. The computer program has its “beliefs” completely defined by its internal state. If you are confused by the term “beliefs”, it refers to ascribing mental qualities to machines. In his famous example, a thermostat has three beliefs: the room is too hot, the room is too cold, and the room is just right.
  2. The programs express their beliefs in sentences in machine memory. However, they do not use ordinary logic. They use other methods like rules and procedures.
  3. In addition to expresses their beliefs in sentences, they also use first order logic and logical deduction to reach their conclusions.
  4. The fourth level is still a goal today. It is to have the program represent general facts about the world as logical sentences. Furthermore, to have a database of these commonsense facts that programs can share.

Let’s step back now for a moment, to a excerpt from the very beginning of the paper:

One path to human-level AI uses mathematical logic to formalize common-sense knowledge in such a way that common-sense problems can be solved by logical reasoning. This methodology requires understanding the common-sense world well enough to formalize facts about it and ways of achieving goals in it. Basing AI on understanding the common-sense world is different from basing it on understanding human psychology or neurophysiology.

This approach to AI is just one approach. It is commonly referred to as a “top down” approach. In the early years of AI it was the dominant way of thinking about things. Looking back at the history of AI, the golden years were full of optimism, (and funding), that this was the path to achieving fully intelligent machines. Disenchantment with unfulfilled promises, led to the first AI winter. There was a rise of expert systems later on that limited their scope to small domains and avoided the common sense problem, but eventually ended in a second AI winter and ushered in our current world. This basic approach is an opposite ground-up view of AI. It uses neural networks and statistics from a physical inspiration. Some of this inspiration is from human neurophysiology, some of it is from insect and animal world, but simplicity behavior of a “body” is emphasized. With the advances in hardware and computing power today, the innovations and accomplishments have been breath taking.

A good example of the two approaches can be seen in my Roomba. A top down approach, would require my Roomba to have a complete room model in its program. It would have to understand what my couch was, where the doors where and have logically reasoning to direct it to which areas to clean and when to stop cleaning and recharge itself. The creators of the Roomba were from the opposite camp of thinking. They took the simpler behavior approach of having the Roomba just take a random walk in the room and turn around when it ran into an obstacle. It took a bit longer to get the room clean in such a random fashion, but not having to deal with the overhead of a mental model was well worth the trade off.

Noam Chomsky recently argued that the pendulum has swung too far in favor of this simplified behaviorist approach. Even in the light of Norvig’s response, I think Chomsky has a point. We would do well to search for gems of true intelligent systems in the historical landscape of the AI Winter. Some of the breakthroughs of current sheer computing power and new modeling techniques, might yield great fruits.

One of the comments by nagelonce, on the Chomsky article, puts this very well:

AI has a hole in the middle. There’s top-down AI, which focuses on abstractions and reductionism. There’s bottom-up AI, which focuses on reactive systems and the front end of visual processing. They have yet to meet in the middle. They are, however, much closer to doing so than they were twenty years ago.

If you are interested in checking out a top-down open source AI project, take a look at OpenCyc. After a brief look at it the other night, it suffers from the lack of love and documentation. But, I can also see the promise of McCarthy’s common sense knowledge and logic system, covered in a thin layer of snow.

7 John McCarthy Papers in 7 Weeks #3

In which I realize that John McCarthy is the father of the Semantic Web

I have realized that it generally takes me more than a week to read a paper, reflect on it, experiment, and finally blog about it. But, since I made up the rules of the project in the first place,  I am not going to dwell on the time frame and just move forward with the next paper.

When I picked the paper First Order Theories of Individual Concepts and Propositions, I thought to myself that it would be a rather narrow, more self contained paper than the first two broad papers that I read. However, the connections that it drew to current technologies caught me by surprise.

The main point of the paper is how to formalize language statements, including concepts, so that a computer can apply mathematical rules and logic to them. McCarthy had mentioned concepts and thoughts in his “Ascribing Mental Qualities” paper, where he says:

“..the deep structure” of a publicly expressible thought is a node is the public network.”

This immediately brought to my mind the Semantic Web.   In Semantic Web, data is structured in RDF statements as triples – <subject> <predicate> <object>.  The data contained in these triples are structured and described so that machines can derive context and meaning from it.  For example, instead of just putting  ”cat” as the subject.  In RDF you would use http://dbpedia.org/resource/Cat as the subject. Which, is pretty much dead on McCarthy’s expressible thought as a node in the public network.

McCarthy uses the following example to illustrate how to construct First Order statements.

Frege (1892) discussed the need to distinguish direct and indirect use of words. According to one interpretation of Frege’s ideas, the meaning of the phrase “Mike’s telephone number” in the sentence “Pat knows Mike’s telephone number” is the concept of Mike’s telephone number, whereas its meaning in the sentence “Pat dialed Mike’s telephone number” is the number itself. Thus if we also have Mary’s telephone number = Mike’s telephone number”, then Pat dialed Mary’s telephone number” follows, but “Pat knows Mary’s telephone number does not. phone number” is the number itself. Thus if we also have Mary’s telephone number = Mike’s telephone number”, then Pat dialed Mary’s telephone number” follows, but Pat knows Mary’s telephone number does not.

McCarthy express the statement “Pat knows Mike’s telephone number” as:

true Know(Pat; Telephone Mike)

He then uses more formalized statements to derive logic statements and reasoning from this example.

At this point, I was seeing more connections to the field of Semantic Web. Expressing data in RDF/ OWL gives computers exactly this type of logic and reasoning ability too.

So how would you go about expressing “Pat knows Mike’s telephone number” in Semantic Web data form?   This question is not a simple one,(at least for me),  because there are so many different ways that you can construct RDF.  The choices were a bit overwhelming.

One option might be to use RDF reification, in which you can make statements about statements.  Another option might be using OWL classes and properties.  There are some excellent answers when I posed the question on http://stackoverflow.com/questions/13114018/how-to-state-pat-knows-mikes-telephone-number-in-rdf-owl.

Indeed, it seems that we can express individual concepts and propositions in Semantic Web form quite well.  I had not realized that John McCarthy is the father of Sematic Web as well.

In closing, he speaks of AI Applications. Reasoning and predication are familiar applications that we use today. However he hits upon one that is quite interesting to me. That is “..determining that it does not know something or that someone else doesn’t.” This is not a common area to think about with computer programs. We are usually much more focused on what it does know and how to reason about it. But, if we are really to build intelligent, learning systems, we need to be able to identify what it does not know as well.  Perhaps then the AI can help us humans, who are pretty bad at that too.

7 John McCarthy Papers in 7 Weeks – #2

Well, life threw me for a bit of a loop and delayed my post on my second paper. So I am going to consider this a “weekish” period of time and just continue on.

I read Towards a Mathematical Science of Computation. It is quite a meaty paper and was certainly a lot to digest. Here are some highlights that I gleaned from it.

How can a Mathematical Science of Computation help in a practical way?

McCarthy points out that while it is hard to predict practical applications ahead of time. A couple of could be

  • Provide a systematic way to create of programming language. Rather than just arguing and arbitrarily adding language features whilly nilly.
  • “It should be possible to eliminate debugging. Debugging is the testing of a program on cases one hopes are typical, until it seems to work. This frequently is in vain.”

This last point of being able to eliminate debugging really stuck with me. Even with the best of TDD and test suites, we as developers still struggle with the testing of programs against what we hope is “typical”. Over the past years we have improved our techniques and made our programs more robust, but it would certainly be nice to be able to prove a program correct.

If fear that even if this was possible, it would not be enough. At least in my experience, a considerable amount of debugging happens at the human level:

  • The translation of understanding of what the human product owner wants to what the software developer can understand.
  • The human product owner’s understanding of what they want in the first place.

In my experience, we have just as much trouble (or even more) stating the problem for the program as we do in attempting to solve and prove that it works.

What we already know that can be applied to a Mathematical Science of Computation

  • The existence of Turing’s Universal computers
  • The existence of classes of unsolvable problems

Perhaps a sonic screwdriver will help?

McCarthy then goes on to add another tool to the Mathematical Science of computation toolbox. He shows that conditional expressions can be defined recursively. Then he expands this to relate to programs/computers that can be defined recursively.

Can a man make a computer program that is as intelligent as him?

Here is the real question. McCarthy has us consider the following problem of whether a program on a computers with unlimited memory will ever stop:

A procedure does the following

  1. If the number is in a creative set then return -> yes.
    If a number is not in a creative set then return -> no
    or it may run indefinitely

  2. There is no procedure while will always return -> yes when the answer is yes. and return -> no when the answer is no

It is a bit depressing that we can’t figure out which ones that are really no and which ones run forever. But don’t give up. We can just try to do the best we can. Emil Post discovered that whenever we try to do the best we can, one can always improve upon it. He showed that given any procedure, he could make a new procedure that solved all the previous cases plus some new ones. McCarthy pointed out that this process, even though it is really like trying to count the biggest ordinal number, can be mechanized. So really there is no reason why a machine could not continually improve its own program.

In summary, McCarthy’s own words are the best:

“In conclusion, let me re-assert that the question of whether there are limitations in principle of what problems man can make machines solve for him as compared to his own ability to solve problems, really is a technical question in recursive function theory.”

7 John McCarthy Papers in 7 weeks – #1 How My Thermostat has Beliefs and Goals

http://www.flickr.com/photos/midnightcomm/447335691/sizes/n/in/photostream/

http://www.flickr.com/photos/midnightcomm/447335691/

Ascribing Mental Qualities to Machines or How My Thermostat has Beliefs and Goals

After reading John McCarthy’s paper this week Ascribing Mental Qualities to Machines, I can honestly say that it has changed the way I think about programs and most certainly thermostats. For you see, I realize now that my thermostat has beliefs and goals. No, it does not have beliefs about what the weather is going to be tomorrow, or when the next George R.R. Martin book is going to come out. But it does have beliefs. It has three of them to be exact:

  • The room is too hot
  • The room is too cold
  • The room is OK

It also only has one goal:

  • The room should be OK

Wat?

Why should we think of a simple thermostat this way? It is not very complex. In fact, we can completely understand its state and reason about its behavior by looking at its small and complete program listing. What benefit can there possibly be to endow the humble thermostat with its own beliefs and goals?

Start Small

Let’s step back. We are talking about designing and building intelligent systems, not just programs. The example of a thermostat is indeed small, but let us try out our ideas on a easy to understand system first. Later we can consider applying it to more complex systems.

Beliefs and Goals are Easier to Understand and Reason About

Using a higher level construct to express state can make it easier to reason and understand intelligent systems. It also is useful in describing states that are not completely known or have portions that are not easily observable. In short, defining a program’s state in terms of beliefs and goals may be closer to our natural way of thinking. When I consider my co-worker sitting next to me. I cannot hope to observe the complete mental state of him at that moment. Although I could hope to describe it at a high level with beliefs and goals. I could even hope to predict future behavior with this knowledge of his beliefs and goals, (which most likely has to do with the goal of eating more bacon).

Easier to Debug and Correct

Once we have a higher level model of a systems mental state and behavior. It would be easier to debug, communicate, and correct problems. For example, If I come home and the room is way too cold, I could look for the problem in terms of beliefs and goals. Does the thermostat have a faulty belief? Or did it have a good belief that the room was too cold? If so, then the problem was that it could not act on its belief to tell the furnace to turn on. If it could communicate and know the problem, perhaps it could message me and I could arrange a service call, or it could even self-correct. Another example, is my recent experience with my Roomba. I came home the other day to find my Roomba had not returned to its charging station after its scheduled cleaning. Instead, it was stopped under my bed. What went wrong? Did it believe that the battery was low? Or was there some other faulty belief? It would be nice if it could tell me.

Delving Further – What is a belief?

McCarthy talks about defining a belief as a function of the system’s state. For each state, there are beliefs that can be expressed as a sentences in a language. The machine does not need to understand the meaning and concepts in the English, French or any given language. That is for us to interpret. The important part is that there is a mapping of the state to this sentence. Taking our humble thermostat for an example:

(defn thermo-belief [temp]
  (cond
    (> temp 70) "The room is too hot."
    (< temp 70) "The room is too cold."
    :else "The room is OK."))

We can test our thermostats beliefs with something like:

(deftest thermo-beliefs-tests
  (is (= "The room is too hot." (thermo-belief 71)))
  (is (= "The room is too cold." (thermo-belief 69)))
  (is (= "The room is OK." (thermo-belief 70))))

This testing or criticizing the belief structure of the thermostat is what McCarthy called a Second Order Structural definition for mental qualities. This differs from a First Order Structural definition in that, rather than criticizing or testing an individual belief, he sought to describe them by testing/ criticizing the structure of the whole set of beliefs.

In the example of our thermostat, to have a “good” belief structure, in accordance with Second Order Structural definition, it the must have some consequences or actions of it beliefs. Furthermore, these actions most be consistent with its goals.

It might be expressed in code like this:

(defn thermo-action [belief temp]
  (case belief
    "The room is too hot." (dec temp)
    "The room is too cold." (inc temp)
    "The room is ok." temp))

In this case, the action of a belief is returning a new state, the temperature. Our thermostat could issue a command to the furnace to turn on. But, let us keep it simple for the moment and just think of its action directly changing the temperature. Now, our believing thermostat program can be described as having beliefs as well as taking actions from them.

(defn thermostat [temp]
  (thermo-action (thermo-belief temp) temp))
 
(thermostat 33) ;=> 34

So now we have a thermostat that has beliefs and consequences from these beliefs. We still need to figure out how to test that its belief system is consistent with its goals. Thankfully, it only has one goal to keep it simple. The goal is that the room should be OK.

(def goal 70)

Let’s say that the thermostat is doing what it believes will achieve its goals, if the new temperature is closer to its goal.

(defn distance-from-goal [g t]
  (Math/abs (- g t)))
 
(distance-from-goal goal 80) ;=> 10
 
(defn closer-to-goal [g t nt]
  (&gt; (distance-from-goal g t)
    (distance-from-goal g nt)))
 
(closer-to-goal goal 75 73) ;=> true
(closer-to-goal goal 75 76) ;=> false
(closer-to-goal goal 56 57) ;=> true

We can now construct a test to see if the thermostat actions are consistent with its goals.

(deftest themo-behavior-test
  (is (closer-to-goal goal 4 (thermostat 4)))
  (is (closer-to-goal goal 74 (thermostat 74)))
  (is (closer-to-goal goal 75 (thermostat 75)))
  (is (closer-to-goal goal 56 (thermostat 56))))

Given this particular thermostat example, we could even recursively show that it will reach its goal:

(defn thermo-simulation [g s]
(if (= g s) "Woo hoo!"
(thermo-simulation g (thermostat s))))
 
(thermo-simulation goal 73) ;=>; "Woo hoo!"
 
(deftest thermo-goal-achievement-test
(is (= "Woo hoo!" (thermo-simulation goal 73)))
(is (= "Woo hoo!" (thermo-simulation goal 100)))
(is (= "Woo hoo!" (thermo-simulation goal 33)))
(is (= "Woo hoo!" (thermo-simulation goal -33))) )

Our thermostat’s beliefs are good!

What if ….

The way that McCarthy explains the Second Order Structural definition as criticizing and testing beliefs, made me start thinking about test driven design. What if we were to start thinking and designing our programs with this testing of belief and goal structure? It could be IDD (Intelligence Driven Design) rather than TDD/ BDD. From experience, I know that TDD has changed the way that I think about coding and resulted in cleaner and more robust programs. I wonder what effect IDD could have on our program’s creation and perhaps the future of AI. Could changing the way we approach our definition of state and behavior change our software to become more intelligent? Wait a minute. If we write a test system to criticize another programs beliefs and goals, wouldn’t we be designing a program that would have beliefs about another program’s beliefs?

My brain get exploded.
It is in fact, turtles all the way down :)