OpenCogPrime:Combo Language Overview

From OpenCog

An Overview of the Combo Language

This page and the two that it supervenes over

give a high-level conceptual discussion of the Combo language, which is a simple programming language created for representing the procedure objects that ground OpenCogPrime:GroundedProcedureNodes.

The Combo language is constantly evolving and the reference point for the details is the OpenCog : Combo page, which is supposed to be kept in coordination with the code. This page and its children are intended to focus more on the overall ideas underlying Combo.

The name "Combo" originated because the first version of Combo made heavy use of combinatory logic ideas. Subsequent versions have drifted a bit from this origin but the name has been retained because it sounds sort of wizzy, it's still relevant (as combinatory logic ideas are still present), and no clearly better name has come up.

Finally an authorial/historical note: Unlike most pages of this OpenCogPrime wiki, the initial version of this one was not mainly written by Ben Goertzel. Rather, the first draft was assembled by Ben Goertzel from prior documents written by Moshe Looks, the primary creator of the Combo language.

The "contents" of most OCP nodes is given by the relationships in which they're involved.

Basic perceptual node types are one exception to this: the contents of an NumberNode is a number, the contents of a CharacterNode is a character, etc. The other exceptions are the ProcedureNode types, SchemaNode and PredicateNode. In particular, these node types have subtypes GroundedSchemaNode and GroundedPredicateNode. These nodes correspond to Procedure objects, which wrap up objects called Combo trees. (Implementation-wise, in OCP the Procedure objects are stored in a special structure called the ProcedureRepository, in which they are indexed by the Handle of the Atom that corresponds to them.) These Combo trees are the objects that OCP uses to directly guide the actions that it learns how to do (both internally and externally). When inference or evolution processes figure out how to carry out some action, the knowledge achieved is stored not only in the form of declarative knowledge suitable for ongoing reasoning, but also in the form of procedural knowledge suitable for actual execution (i.e. Combo trees). The purpose of this page and its children is to give rough indications of the answers to a few basic, obvious questions about Combo trees: how they are constructed, how they are interpreted, and how they relate with the rest of OCP.

Structurally, Combo trees are data structures that are trees or dags (directed acyclic graphs) whose internal nodes are either

  • @ symbols (denoting "function application," as defined in the earlier discussion of combinatory logic)
  • function labels (indicating that the function denoted should be applied to the arguments denoted by the child nodes), or
  • LIST operators (indicating that the child nodes should be arranged in a list)

and whose leaf nodes are either

  • Elementary data items (e.g. numbers, characters or strings), or
  • Functions, known as "elementary schemata" (elementary procedures)
  • Input variables

The collection of elementary schemata used is known as the "elementary schema vocabulary." The precise optimal schema vocabulary for OCP is only going to be determined based on experimentation, and may vary based on the given OCP system's application domain. In this chapter we will run through a significant portion of our working set of elementary schema functions, explaining the use of each one and giving examples.

Textual Representations of Combo

Raw Combo

Combo trees may be represented directly as strings using a set of typographical conventions, and this gives rise to a simple programming language, which we call Combo, or else (if there is a need to distinguish it from other languages built on top of Combo) "raw Combo."

Raw Combo is a bare-bones programming language created with the following primary design constraints: to allow complex programs to be represented concisely, and to be amenable to evolutionary programming and probabilistic reasoning methods. These constraints have led to a unique style of programming, in which the fundamental unit of programming is the function (a lambda-abstraction), but within function definitions, combinators (abstract tree rewriting rules) are frequently used, rather than lambda abstractions.

It is actually possible to write programs in the raw Combo language, although we don't recommend it except for very small and simple cases. Raw Combo has the advantage of mapping directly into OCP structures, but it has many disadvantages from a usability-by-humans perspective, for example the lack of local variables.

The lack of usability of raw Combo has led to a couple efforts to append more syntactic sugar onto the Combo framework.

The Sasha Language

In a 2005 collaboration, Lukasz Kaiser, Moshe Looks, Ben Goertzel and others created a language called Sasha, which has a much higher level of usability than raw Combo and compiles into the latter. As compared to raw Combo, Sasha can more easily be used to write nontrivial complex OCP schemata and predicates. However, development on Sasha was frozen in early 2005 due to lack of funding, and in practice when coding schema by hand needed to be done for the NCE, we have used raw Combo rather than Sasha, so far.

There are pages on the OCP wiki site informally describing Sasha:

but unless Sasha development is resurrected these will be of purely historical interest.

Combo LISP

In 2007-2008, some work was done by Moshe Looks toward the end of creating a new LISP interpreter/compiler that outputs Combo trees. However, this project was suspended in Spring 2008 in favor of an alternate approach of taking an existing LISP interpreter and modifying it to output Combo trees. This work is currently in progress.

Making Combo Richer

Currently Combo trees are fairly limited in their representational mechanisms. Of course, they can represent anything (combinatory logic being a Turing-complete formalism), but the challenge is to craft a language in which cognitively simple procedures have simple (compact, easily vary-able and manipulable) representations.

Turner Combinators

One potential way to make Combo richer is simply to add powerful combinators to the elementary schema vocabulary. For instance, the so-called "Turner combinators" have a lot of power and we have not yet experimented with them in the OCP context.

Local Variables

One of the shortcomings of the Combo versions implemented so far has to do with local variables (a separate, though related, issue to input variables ... note that a fully pure combinatory logic based language would have only one input for each program, whereas we have never made a Combo version that pure, always allowing the possibility of multiple input variables). While in many cases it is preferable from a standpoint of automatic program learning and inference to avoid use of local variables, in some cases it provides a dramatic increase in simplicity, such that avoiding them begins to seem more dogmatic than elegant. But on the other hand, if one is going to incorporate local variables in Combo, one needs to decide how to do it, and there are many possibilities.

The approaches we've discussed in most detail are described on the page LocalVariablesInCombo.

Making Combo Programs Efficient

At the moment (July 2008) the Combo interpreter used in the OCP codebase is not tremendously efficient, which is an issue that needs to be resolved eventually. For instance, in the long term we would like to rewrite the OCP MindAgents in (some variant of, or something that compiles into) Combo, but that would not be pointful now because a MindAgent written in Combo would run too slowly to be practical. This sort of issue will get practical attention within the OCP project once the cognition code is mature enough to adapt, improve and learn from the Combo versions of MindAgents.

Supercompiling Combo Programs

An interesting approach to solving this problem is to "supercompile" Combo into efficient C++ code for rapid execution. Some preliminary experiments of this nature were done in 2004, supercompiling simple Combo programs into efficient Java using the Java Supercompiler created by Supercompilers LLC (see the whitepapers at for an overview of supercompilation technology). These experiments are outside the scope of the OCP WikiBook per se, but are informally described on some other pages on the OCP wiki site:

That work, done in 2004, was rather promising and will be written up for publication when someone finds the time and motivation. Unfortunately, due to funding issues it was never really completed.