OpenCog uses many different kinds of Atoms. The name "Atom" was chosen because of the resemblance of OpenCog Atoms to the concept of atoms in mathematical logic; this is explained on the Atom page. Unlike most typical applications in mathematical logic, OpenCog Atoms are typed. This allows them to be assembled more clearly, and their roles to be more easily understood.
The two most basic types of atoms are the Node and the Link. Nodes are identified by their names or labels; that is the only property that they have. Nodes, once placed in the AtomSpace, are unique: there can only ever be one node of a given type and name. Links are identified by their contents, which are ordered or unordered sets of other atoms. Links do not have any name or label other than their contents: a link is uniquely identified by it's type and it's contents.
The atom type category lists all documented atoms currently in use. This page provides a general introduction to some of the types in current use. It is not a complete list: new types are easily invented, and the various OpenCog books mention Atom types that are not implemented or have been implemented in a somewhat different way. The partial nature of the list given here reflects a more general point: The specific collection of Atom types in an OpenCog system is bound to change as the system is developed and experimented with. OpenCogPrime specifies a certain collection of representational approaches and cognitive algorithms for acting on them; any of these approaches and algorithms may be implemented with a variety of sets of Atom types. The specific set of Atom types in the OpenCog system currently does not necessarily have a profound and lasting significance -- the list might look a bit different in five years, based on clearer understandings and detailed design requirements.
There is a type system for working with atom types: that is, the type of an atom can itself be specified using other atoms: specifically, by using the TypeNode, the SignatureLink, the ArrowLink and the DefinedTypeNode as type constructors. Polymorphic types can be specified using the TypeChoice link. The type system allows for basic error checking, such as with the type checker, and more generally, it allows type-logical reasoning and inference to be performed on atom signatures.
New Atom types can be dynamically created, using the classserver in the AtomSpace. The list of staticly-defined atom types are given in multiple different atom_types.script files; the core one is here. From these, the C++, scheme and python bindings are auto-generated. The bindings are generated by the lib/OpenCogAtomTypes.cmake file.
Some Basic Atom Types
First, a ConceptNode does not necessarily refer to a whole concept, but may refer to part of a concept -- it is essentially a "basic semantic node" whose meaning comes from its links to other Atoms. It would be more accurately, but less tersely, named "concept or concept fragment or element node." A simple example would be a ConceptNode grouping nodes that are somehow related, e.g.
ConceptNode: C InheritanceLink (ObjectNode: BW) C InheritanceLink (ObjectNode: BP) C InheritanceLink (ObjectNode: BN) C ReferenceLink BW (PhraseNode "Ben's watch") ReferenceLink BP (PhraseNode "Ben's passport") ReferenceLink BN (PhraseNode "Ben's necklace")
indicates the simple and uninteresting ConceptNode grouping three objects owned by Ben (note that the above-given Atoms don't indicate the ownership relationship, they just link the three objects with textual descriptions). In this example, the ConceptNode links transparently to physical objects and English descriptions, but in general this won't be the case -- most ConceptNodes will look to the human eye like groupings of links of various types, that link to other nodes consisting of groupings of links of various types, etc.
There are Atoms referring to basic, useful mathematical objects, e.g. NumberNodes like
NumberNode #4 NumberNode #3.44
The numerical value of a NumberNode is explicitly referenced within the Atom.
A core distinction is made between ordered links and unordered links; these are handled differently in the Atomspace software. A basic unordered link is the SetLink, which groups its arguments into a set. For instance, the ConceptNode C defined by
ConceptNode C MemberLink A C MemberLink B C
is equivalent to
SetLink A B
On the other hand, ListLinks are like SetLinks but ordered, and they play a fundamental role due to their relationship to predicates. Most predicates are assumed to take ordered arguments, so we may say e.g.
EvaluationLink PredicateNode eat ListLink ConceptNode cat ConceptNode mouse
to indicate that cats eat mice.
Note that by an expression like
ConceptNode C ReferenceLink W C WordNode W #cat
since it's WordNodes rather than ConceptNodes that refer to words. (And note that the strength of the ReferenceLink would not be 1 in this case, because the word "cat" has multiple senses.) However, there is no harm nor formal incorrectness in the "ConceptNode cat" usage, since "cat" is just as valid a name for a ConceptNode as, say, "C."
We've already introduced above the MemberLink, which is a link joining a member to the set that contains it. Notable is that the truth value of a MemberLink is fuzzy rather than probabilistic, and that PLN is able to inter-operate fuzzy and probabilistic values.
SubsetLinks also exist, with the obvious meaning, e.g.
ConceptNode cat ConceptNode animal SubsetLink cat animal
Note that SubsetLink refers to a purely extensional subset relationship, and that InheritanceLink should be used for the generic "intensional + extensional" analogue of this -- more on this below. SubsetLink could more consistently (with other link types) be named ExtensionalInheritanceLink, but SubsetLink is used because it's shorter and more intuitive.
Pattern matching, graph re-writing
In order to do any sort of useful computation within the atomspace, one must have a way of spotting a particular pattern, and creating a new/different pattern. This is accomplished by using the BindLink and the ImplicationLink. It can be thought of as a graph re-write rule, or as an if-then statement or as an implication A -> B. That is, A->B means "if(A) then (B)" where A and B are hypergraphs themselves. ImplicationLinks take two arguments: A and B. Either can be arbitrarily complicated as graphs.
Attention: there are two ways of working with data in the AtomSpace: declaratively, and functionally/procedurally. In the declarative mode, one merely asserts facts. In the functional/procedural mode, one asserts facts that can also be evaluated, providing a result. The ImplicationLink is declarative. The BindLink is functional: it describes a pattern-query that can actually be run, to obtain an answer: a list of all matching graphs. The below talks about the ImplicationLink; in practice, many/most users heavily depend on the BindLink.
There are links representing Boolean operations AND, OR and NOT. For instance, we may want to say "if (young and beautiful) then attractive". This would be:
ImplicationLink ANDLink ConceptNode young ConceptNode beautiful ConceptNode attractive
Note: Two ConceptNodes that are linked by an AND represent a new ConceptNode (the intersection of the two concepts). However, the above doesn't express who it is that is young and attractive. We really want pattern matching to allow "variable holes" in the pattern. That is "if (X is young and X is beautiful) then X is attractive" where X can be thought of a "hole" or a "blank" in the expression: anything that fits in this hole will provide a match to the template "X is young and X is beautiful" and thus allow the graph re-write "X is attractive" to occur. The variable X is indicated with a VariableNode:
AverageLink $X ImplicationLink ANDLink EvaluationLink young $X EvaluationLink beautiful $X EvaluationLink attractive $X
NOTLink is a unary link, so e.g. we might say
AverageLink $X ImplicationLink ANDLink EvaluationLink young $X EvaluationLink beautiful $X EvaluationLink NOT EvaluationLink poor $X EvaluationLink attractive $X
ContextLink allows explicit contextualization of knowledge, which is used in PLN, e.g.
ContextLink ConceptNode golf InheritanceLink ObjectNode BenGoertzel ConceptNode incompetent
says that Ben Goertzel is incompetent in the context of golf.
TypedVariableLink VariableNode $X TypeNode ConceptNode
which specifies that the variable $X can be grounded only by nodes of type 'ConceptNode'.
Variables are handled via quantifiers; the default quantifier being the AverageLink, so that the default interpretation of
ImplicationLink InheritanceLink $X animal EvaluationLink PredicateNode: eat ListLink $X ConceptNode: food
AverageLink $X ImplicationLink InheritanceLink $X animal EvaluationLink PredicateNode: eat ListLink $X ConceptNode: food
The AverageLink invokes an estimation of the average TruthValue of the embedded expression (in this case an ImplicationLink) over all possible values of the variable $X. If there are type restrictions regarding the variable $X, these are taken into account in conducting the averaging. ForAllLink and ExistsLink may be used in the same places as AverageLink, with uncertain truth value semantics defined in PLN theory using third-order probabilities. There is also a ScholemLink used to indicate variable dependencies for existentially quantified variables, used in cases of multiply nested existential quantifiers.
EvaluationLink and MemberLink have overlapping semantics, allowing expression of the same conceptual/logical relationships in terms of predicates or sets. So, for example, the predicate specifying things $X that eat food is expressed by
EvaluationLink PredicateNode: eat ListLink $X ConceptNode: food
It has the same semantics as the set-membership declaration of things $X that are food-eaters:
MemberLink ListLink $X ConceptNode: food ConceptNode: FoodEaters
The relation between the predicate "eat" and the concept "FoodEaters" is formally given by
ExtensionalEquivalenceLink ConceptNode: FoodEaters SatisfyingSetLink PredicateNode: eat
In other words, we say that "FoodEaters" is the SatisfyingSet of the predicate "eat": it is the set of entities that satisfy the predicate "eat". Note that the truth values of MemberLink and EvaluationLink are fuzzy rather than probabilistic.
There is a host of link types embodying logical relationships as defined in the PLN logic system, e.g. InheritanceLink, SubsetLink (aka ExtensionalInheritanceLink) and IntensionalInheritanceLink. There are different sorts of inheritance, e.g.
SubsetLink salmon fish IntensionalInheritanceLink whale fish InheritanceLink fish animal
SimilarityLink shark barracuda IntensionalSimilarityLink shark dolphin ExtensionalSimiliarityLink American obese\_person
There are also higher-order versions of these links, both asymmetric ImplicationLink, ExtensionalImplicationLink, IntensionalImplicationLink. The symmetric versions are EquivalenceLink, ExtensionalEquivalenceLink and IntensionalEquivalenceLink. These are used between predicates and links, e.g.
ImplicationLink EvaluationLink eat ListLink $X dirt EvaluationLink feel ListLInk $X sick
ImplicationLink EvaluationLink eat ListLink $X dirt InheritanceLink $X sick
ForAllLink $X, $Y, $Z ExtensionalEquivalenceLink EquivalenceLink $Z EvaluationLink + ListLink $X $Y ExtensionalEquivalenceLink EquivalenceLink $Z EvaluationLink + ListLink $Y $X
Note, the latter is given as an extensional equivalence because it's a pure mathematical equivalence. This is not the only case of pure extensional equivalence, but it's an important one.
There are also temporal versions of these links, such as
which combine logical relation between the argument with temporal relation between their arguments. For instance, we might say
PredictiveImplicationLink PredicateNode: JumpOffCliff PredicateNode: Dead
or including arguments,
PredictiveImplicationLink EvaluationLink JumpOffCliff $X EvaluationLink Dead $X
The former version, without variable arguments given, shows the possibility of using higher-order logical links to join predicates without any explicit variables. Via using this format exclusively, one could avoid VariableAtoms entirely, using only higher-order functions in the manner of pure functional programming formalisms like combinatory logic. However, this purely functional style has not proved convenient, so the Atomspace in practice combines functional-style representation with variable-based representation.
Temporal links often come with specific temporal quantification, e.g.
PredictiveImplicationLink <5 seconds> EvaluationLink JumpOffCliff $X EvaluationLink Dead $X
indicating that the conclusion will generally follow the premise within 5 seconds. There is a system for managing fuzzy time intervals and their interrelationships, based on a fuzzy version of Allen Interval Algebra.
SequentialANDLink is similar to PredictiveImplicationLink but its truth value is calculated differently. The truth value of
SequentialANDLink <5 seconds> EvaluationLink JumpOffCliff $X EvaluationLink Dead $X
indicates the likelihood of the sequence of events occurring in that order, with gap lying within the specified time interval. The truth value of the PredictiveImplicationLink version indicates the likelihood of the second event, conditional on the occurrence of the first event (within the given time interval restriction).
There are also links representing basic temporal relationships, such as BeforeLink and AfterLink. These are used to refer to specific events, e.g. if X refers to the event of Ben waking up on July 15 2012, and Y refers to the event of Ben getting out of bed on July 15 2012, then one might have
AfterLink X Y
And there are TimeNodes (representing time-stamps such as temporal moments or intervals) and AtTimeLinks, so we may e.g. say
AtTimeLink X TimeNode: 8:24AM Eastern Standard Time, July 15 2012 AD
There are links representing associative, attentional relationships,
These connote associations between their arguments, i.e. they connote that the entities represented by the two argument occurred in the same situation or context, for instance
HebbianLink happy smiling AsymmetricHebbianLink dead rotten InverseHebbianLink dead breathing
The AsymmetricHebbianLink indicates that when the first argument is present in a situation, the second is also often present. The symmetric (default) version indicates that this relationship holds in both directions. The inverse versions indicate the negative relationship: e.g. when one argument is present in a situation, the other argument is often not present.
There are nodes representing various sorts of procedures; these are kinds of ProcedureNode, e.g.
- SchemaNode, indicating any procedure
- GroundedSchemaNode, indicating any procedure associated in the system with a Combo program or a scheme, python or C++ function allowing the procedure to be executed
- PredicateNode, indicating any predicate that associates a list of arguments with an output truth value
- GroundedPredicateNode, indicating a predicate associated in the system with a Combo program a scheme, python or C++ function allowing the predicate's truth value to be evaluated on a given specific list of arguments.
ExecutionLink step_forward ExecutionLink step_forward 5 ExecutionLink + ListLink NumberNode: 2 NumberNode: 3
The first example indicates that the schema "step forward" has been executed. The second example indicates that it has been executed with an argument of "5" (meaning, perhaps, that 5 steps forward have been attempted). The last example indicates that the "+" schema has been executed on the argument list (2,3), presumably resulting in an output of 5.
The output of a schema execution may be indicated using an ExecutionOutputLink, e.g.
ExecutionOutputLink + ListLink NumberNode: 2 NumberNode: 3
refers to the value "5" (as a NumberNode).
Links for Special External Data Types
Finally, there are also Atom types referring to specific types of data important to using OpenCog in specific contexts. For instance, there are Atom types referring to general natural language data types, such as
plus more specific ones referring to relationships that are part of link-grammar parses of sentences
or RelEx semantic interpretations of sentences
There are also Atom types corresponding to entities important for embodying OpenCog in a virtual world, e.g.
Defining new Link Types
All of the atom types mentioned above can be thought of as custom link types created for special-purpose use. These link types are convenient, and handy, but are not really "fundamental" -- almost all of them can be (and should be) understood as "syntactic sugar" for an EvaluationLink. Thus, for example, the NLP subsystem uses a PartOfSpeechLink to tag words with parts of speech:
PartOfSpeechLink WordNode "automobile" DefinedLinguisticConceptNode "noun"
This should effectively be understood to be equivalent to
EvaluationLink PredicateNode "PartOfSpeech" ListLink WordNode "automobile" DefinedLinguisticConceptNode "noun"
Furthermore, both WordNode and DefinedLinguisticConceptNode are not "fundamental", but are in turn yet more syntactic sugar, which can be re-expressed using InheritanceLinks. So, at the fundamental level, one has:
EvaluationLink PredicateNode "PartOfSpeech" ListLink InheritanceLink ConceptNode "automobile" ConceptNode "Word" InheritanceLink ConceptNode "noun" ConceptNode "DefinedLinguisticConcept"
The difference between this last form, and the first, indicates why "syntactic sugar" is tasty.
The DefinedTypeNode can be used to give a name to anonymous types. The mechanism for converting types created with DefinedTypeNode into types accessible in C++ has not been fully specified or implemented. By contrast, the EquivalenceLink can be used to create definitions for new PredicateNodes and Conceptnodes.