3 Built-Ins

3.1 Introduction

This section contains descriptions of the functions, relations and actions of the Qulog library. In the interpreter you can see all their names and types by entering the command

| ?? stypes.

Many of these are Qu-Prolog primitive relations 'lifted' to QuLog by giving them appropriate type/mode declarations. Other Qu-Prolog relations and actions can be 'lifted' to the Qulog level be giving them a QuLog type declaration in your QuLog program file.

For example, if the primitives described on Section List Processing had not already been made available for use in QuLog, all you would have needed to do was include their type declarations as given in that section.

As another example, there is a Qu-Prolog primitive

between(From,To,N)

for generating or testing an integer value N between given integer values From and To.

To use this in a QuLog program, add the moded type declaration

between: (integer,integer,?integer) <=

to your program file. It tells the QuLog mode/type checker that the relation is a Qu-Prolog primitive (that will be checked), and that in every use the first two arguments should be given as integers but the third integer argument may be given or may be returned as value of an unbound variable.

3.2 Input / Output

3.2.1 Term Input/Output Actions

Actions:

writeL(List)

Write the elements of List. If the atom nl_ appears in List it is written as a newline.

You can also use sp_(N) where N is a positive integer to insert N spaces. Strings in List are displayed without the string quotes ".." unless you write them with q_("..."). The quotes are then put around the string.

mode/type    writeL(![??term])

Example:
| ?? writeL(["List of atoms ",[a,b], nl_,
"Set of nats ", {2,1,4,1}]).

List of atoms [a, b]
Set of nats {1, 2, 4}

with the next output on the next line. nl_ causes a new line to be output as would the string "\n". In fact any of the C string control characters, such as "\t", "\s" for tab and space respectively, can be put into a string and will have the intended effect unless the string is wrapped inside a q_ term. So we could have written the above query as:
| ?? writeL(["List of atoms ",[a,b],
"\nSet of nats ", {2,1,4,1}]).

Other control term we can put in the list argument of writeL are:
sp_(n), n positive integer. It will display n spaces.
uq_(Atom), where Atom is an atom that normally needs to be quoted. It will be displayed without the single quotes.
wr_(Var), will not display Var as an underscore followed by a sequence of digits, as is normal, but will give it a name such as A, B, C when displayed and will give subsequent occurence of Var in the list to be output using the given name for Var.

The following query illustrates the the use of uq_ and wr_.

| ?? writeL([uq_('Hello')," there\n",wr_(_895),sp_(2),
_895,sp_(2),wr_(_678),nl_]).

Hello there
A A B
_895 = A : Ty1
_678 = B : Ty2
success

writeLine(List)

The same as writeL but with a trailing newline.

Example:
| ??writeLine([s("A list "), [a, b], sp_(2), {2, 1, 4, 1},
s(" followed by a set.")]).

A list [a, b] {1, 2, 4} followed by a set.

with the next output being at the beginning of the next line.

readT(Term)

Unifies Term with the next term denoted by the next sequence of characters typed at the terminal followed by fullstop, return.

Example:
| ?? readT(X).

f(A).
X = f(A) : term

Note that this read remembers the names of variables (the A above). A consequence of this, given the occurs check in unification, is that the following query fails.
| ?? readT(A).

f(A).
no

3.3 Terms

3.3.1 Comparison of Terms

Two terms are compared according to the standard ordering, which is defined below. Items listed at the beginning come before the items listed at the end. For example, numbers are less than atoms in the standard ordering.

  1. Variables, in age ordering (older variables come before younger variables).
  2. Numbers, in numerical ordering.
  3. Atoms, in character code (ASCII) ordering.
  4. String, in standard string odering.
  5. Compound terms are compared in the following order:
    1. Arity, in numerical ordering.
    2. Functor, in standard ordering.
    3. Arguments, in standard ordering, from left to right.
  6. Sets, in dictionary order on elements.
  7. Lists, in dictionary order on elements.
The above ordering is used when constructing sets.

The following relations use the above ordering to test terms.

Term1 @> Term2

Succeeds if Term1 is greater thanTerm1 in the above ordering.

Term1 @>= Term2

Succeeds if Term1 is greater than or equal to Term2 in the above ordering.

Term1 @< Term2

Succeeds if Term1 is less thanTerm1 in the above ordering.

Term1 @=< Term2

Succeeds if Term1 is less than or equal to Term2 in the above ordering.

3.3.2 Testing of Terms

These testing predicates are used to determine various properties of the data objects, or apply constraints to the data objects.

Relations:

type(Term, Type)

Succeed if Term is a non-variable of type Type.
mode/type    type : (??top, !typeE(_)) <=

Example:
| ?? type(a, atomic).

yes

| ?? type(a, int).

no

| ?? type([a,2], [int || atom]).

yes

ground(Term)

Succeed if Term is ground.
mode/type    ground : (??top) <=

isa(Term, Type)

Succeed if Term is of type Type and Type is a finite type.
mode/type    isa : (?Term, !typeE(_)) <=

Example: For this example we assume the following type declarations.


name ::= "Alice" | "Bob" | "Carol"
status ::= good(name) | bad(name)


| ?? isa(X, status).

X = good("Alice")
...
X = good("Bob")
...
X = good("Carol")
...
X = bad("Alice")
...
X = bad("Bob")
..
X = bad("Carol")

| ?? isa(good("Bob"), status).

yes

| ?? isa(2, nat).

no

template(Term)

Succeed if Term is atomic or a compound term with a ground functor.
mode/type    template :(??top) <=

ground_inputs(Term)

Succeed if Term is a relation or action term and that the modes of its arguments are correct.
mode/type    ground_inputs : ??(relcall || actcall)

3.3.3 List Processing

append(L1, L2, L3)

Succeed if L3 is the concatentation of L1 and L2
mode/type
   append: ([T]?, [T]?, [T]?)<= | (![T], ![T], ?[T])<= |
           (?[T], ?[T], ![T])<=

reverse(L1, L2)

Succeed if L2 is the reverse of L1.
mode/type
   reverse : (![T?], ?[T?]) <=

sort(L1, L2)

Succeed if L2 is L1 sorted.
mode/type
   sort : (![T?], ?[T?]) <=

member(X, L)

Succeed if X is in L.
mode/type
   member : (T?, [T]?) <=

X in L

Succeed if X is in L.
mode/type
   in: (?T,[T])<= | (T?,![T?])<= | (?string,[string])<= |
           (?T,{T}) <=

Almost exactly the same uses as member except that it it must be given a complete list of possibly non-ground terms.

As its type indicates, in can also be used to access single character substrings of a string and ground elements of a set.

3.4 Arithmetic

The following arithemetic functions are available.

Num1 + Num2

Returns the sum of Num1 and Num2.
+ : (nat, nat) -> nat | (int, int) -> int | (num, num) -> num

Num1 - Num2

Returns the difference of Num1 and Num2.
- : (int, int) -> int | (num, num) -> num

-Num1

Returns the negation of Num.
- : int -> int | num -> num

Num1 * Num2

Returns the product of Num1 and Num2.
* : (nat, nat) -> nat | (int, int) -> int | (num, num) -> num

Num1 // Num2

Returns the integer division of Num1 and Num2.
// : (nat, nat) -> nat | (int, int) -> int

Num1 / Num2

Returns the division of Num1 and Num2.
/ : (num, num) -> num

Num1 mod Num2

Returns the mod of Num1 and Num2.
mod : (nat, int) -> nat | (int, int) -> int

Num1 ** Num2

Returns Num1 raised to the power Num2.
** : (nat, nat) -> nat | (int, nat) -> int | (num, num) -> num

Int >> Nat

Returns the bitwise right shift of Int with respect to Nat.
>>: (int, nat) -> int

Int << Nat

Returns the bitwise left shift of Int with respect to Nat.
<<: (int, nat) -> int

Int1 /\ Int2

Returns the bitwise AND of Int1 and Int2.
/\: (int, int) -> int

Int1 \/ Int2

Returns the bitwise OR of Int1 and Int2.
\/: (int, int) -> int

\ Int

Returns the bitwise complement of Int.
\: (int) -> int

abs(Num)

Returns the absolute value of Num.
abs: int -> nat | num -> num

sqrt(Num)

Returns the square root of Num.
sqrt: num -> num

round(Num)

Returns the round of Num.
round: num -> int

floor(Num)

Returns the floor of Num.
floor: num -> int

ceiling(Num)

Returns the ceiling of Num.
ceiling: num -> int

pi_()

Returns PI.
pi_: () -> num

e_()

Returns E.
e_: () -> num

sin(Num)

Returns the sin of Num.
sin: num -> num

cos(Num)

Returns the cos of Num.
cos: num -> num

tan(Num)

Returns the tan of Num.
tan: num -> num

asin(Num)

Returns the arcsin of Num.
asin: num -> num

acos(Num)

Returns the arccos of Num.
acos: num -> num

atan(Num)

Returns the arctan of Num.
atan: num -> num

atan2(Y, X)

Returns the atan2 of Y and X. This returns an angle in the range (-pi, pi].
atan2: (num,num) -> num

3.5 Other Functions

now()

Returns the current time.
now: () -> num

exec_time()

Returns the lapsed time in seconds since this qulog process was started
exec_time: () -> num

start_time()

Returns the time at which this qulog process was started
start_time: () -> num

random_num()

Returns a random number in [0,1).
random_num: () -> num

random_int(Lower, Upper)

Returns a random number in the interval [Lower, Upper].
random_int: (int, int) -> num

S1 union S2

Returns the union of sets S1 and S2.
union: ({T}, {T}) -> {T}

S1 inter S2

Returns the intersection of sets S1 and S2.
inter: ({T}, {T}) -> {T}

S1 diff S2

Returns the set difference of sets S1 and S2.
diff: ({T}, {T}) -> {T}

L1 <> L2

Returns the concatination of lists L1 and L2.
<> : ([T], [T]) -> [T]

S1 ++ S2

Returns the concatination of strings S1 and S2.
++ : (string, string) -> string

#L

Returns the length of the list, set, or string L.
# : [T] -> nat | {T} -> nat | string -> nat

F@..Args

Returns the compound term obtained by applying F to Args.
@.. : (term, [term]) -> term

Example:
| ?? @..(a, [1,2]).

a(1, 2) : term

@.. can also be used to split up a compound term as in the following example.
| ?? a(1,2) =? F@..Args.

F = a : atom
Args = [1, 2] : [nat]

$Name, where $ is a prefix operator.

Here Name is an atom that must have been initialised with a statement

int Name:=Integer, e.g. int count:=0 or

num Name:=Number, e.g. num savings:=678.50

in the program. It returns the current value associated with Name
which can be updated by primitive actions (see :=).

3.6 Other Relations

true

Always succeeds.
mode/type    true : () <=

false

Always fails.
mode/type    false : () <=

Term1 = Term2

Succeeds if Term1 and Term2 unify.
Any function calls in each argument term are evaluated first using strict evaluation
- expression arguments evaluated first - as with every relation call.
mode/type    = : (term?, term?) <=

N1 > N2

Succeeds if N1 is greater than N2.
mode/type    > : (!num, !num) <=

N1 >= N2

Succeeds if N1 is greater than or equal to N2.
mode/type    >= : (!num, !num) <=

N1 < N2

Succeeds if N1 is less than N2.
mode/type    < : (!num, !num) <=

N1 =< N2

Succeeds if N1 is less than or equal to N2.
mode/type    =< : (!num, !num) <=

X in T

Succeeds if X is a term and and T is a list or set of terms and X is an element of T or if X and T are both strings and X is a single character string occurring inT.
mode/type    in: (T?,![T?]) <= | (?T,![T]) <= | (?T,!{T}) <= |
    (?string, !string) <=

string2term(S, T)

Succeeds if T is the term obtained by parsing the string Sas a Qulog term.
mode/type    string2term : (!string, term?) <=

current_thread(Name)

Succeeds if Name is the name of this thread
mode/type    current_thread : (?atom) <=

get_active_resources(ResourceInfo)

Succeeds if ResourceInfo is the list of terms res(atom,[resource]) giving resources used by each running task in a multi-tasking agent. The atom is task name.
mode/type    get_active_resources : (?term) <=

get_waiting_resources(ResourceInfo)

Succeeds if ResourceInfo is the list of terms res(atom,[resource]) giving resources needed by each waiting task in a multi-tasking agent. The atom is task name.
mode/type    get_waiting_resources : (?term) <=

3.7 Other Actions

remember(Belief)

Adds its ground relcall argument (Belief) as a new last dynamic fact for its functor relation name R. R must have been declared as a belief.
mode/type    remember : (relcall) ~>>

remember_for(Belief, Secs)

The same as remember except that Belief is forgotten after Secs seconds.
mode/type    remember_for : (relcall, num) ~>>

Alternative syntax: remember Belief for Secs

rememberA(Belief)

Adds its ground relcall argument (Belief) as a new first dynamic fact for its functor relation name R. R must have been declared as a belief.
mode/type    rememberA : (relcall) ~>>

rememberA_for(Belief, Secs)

The same as rememberA except that Belief is forgotten after Secs seconds.
mode/type    remember_for : (relcall, num) ~>>

Alternative syntax: rememberA Belief for Secs

forget(Belief)

Remove the first dynamic fact matching Belief. Note that Belief may contain variables within the arguments. forget always succeeds even if there are no matching facts.
mode/type    forget : (relcall) ~>>

forget_after(Belief, Secs)

The same as forget except that Belief is forgotten when Secs seconds has elapsed and Belief must be ground at the time of call.
mode/type    forget_after : (relcall, num) ~>>

Alternative syntax: forget Belief after Secs

replace_by(Belief1, Belief2)

The same as forget(Belief1) ; remember(Belief2). Belief1 and Belief2 may share variables.

Name := Expression

Here Name is an atom that must have been initialised with a statement

int Name:=Integer, e.g. int count:=0 or

num Name:=Number, e.g. num savings:=678.50

in the program. These statements are shorthand for belief declarations and a definition using one fact of a unary relation called Name. They are respectively expanded into:

belief Name: int <=
Name(Integer)

belief Name: num <=
Name(Number)

The action Name := Expression is the same as
forget(Name(_));remember(Name(Expression)).

mode/type    := : (!(?int <= ), !int) ~>> |
       (!(?num <= ), !num) ~>>

Name can be used as though it were a global variable. To access its value the operator $ is applied. The expression $Name evaluates to the current int or num value stored in Name, i.e. in the current Name belief.

Name +:= Expression

As above, Name is an atom that must have been initialised with a statement

int Name:=Integer or num Name:=Number

in the program.

The action Name +:= Expression is the same as
forget(Name(Val));remember(Name(Val+Expression)).

mode/type    := : (!(?int <= ), !int) ~>> |
       (!(?num <= ), !num) ~>>

Example use count +:= 1 for increasing value held in count by 1.

Name -:= Expression

As above, Name is an atom that must have been initialised with a statement

int Name:=Integer or num Name:=Number

in the program.

The action Name -:= Expression is the same as
forget(Name(Val));remember(Name(Val-Expression)).

mode/type    := : (!(?int <= ), !int) ~>> |
       (!(?num <= ), !num) ~>>

Example use savings -:= 67.90 for decreasing the value held in savings by 67.90.

fork_as(Action, Name)

Fork a new Qulog thread, give it the name Name, and start the thread executing Action. If Name is a variable it will be instantiated to a name given by the system. If Name is given it must not be the name of an existing thread.
mode/type    fork_as : (actcall, ?atom) ~>>

Alternative syntax: fork Action as Name

from(Term, Handle)

This is the message receive action. It will succeed it there is a message term in that threads message buffer whose message term unifies with Term and whose message handle unifies with Handle. If not the call will suspend and be repeatedly retried as new messages arrive until it succeeds. When it does succeed, the matched message will be removed from the message buffer.
mode/type    from : (term?, ?handle) ~>>

Alternative syntax: Term from Handle

to(Term, Handle)

This is the message send action. It sends Term as a message to the thread (of possibly another process on another machine) whose message address is Handle.
mode/type    to : (??term, !handle) ~>>

Alternative syntax: Term to Handle

thread_sleep(Secs)

Causes the executing thread to suspend for Secs seconds.
mode/type    thread_sleep : (!num) ~>>

3.8 TeleoR Specific Actions

The following actions are available when the system is running in TeleoR mode (after the command teleor has been executed in the interpreter).

actions(Actions)

An interpreter command that can be used in teleor mode when an agent has been started using start_agent. Actions is a list of actions that agent wants the robotic interface to perform. The given actions must have been declared as discrete or durative.
mode/type    actions : ([discrete || durative]) ~>>

kill_agent

Kill the current agent started using start_agent.
mode/type    kill_agent : () ~>>

kill_task(Task)

Kill the task with name Task started using start_task.
mode/type    kill_task : (atom) ~>>

start_agent(Name, Handle, Convention)

Start a new agent whose name is Name. Handle is the message address of the robot interface or simulation with which the agent will interact. Convention is the percepts update convention being used. This is one of: all if the robot sends all the percepts each time it sends percepts; updates if the robot only sends changes to percepts; or user if the percept management is application specific in which case the action handle_percepts_ needs to be defined in the program.
mode/type    start_agent : (atom, handle, atom) ~>>

start_task(Name, TRCall)

Start a new task (as a thread) whose name is Name. TRCall is the TeleoR call to be executed in the thread.
mode/type    start_task : (atom, trcall) ~>>

Table of Contents Overview of QuLog Getting Started Syntax Built-ins Standard Operators Index