Did you know ... Search Documentation:
Pack link_grammar_prolog -- patches/4.1b/README.md

These instructions show examples on how to use the Link Grammar from SWI-Prolog.

First, load the library. Open the SWI-Prolog interprete and run the following commands:

?- use_module(library(lgp)).

%  library(shlib) compiled into shlib 0.01 sec, 9,176 bytes
% c:/program files/swi-prolog/lgp_lib.pl compiled into lgp_lib 0.01 sec, 28,172 bytes

?- lgp:create_dictionary('4.0.dict', '4.0.knowledge', '4.0.constituent-knowledge', '4.0.affix', Dictionary_handle).

Dictionary_handle = '$dictionary'(0)

Yes

Note: If an exception "cant_create" is reported, make sure that the words/ subdirectory is present in the current directory, and that the 4 specified database files (dict, knowledge, constituent-knowledge and affix) are also referenced properly from the current directory. If SWI-Prolog is killed during this command, check that the content of words/ is matching with the LGP source files used to build lgp.dll (even if the version appears to be the same, it is always better to reextract the content of words/ when extracting the system-?.?.tar.gz archive

?- lgp:create_parse_options([disjunct_cost=2, min_null_count=0, max_null_count=0, linkage_limit=100, max_parse_time=10, max_memory=128000000], PO_handle).

PO_handle = '$options'(0)

Yes
?- lgp:create_parse_options([disjunct_cost=3, min_null_count=1, max_null_count=250, linkage_limit=100, max_parse_time=10, max_memory=128000000], Panic_PO_handle).

Panic_PO_handle = '$options'(1)

Yes
?- lgp:enable_panic_on_parse_options($Panic_PO_handle).

Yes
?- lgp:create_sentence('This is the first recorded sentence', $Dictionary_handle, Sentence_0).

Sentence_0 = '$sentence'(0)

Yes
?- lgp:create_linkage_set($Sentence_0, $PO_handle, Linkage_set_handle_0).

Linkage_set_handle_0 = '$linkageset'(0)

Yes
?- lgp:create_sentence('The software is now fully installed', $Dictionary_handle, Sentence_1).

Sentence_1 = '$sentence'(1)

Yes
?- lgp:create_linkage_set($Sentence_1, $PO_handle, Linkage_set_handle_1).

Linkage_set_handle_1 = '$linkageset'(1)

Yes
?- get_nb_parse_options(Nb).

Nb = 2

Yes
?- get_handles_nb_references_parse_options(Handle, Nb).

Handle = ['$options'(1), '$options'(0)]
Nb = [0, 2]

Yes
?- get_nb_sentences(Nb).

Nb = 2 ;

No
?- get_handles_nb_references_sentences(Handle, Nb).

Handle = ['$sentence'(1), '$sentence'(0)]
Nb = [1, 1]

Yes
?- get_handles_sentences(HS).

HS = ['$sentence'(1), '$sentence'(0)]

Yes
?- lgp:get_linkage($Linkage_set_handle_1, Linkage).
Linkage = [link([m], connection(e-[m], fully(_G608), installed(v))), link([m], connection(e-[], now(e), installed(v))), link([m], connection(p-[v], is(v), installed(v))), link([m], connection(s-[s], software(n), is(v))), link([m], connection(d-[m|...], the(_G516), software(n))), link([m], connection(w-[...], 'left-wall'(_G493), software(n))), link([], connection(... -..., 'left-wall'(...), 'right-wall'(...)))] ;

No

This is the list of links in this linkage set. SWI-Prolog doesn't print this list in a readable way, so the following will extract one member after the other.

?- help(member).
member(?Elem, ?List)
    Succeeds  when Elem can be unified with one of the members  of List.
    The predicate can be used with any instantiation pattern.


Yes
?- member(One_link, $Linkage).

One_link = link([m], connection(e-[m], fully(_G355), installed(v))) ;

One_link = link([m], connection(e-[], now(e), installed(v))) ;

One_link = link([m], connection(p-[v], is(v), installed(v))) ;

One_link = link([m], connection(s-[s], software(n), is(v))) ;

One_link = link([m], connection(d-[m, u], the(_G447), software(n))) ;

One_link = link([m], connection(w-[d], 'left-wall'(_G470), software(n))) ;

One_link = link([], connection(rw-[], 'left-wall'(_G487), 'right-wall'(_G489))) ;

No

We now go back the the sentence 0, recorded in linkage set 0, and fail get_linkage to see the 3 different linkages in the linkage set

?- lgp:get_linkage($Linkage_set_handle_0, Linkage).

Linkage = [link([m], connection(e-[], first(a), recorded(v))), link([m], connection(a-[], recorded(v), sentence(n))), link([m], connection(d-[s], the(_G622), sentence(n))), link([m], connection(o-[s, t], is(v), sentence(n))), link([m], connection(s-[s|...], this(p), is(v))), link([m], connection(w-[...], 'left-wall'(_G543), this(p))), link([], connection(... -..., 'left-wall'(...), 'right-wall'(...)))] ;

Linkage = [link([m], connection(a-[], recorded(v), sentence(n))), link([m], connection(l-[], the(_G645), first(a))), link([m], connection(d-[s], the(_G622), sentence(n))), link([m], connection(o-[s, t], is(v), sentence(n))), link([m], connection(s-[s|...], this(p), is(v))), link([m], connection(w-[...], 'left-wall'(_G543), this(p))), link([], connection(... -..., 'left-wall'(...), 'right-wall'(...)))] ;

Linkage = [link([m], connection(a-[], recorded(v), sentence(n))), link([m], connection(an-[], first(n), sentence(n))), link([m], connection(d-[s], the(_G622), sentence(n))), link([m], connection(o-[s, t], is(v), sentence(n))), link([m], connection(s-[s|...], this(p), is(v))), link([m], connection(w-[...], 'left-wall'(_G543), this(p))), link([], connection(... -..., 'left-wall'(...), 'right-wall'(...)))] ;

No

Let's now look at the last (third) possible linkage set, which is the last one returned by get_linkage/2 before failing

?- member(One_link, $Linkage).

One_link = link([m], connection(a-[], recorded(v), sentence(n))) ;

One_link = link([m], connection(an-[], first(n), sentence(n))) ;

One_link = link([m], connection(d-[s], the(_G403), sentence(n))) ;

One_link = link([m], connection(o-[s, t], is(v), sentence(n))) ;

One_link = link([m], connection(s-[s, _G452, b], this(p), is(v))) ;

One_link = link([m], connection(w-[d], 'left-wall'(_G481), this(p))) ;

One_link = link([], connection(rw-[], 'left-wall'(_G498), 'right-wall'(_G500))) ;

No

The real power of the combination of the Prolog engine and the Link Grammar Parser is the ability to look for a specific link in the sentence. Prolog will thus find the linkage that matches the pattern searched for, within the whole linkage set:

?- lgp:get_linkage($Linkage_set_handle_0, Linkage), member(One_link, Linkage), One_link=link([_], connection(Link_type-Link_subtype_list, is(Type_a), Word_b)).

Linkage = [link([m], connection(e-[], first(a), recorded(v))), link([m], connection(a-[], recorded(v), sentence(n))), link([m], connection(d-[s], the(_G1426), sentence(n))), link([m], connection(o-[s, t], is(v), sentence(n))), link([m], connection(s-[s|...], this(p), is(v))), link([m], connection(w-[...], 'left-wall'(_G1347), this(p))), link([], connection(... -..., 'left-wall'(...), 'right-wall'(...)))]
One_link = link([m], connection(o-[s, t], is(v), sentence(n)))
Link_type = o
Link_subtype_list = [s, t]
Type_a = v
Word_b = sentence(n) ;

Linkage = [link([m], connection(a-[], recorded(v), sentence(n))), link([m], connection(l-[], the(_G1449), first(a))), link([m], connection(d-[s], the(_G1426), sentence(n))), link([m], connection(o-[s, t], is(v), sentence(n))), link([m], connection(s-[s|...], this(p), is(v))), link([m], connection(w-[...], 'left-wall'(_G1347), this(p))), link([], connection(... -..., 'left-wall'(...), 'right-wall'(...)))]
One_link = link([m], connection(o-[s, t], is(v), sentence(n)))
Link_type = o
Link_subtype_list = [s, t]
Type_a = v
Word_b = sentence(n) ;

Linkage = [link([m], connection(a-[], recorded(v), sentence(n))), link([m], connection(an-[], first(n), sentence(n))), link([m], connection(d-[s], the(_G1426), sentence(n))), link([m], connection(o-[s, t], is(v), sentence(n))), link([m], connection(s-[s|...], this(p), is(v))), link([m], connection(w-[...], 'left-wall'(_G1347), this(p))), link([], connection(... -..., 'left-wall'(...), 'right-wall'(...)))]
One_link = link([m], connection(o-[s, t], is(v), sentence(n)))
Link_type = o
Link_subtype_list = [s, t]
Type_a = v
Word_b = sentence(n) ;

No

The expression above looks for all different links concerning is, and returns the linkage (Linkage), the link (One_link), the type of the link (Link_type) and its subtype if any (Link_subtype_list), as well as the type found for the word 'is' (Type_a) and the word link to 'is' (in Word_b) We can also look for all objects linked with the:

?- lgp:get_linkage($Linkage_set_handle_0, Linkage), member(One_link, Linkage), One_link=link([_], connection(_-_, the(_Type_a), Word_b)).

Linkage = [link([m], connection(e-[], first(a), recorded(v))), link([m], connection(a-[], recorded(v), sentence(n))), link([m], connection(d-[s], the(_G982), sentence(n))), link([m], connection(o-[s, t], is(v), sentence(n))), link([m], connection(s-[s|...], this(p), is(v))), link([m], connection(w-[...], 'left-wall'(_G1185), this(p))), link([], connection(... -..., 'left-wall'(...), 'right-wall'(...)))]
One_link = link([m], connection(d-[s], the(_G982), sentence(n)))
Word_b = sentence(n) ;

Linkage = [link([m], connection(a-[], recorded(v), sentence(n))), link([m], connection(l-[], the(_G982), first(a))), link([m], connection(d-[s], the(_G1264), sentence(n))), link([m], connection(o-[s, t], is(v), sentence(n))), link([m], connection(s-[s|...], this(p), is(v))), link([m], connection(w-[...], 'left-wall'(_G1185), this(p))), link([], connection(... -..., 'left-wall'(...), 'right-wall'(...)))]
One_link = link([m], connection(l-[], the(_G982), first(a)))
Word_b = first(a) ;

Linkage = [link([m], connection(a-[], recorded(v), sentence(n))), link([m], connection(l-[], the(_G1287), first(a))), link([m], connection(d-[s], the(_G982), sentence(n))), link([m], connection(o-[s, t], is(v), sentence(n))), link([m], connection(s-[s|...], this(p), is(v))), link([m], connection(w-[...], 'left-wall'(_G1185), this(p))), link([], connection(... -..., 'left-wall'(...), 'right-wall'(...)))]
One_link = link([m], connection(d-[s], the(_G982), sentence(n)))
Word_b = sentence(n) ;

Linkage = [link([m], connection(a-[], recorded(v), sentence(n))), link([m], connection(an-[], first(n), sentence(n))), link([m], connection(d-[s], the(_G982), sentence(n))), link([m], connection(o-[s, t], is(v), sentence(n))), link([m], connection(s-[s|...], this(p), is(v))), link([m], connection(w-[...], 'left-wall'(_G1185), this(p))), link([], connection(... -..., 'left-wall'(...), 'right-wall'(...)))]
One_link = link([m], connection(d-[s], the(_G982), sentence(n)))
Word_b = sentence(n) ;

No

Now, let's have a look at the linkage set objects existing in the memory:

?- get_handles_linkage_sets(HLS).

HLS = ['$linkageset'(1), '$linkageset'(0)]

Yes

We can consult each linkage set to know how many linkages it contains, which sentence it has been created from, and which parse options it used:

?- get_full_info_linkage_sets($linkageset'(1), PLS1).

PLS1 = [num_linkage=1, sentence_handle='$sentence'(1), parse_options_handle='$options'(0)]

Yes

An other solution is to get the information about all linkage sets using get_full_info_linkage_sets/1

?- get_full_info_linkage_sets(Full_info).

Full_info = [[handle='$linkageset'(1), num_linkage=1, sentence_handle='$sentence'(1), parse_options_handle='$options'(0)], [handle='$linkageset'(0), num_linkage=3, sentence_handle='$sentence'(0), parse_options_handle='$options'(0)]]

Yes

The following checks that the reference counts are updated when freeing up objects

?- get_handles_nb_references_sentences(Handle, Nb).

Handle = ['$sentence'(1), '$sentence'(0)]
Nb = [1, 1]

Yes
?- delete_linkage_set($Linkage_set_handle_0).

Yes

After linkage set 0 has been removed, sentence 0 is not referenced anymore

?- get_handles_nb_references_sentences(Handle, Nb).

Handle = ['$sentence'(1), '$sentence'(0)]
Nb = [1, 0]

Yes

We can't delete sentence 1 because it is still referenced

?- delete_sentence('$sentence'(1)).
ERROR: Unhandled exception: lgp_api_error(sentence, still_referenced)

However, we can now delete sentence 0

?- delete_sentence('$sentence'(0)).

Yes

Dictionary 1 is now only referenced by sentence 1 (by only one object)

?- get_handles_nb_references_dictionaries(Handle, Nb).

Handle = ['$dictionary'(1)]
Nb = [1]

Yes
?- delete_all_sentences.

Yes

Returns yes, but actually failed because of one sentence '$sentence'(1) that is still referenced

Let's free up the memory by getting rid of the linkage sets, sentences and parse options

?- delete_all_linkage_sets.

Yes
?- get_full_info_linkage_sets(Full_info).

Full_info = []

Yes
?- delete_all_sentences.

Yes
?- get_nb_sentences(Nb).

Nb = 0

Yes
?- delete_all_parse_options.

Yes
?- get_handles_parse_options(HPO).

HPO = []

Yes

We now only have a dictionary object in memory:

?- get_handles_dictionaries(HD).

HD = ['$dictionary'(0)]

Yes

Let's delete it as well

?- delete_dictionary('$dictionary'(0)).

Yes
?- get_handles_dictionaries(HD).

HD = []

Yes

Note: when all dictionaries have been deleted, an automatic memory leak check is performed In case some memory could not be deallocated properly, an exception "lgp_api(external_space, leak)" will be raised.

We now query Prolog to know which are the foreign libraries loaded

?- current_foreign_library(Lib, Predicates).

Lib = lgp
Predicates = [lgp:create_dictionary(_G454, _G455, _G456, _G457, _G458), lgp:delete_dictionary(_G466), lgp:delete_all_dictionaries, lgp:get_nb_dictionaries(_G480), lgp:get_handles_dictionaries(_G488), lgp:create_parse_options_(_G496), lgp:delete_parse_options(_G504), lgp:delete_all_parse_options, ... :...|...]

Yes

Let's unload the lgp_lib from the memory (this will deallocate the whole space taken by the DLL)

?- unload_foreign_library(lgp).

Yes

We can double-check that the lgp library is not in memory anymore:

?- current_foreign_library(Lib, Predicates).

No
?-