Everything described on this page is obsolete. Its only kept here to provide a historical record of what used-to-be. The code implementing this was removed from github in the 2015 time-frame. See SpaceServer for notes about the current system.
Time Server is a member of AtomSpace that provides indexing and searching of atoms based on temporal criteria.
Representation of temporal information
An atom in the AtomSpace may be associated to 3 types of temporal information, as follows:
Timestamp corresponds to an exact instant in time. This is represented by a number of elapsed units of time since a given Epoch (both the unit of time and the Epoch used depends on the application running on Opencog framework). In the Embodiment application, for example, Epoch is defined as 00:00:00 AM on Jan 1st, 2008 and the unit of time is 0.1 second (one tenth of a second). So, if the timestamp associated to an atom is 1000, it means that such an atom is associated to 100 seconds after the defined Epoch, i.e., 00:01:40.0 AM on Jan 1st, 2008.
Timelag (uniform distribution)
A timelag with uniform distribution is defined as the interval between 2 (the start and the end) timestamps. This way, and still considering the Epoch and unit of time mentioned above, an uniform distribution timelag whose start and end timestamps are 0 and 1000 represents the time interval between 00:00:00.0 and 00:01:40.0 on Jan 1st, 2008.
Timelag (normal distribution)
For a normal distribution, we must define a timelag by specifying the mean and the standard deviation values (also in the same units of time, as described above). Currently, the number of standard deviation used to define the corresponding time interval is always 1 (this may be reviewed later, if needed). So, in practice, if we have a normal distribution timelag whose mean is 1000 and the standard deviation is 100, this corresponds to the interval [900,1100] with a normal distribution.
TimeNode and Temporal class
A TimeNode represents a temporal value, i.e., a timestamp or a timelag (with uniform or normal distribution) inside the AtomSpace's hypergraph. So, all the information that defines a timestamp or timelag must be put in the name of this node. Inside TimeServer, though, this same information is represented by the class Temporal so that we can implement the queries involving temporal information in a more efficient (fast) way.
In addition to provide the constructors and methods to deal with any of these 3 types of temporal information described above, the Temporal class also provides methods to get the name of TimeNode that corresponds to a Temporal object and vice-versa. This way, it's possible to convert from a representation to another easily.
Time units and Epoch
For representing a specific timestamp, we use a non-negative integer that indicates the number of units of time elapsed since a given Epoch. However, both the unit of time and the Epoch used depends on the application running on Opencog framework. In the Embodiment application, for example, Epoch is currently (dec 2009) defined as 00:00:00 AM on Jan 1st, 2008 and the unit of time is 0.1 second (one tenth of a second). So, if a timestamp is 1000, it means 100 seconds after the defined Epoch, i.e., 00:01:40 AM on Jan 1st, 2008. So, the interpretation of temporal values in TimeNodes or Temporal objects will depend on how the application has defined them.
Format of the name of a TimeNode
The name of a TimeNode depends on which type of temporal information it is representing, as follows:
- Timestamps: its name of the TimeNode is the integer value that represents such timestamp. For example, if the timestamp is 1000, the name of the TimeNode will be "1000".
- Timelags (uniform distribution): the name of the TimeNode is composed by the start timestamp and the end timestamp separated by a colon. For example, the TimeNode named "0:1000" represents the timelag between the timestamps 0 and 1000 using an uniform distribution.
- Timelags (normal distribution): the name of the TimeNode is composed by the mean, a colon, the standard deviation, another colon and the number 1, which indicates it has a normal distribution. The current code assumes only 1 standard deviation from the mean to define the correspond interval of a Temporal object. So, if we have a Temporal object with normal distribution whose mean is 1000 and the standard deviation is 100, it corresponds to the interval [900,1100]. This may be reviewed later, if needed.
Temporal association in AtomSpace hypergraph and TimeServer
For representing the association of a temporal value (timestamp or timelag) to an atom, we use an AtTimeLink between the corresponding TimeNode and that atom, as the following example:
AtTimeLink TimeNode "6000:72000" EvalLink PredicateNode "Position" ListLink ObjectNode "ball" NumberNode "100" NumberNode "20" NumberNode "100"
The above example means that the object "ball" is/was at position (100,20,100) during the time interval [6000,72000].
Each AtTimeLink as above corresponds to a TimeServer's entry, which is actually a pair of a Handle and a Temporal object (see the HandleTemporalPair class). In the example above, we would have a pair composed of the handle of the EvaluationLink and a Temporal object that represents the interval [6000,72000] with uniform distribution.
Time Server API
The Time Server API is quite simple and provides the following basic methods:
void add(Handle, const Temporal&); get(OutputIterator outIt, Handle, const Temporal&, TemporalRelationship); bool remove(Handle, const Temporal&, TemporalRelationship);
The add method receives the Handle of an atom in AtomSpace and a Temporal object which the atom is associated to.
The get method receives the following arguments:
- OutputIterator: where the method will put the results of the query. This iterator is filled with the HandleTemporalPair objects that matches the search criteria.
- Handle: indicates which specific atom the query is about. An UNDEFINED_HANDLE may be passed, what means it will match any Handle.
- Temporal: indicates the Temporal information that will be used as reference for the temporal criterion defined by the next argument. An UNDEFINED_TEMPORAL may be passed, what means it will match any temporal value.
- TemporalRelationship: indicates the temporal relationship an internal Temporal object must have in relation to the passed Temporal object argument (if not undefined) to match the search criterion. For example, the TemporalRelationship may be EXACT, i.e., only internal Temporal objects that are equals to the passed Temporal argument will match; or INCLUDES, i.e., only the internal Temporal objects that includes the passed Temporal argument will match. All current temporal relationship used as search criteria are described and explained in the next section.
The remove method works similarly to the get method, but instead of returning the matching entries according to the passed arguments, it removes the matching entries from the Time Server.
Temporal search criteria
In order to describe the temporal search criteria already implemented, let´s consider:
- T (a Temporal object associated to a Handle in the TimeServer) = [l,u], where l and u are respectively the lower and upper bounds of the corresponding time interval.
- T' (the Temporal object passed as argument to be the reference for the temporal relationship used as search/removal criterion) = [l',u'], where l' and u' are respectively the lower and upper bounds of the corresponding time interval.
That said, the temporal relationship R to be used as criterion may be one of the following ones:
- EXACT: T == T' => l == l' && u == u' && distribution type (normal or uniform) are the same
- STARTS_BEFORE: l < l'
- STARTS_WITHIN: l' <= l <= u'
- STARTS_AFTER: l > u'
- ENDS_BEFORE: u < l'
- ENDS_WITHIN: l' <= u <= u'
- ENDS_AFTER: u > u'
- OVERLAPS: STARTS_WITHIN || ENDS_WITHIN => l' <= u && l <= u' (since l <= u && l' <= u')
- INCLUDES: l <= l' && u >= u'
- NEXT_AFTER_START_OF: next time T whose l > l'
- NEXT_AFTER_END_OF: next time T whose l > u'
- PREVIOUS_BEFORE_START_OF: previous time T whose l < l'
- PREVIOUS_BEFORE_END_OF: previous time T whose l < u'
Although TimeServer is currently implemented as a member of AtomSpace, the current AtomSpace API only provides a constant reference to its TimeServer object. So, only the TimeServer's get method can be called directly. The remaining methods are called indirectly by methods in the AtomSpace API related to the Temporal information that take care of changes that should be done consistently in both AtomSpace's hypergraph and TimeServer, as follows:
Handle addTimeInfo(Handle atom, const Temporal& t, const TruthValue& tv); bool removeTimeInfo(Handle atom, const Temporal& t, TemporalTable::TemporalRelationship, bool removeDisconnectedTimeNodes, bool recursive);
There are also the method for getting the HandleTemporalPair objects that match a search criteria and the method that gets the atom Handle (of the AtTimeLink) that corresponds to a given HandleTemporalPair, as follows:
getTimeInfo(OutputIterator outIt, Handle h, const Temporal& t, TemporalTable::TemporalRelationship); Handle getAtTimeLink(const HandleTemporalPair& htp);