Adding Dimensions |
A central concept in GBBopen is dimensionality. Dimensional abstraction of space instances, unit instances, and proximity-based retrieval patterns is used to provide a semantically meaningful separation of blackboard-repository storage mechanisms from system and application code. This separation provides flexibility in developing and evolving complex blackboard applications and allows GBBopen to change storage and search strategies and optimizations dynamically.
Each space instance can be created as a conceptual hyper-dimensional volume. Unit instances occupy multidimensional extent based on their attributes. The location of a unit instance within the space instance is determined by the intersection of the space instance's dimensionality and the unit instance's dimension values.
GBBopen supports three types of dimensions:
In this exercise, we will redefine the location
x
and y
, that represent Euclidean
positions on a two-dimensional plane. Then we will create a two-dimensional
known-world
location
known-world
tutorial-example.lisp
(in-package :gbbopen-user) (define-unit-class location () (x y))
:gbbopen-user
location
unit class
Edit your tutorial-example.lisp
location
(define-unit-class location () (x y) (:dimensional-values (x :point x) (y :point y)))In this tutorial, we will highlight code additions and changes using a black font.
The :dimensional-values
location
x
and y
, and that the value of each dimension will be a single numeric
value obtained from the slots x
and y
, respectively.
Because we chose to use the same name for each dimension and its associated
slot value, our :dimensional-values
(define-unit-class location () (x-slot y-slot) (:dimensional-values (x :point x-slot) (y :point y-slot)))which clarifies the semantics of the
:dimensional-values
We could compile and load the entire tutorial-example.lisp
C-c
C-c
C-c C-x
location
location
unit instance
Let's test our new location
gbbopen-user> (defparameter ui (make-instance 'location :x 40 :y 60)) ui gbbopen-user>and display its description:
gbbopen-user> (describe-instance ui) Location #<location 1> Instance name: 1 Space instances: None Dimensional values: x: 40 y: 60 Non-link slots: x: 40 y: 60 Link slots: None gbbopen-user>Note the dimensional values for the
x
and y
dimensions.
known-world
space instance
Create the known-world
gbbopen-user> (defparameter si (make-space-instance '(known-world))) si gbbopen-user>
Now, add the location
gbbopen-user> (add-instance-to-space-instance ui si) Warning: In add-instance-to-space-instance: #<location 1> does not share any dimensions with space instance #<standard-space-instance (known-world)>. #<location 1> gbbopen-user>
GBBopen has warned us that our location
known-world
known-world
gbbopen-user> (describe-blackboard-repository) Space Instance Contents -------------- -------- known-world 1 instance (1 location) Unit Class Instances ---------- --------- location 1 standard-space-instance 1 --------- 2 instances gbbopen-user>but we cannot perform dimension-based retrieval of our
location
known-world
known-world
Let's delete the known-world
x
and y
dimensions:
gbbopen-user> (delete-space-instance si) #<deleted-unit-instance standard-space-instance (known-world)> gbbopen-user> (setf si (make-space-instance '(known-world) :dimensions '((x :ordered) (y :ordered)))) #<standard-space-instance (known-world)> gbbopen-user>We have specified
x
and y
as ordered dimensions, making the
known-world
Verify the dimensionality of the known-world
gbbopen-user> (describe-space-instance si) Standard-space-instance #<standard-space-instance (known-world)> Allowed unit classes: t Dimensions: (x :ordered) (y :ordered) gbbopen-user>
location
unit instance to the new
known-world
Add the location
known-world
gbbopen-user> (add-instance-to-space-instance ui si) #<location 1> gbbopen-user>The dimension warning is gone.
location
to the known-world
automatically
Up to this point, we have used location
known-world
:initial-space-instances
Add the following :initial-space-instances
location
tutorial-example.lisp
(define-unit-class location () (x y) (:dimensional-values (x :point x) (y :point y)) (:initial-space-instances (known-world)))
Compile and load the new location
location
unit instances
Let's test our new location
gbbopen-user> (make-instance 'location :x 70 :y 30) #<location 2> gbbopen-user>and confirm that the new
location
known-world
gbbopen-user> :dsbb Space Instance Contents -------------- -------- known-world 2 instances (2 location) Unit Class Instances ---------- --------- location 2 standard-space-instance 1 --------- 3 instances gbbopen-user>Here we used GBBopen's
:dsbb
REPL command, which is equivalent to
evaluating (describe-blackboard-repository)
Now, let's populate the known-world
gbbopen-user> (make-instance 'location :x 20 :y 20) #<location 3> gbbopen-user> (make-instance 'location :x 25 :y 25) #<location 4> gbbopen-user> (make-instance 'location :x 20 :y 30) #<location 5> gbbopen-user>and verify that they are all on the
known-world
gbbopen-user> :dsbb Space Instance Contents -------------- -------- known-world 5 instances (5 location) Unit Class Instances ---------- --------- location 5 standard-space-instance 1 --------- 6 instances gbbopen-user>
We have seen how we can use location
known-world
gbbopen-user> (find-instances 'location '(known-world) :all) (#<location 5> #<location 4> #<location 3> #<location 2> #<location 1>) gbbopen-user>
Now that we have added x
and y
dimensions to
location
known-world
location
gbbopen-user> (find-instances 'location '(known-world) '(and (= x 20) (= y 20))) (#<location 3>) gbbopen-user>
We can use location
gbbopen-user> (find-instances 'location '(known-world) '(and (= x 20) (= y 20))) (#<location 3>) gbbopen-user> (describe-instance (first *)) Location #<location 3> Instance name: 3 Space instances: ((known-world)) Dimensional values: x: 20 y: 20 Non-link slots: x: 20 y: 20 Link slots: None gbbopen-user>Note that we used Common Lisp's REPL
*
variable that is always set to
the value returned by evaluating the last REPL expression (in this case, the
result of location
unit instances
It would be convenient if we could easily see the coordinates of
location
print-object
location
Add the following location
tutorial-example.lisp
(define-unit-class location () (x y) (:dimensional-values (x :point x) (y :point y)) (:initial-space-instances (known-world))) (defmethod print-instance-slots ((location location) stream) (call-next-method) (when (and (slot-boundp location 'x) (slot-boundp location 'y)) (format stream " (~s ~s)" (x-of location) (y-of location))))The method first performs a
(call-next-method)
location
x
and y
slots are bound and, if so,
writes the location
x
and
y
, formatted together.)
Now, compile and load the
gbbopen-user> (find-instances 'location '(known-world) '(= (x y) (20 20))) (#<location 3 (20 20)>) gbbopen-user>
Note that this time we used a two-dimensional (x
,y
) retrieval
pattern rather than the conjunction of two one-dimensional patterns that we
used previously. The two patterns are equivalent, but often a
higher-dimensional pattern may be more convenient than a conjunction. Also
note that we can see immediately that we retrieved the desired
location
Let's try some additional dimensional retrievals. First, find all
location
x
position of 20:
gbbopen-user> (find-instances 'location '(known-world) '(= x 20)) (#<location 5 (20 30)> #<location 3 (20 20)>) gbbopen-user>Find all
location
x
and y
coordinates are less than or equal to 25:
gbbopen-user> (find-instances 'location '(known-world) '(<= (x y) (25 25))) (#<location 4 (25 25)> #<location 3 (20 20)>) gbbopen-user>Find all
location
x
coordinates are
between 0 and 40 (inclusive) and whose y
coordinates are between 60 and
100 (inclusive):
gbbopen-user> (find-instances 'location '(known-world) '(within (x y) ((0 40) (60 100)))) (#<location 1 (40 60)>) gbbopen-user>Find all
location
gbbopen-user> (find-instances 'location '(known-world) '(not (within (x y) ((0 40) (60 100))))) (#<location 5 (20 30)> #<location 4 (25 25)> #<location 3 (20 20)> #<location 2 (70 30)>) gbbopen-user>
Recall that we assigned location
1
to the global variable
ui
:
gbbopen-user> ui #<location 1 (40 60)> gbbopen-user>and we can retrieve it by its
x
and y
coordinates:
gbbopen-user> (find-instances 'location '(known-world) '(= (x y) (40 60))) (#<location 1 (40 60)>) gbbopen-user>
Let's change its x
position to 80
and try retrieving it again:
gbbopen-user> (setf (x-of ui) 80) 80 gbbopen-user> (find-instances 'location '(known-world) '(= (x y) (40 60))) nil gbbopen-user>It has moved on the
known-world
location
1
unit instance is now at (80, 60):
gbbopen-user> (find-instances 'location '(known-world) '(= (x y) (80 60))) (#<location 1 (80 60)>) gbbopen-user>Also note that the textual representation of
location
1
shows the new x
slot value.
The GBBopen Project
Adding Dimensions |