The AtomSpace uses many different kinds of Atoms and Values. The name "Atom" was chosen because of the resemblance to the concept of the "atomic sentence (Wikipedia link)" in mathematical logic. Likewise, the word "Value" is meant to invoke the idea of a truth value, or a valuation in logic. All Atoms are typed, both in the sense of a data type, and in the sense of type theory. Almost all Atomese types are abstract data types.
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 category of atom types lists all documented atoms currently in use; there are over 150 of them. This page provides a general introduction to some of the types in current use, focusing on (old-fashioned symbolic-AI-style) knowledge representation, and on KR query. It is not a complete list: new types are easily created (see the examples/type-system demo in github.) There are also more modern, large sparse vector-oriented representation systems in the AtomSpace (i.e. neural-net-like); these are not covered here. There are also a considerable number of domain-specific Atom types, for genetics, biology, chemistry, robotics, vision, natural language processing. Most of these are not documented on this wiki; they appear in 3rd-party packages and subsystems.
The various OpenCog books mention Atom types that are not implemented or have been implemented in a somewhat different way (or are obsolete.) The partial nature of the list given here reflects a more general point: The specific collection of core Atom types has changed as the system developed. The current core set is the result of over a decade of experimentation and false starts.
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. The idea of using Atoms to describe Atoms and work with Atoms is called Atomese; this meta-self-abstraction is perhaps the most important invention of the system.
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, for example
ConceptNode "C" InheritanceLink (ObjectNode "BW") (ConceptNode "C") InheritanceLink (ObjectNode "BP") (ConceptNode "C") InheritanceLink (ObjectNode "BN") (ConceptNode "C") ReferenceLink (ObjectNode "BW") (PhraseNode "Ben's watch") ReferenceLink (ObjectNode "BP")(PhraseNode "Ben's passport") ReferenceLink (ObjectNode "BN") (PhraseNode "Ben's necklace")
indicates the simple ConceptNode grouping three objects owned by Ben. The above-given Atoms don't indicate the ownership relationship, they just link the three objects with textual descriptions -- they provide a syntactic relation, and not a semantic one. 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.14 NumberNode 1 2 3 4 5 42
NumberNodes are vectors. (For most practical applications, the FloatValue provides a faster, easier and cheaper numeric vector; but Values are a more advanced topic.)
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, for example, we might say
AverageLink $X ImplicationLink AndLink EvaluationLink young $X EvaluationLink beautiful $X EvaluationLink NotLink 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.
We have already introduced VariableNodes above; it's also possible to specify the type of a VariableNode via linking it to a VariableTypeNode via a TypedVariableLink, e.g.
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
There are SimilarityLink, ExtensionalSimilarityLink, IntensionalSimilarityLink which are symmetrical versions, e.g.
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 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.
ExecutionLinks and EvaluationLinks record the activity of SchemaNodes and PredicateNodes. We have seen many examples of EvaluationLinks in the above. Example ExecutionLinks would be:
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
These are just three out of several dozen listed in Category:NLP Atom Types. Different projects can create their own Atom types; the AGI-Bio project defines a GeneNode and ProteinNode. The chemistry project defines a Node for each chemical element. The 3D and Robot projects define Atoms appropriate for those domains.
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.