The mergingplugin (MErging Library for Dlvhex) consists of a set of external atoms and additional command-line optios for dlvhex,
the definition of a merging plan language, and a command-line tool called mpcompiler
(merging plan compiler).
Altogether these components can be used to merge several belief bases into one. Belief bases are considered to be given in form of HEX programs. The answer sets are assumed to be the knowledge stored in the bases. The result of a merging process will again be a set of answer sets.
For a quick introduction, take a look at our examples.
If you wish to write user-defined merging operators, read the section about operator implementation.
Application: An important application of the MELD system is the merging of decision diagrams. For more information we refer to the Decision Diagram Plugin.
mpcompiler
. This means,
in practical applications, the user will use these atoms only indirectly when the merging task specification is translated into a semantically equivalent HEX program.
&hex
takes two strings that describe a nested HEX program as input and returns a symbolic handle to the program result.
Prog
is evaluatedExample:
handle(A) :- &hex["a. b.", ""](A).This will deliver
handle(0)
, where 0
is a handle to the answer of the nested HEX program. To look into this answer, see below.
&hexfile
takes two strings that describe a nested HEX program as input and returns a symbolic handle to the program result.
File
is evaluatedExample:
handle(A) :- &hexfile["./programs/myprog.hex", ""](A).This will deliver
handle(0)
, where 0
is a handle to the answer of the nested HEX program. To look into this answer, see below.
&callhex{n}
takes the nested HEX program as string constant, n
predicate names over which the input facts to the subprogram are specified (1 ≤ n ≤ 32
), and an optional string constant containing the command line arguments to the reasoner. It returns a symbolic handle to the program result.
n
predicate names which specify the input facts to the subprogram. The number must match the {n}
, where 1 ≤ n ≤ 32
Prog
is evaluatedExample:
isA(sue, cat). isA(bob, dog). isFemale(sue). isMale(bob). handle(A) :- &callhex3["a. b.", isA, isFemale, isMale, ""](A).This will deliver
handle(0)
, where 0
is a handle to the answer of the nested HEX programrun on the facts specified over isA
, isFemale
and isMale
&callhexfile{n}
takes the filename of the nested HEX program as string constant, n
predicate names over which the input facts to the subprogram are specified (1 ≤ n ≤ 32
), and an optional string constant containing the command line arguments to the reasoner. It returns a symbolic handle to the program result.
n
predicate names which specify the input facts to the subprogram. The number must match the {n}
, where 1 ≤ n ≤ 32
File
is evaluatedExample:
isA(sue, cat). isA(bob, dog). isFemale(sue). isMale(bob). handle(A) :- &callhexfile3["./programs/myprog.hex", isA, isFemale, isMale, ""](A).This will deliver
handle(0)
, where 0
is a handle to the answer of the nested HEX program run on the facts specified over isA
, isFemale
and isMale
. To look into this answer, see below.
&answersets
returns a list of handles to the answer sets of a given HEX program
&hex
or &hexfile
A
AS
is only unique within an answer, i.e., a complete identification is only possible with the tuple (A, AS)
Example:
handles(A, AS) :- &hex["a v b.", ""], &answersets[A](AS).This rule will deliver an answer set containing 2 handles since
/a v b.
has two answer sets. For looking into answer sets, see below.
&predicates
returns a list of predicate/arity tuples contained in an answer set of a nested program.
A
A, AS
Pred
Example:
preds(Pred, Arity) :- &hex["a. p(x).", ""], &answersets[A](AS), &predicates[A, AS](Pred, Arity).This rule will deliver two atoms upon
preds
, namely preds(a, 0)
and preds(p, 1)
since the inner program uses propositional atom a
and unary predicate p
.
&arguments
returns a list of triplets describing the atoms upon a certain predicate name within an answer set.
A
A, AS
Pred
) or the special value s
to retrieve the sign of the atom (0 for positive, 1 for strongly negated)ArgIndex
in the I
-th occurrence of the given predicateExample:
pInner(Value1, Value2) :- &hex["p(x, y). p(a, b).", ""], &answersets[A](AS), &arguments[A, AS, p](I, 0, Value1), &arguments[A, AS, p](I, 1, Value2).This rule will deliver two atoms upon
pInner
: pInner(x, y)
and pInner(a, b)
.I
is used in both evaluations of &arguments
. This makes sure that we actually retrieve the first and second argument (indices 0 and 1) of the same occurrence of this predicate.
&operator
takes one string (operator name) and two binary predicates as parameters. Its output parameter is an integer handle to the operator's result.
I,H
, where I
is a parameter index and H
the handle to some program or operator result, which shall be passed to the operator as its I
-th argumentExample:
args(0, A) :- &hex["a. b.", ""](A). args(1, A) :- &hex["c.", ""](A). innerPreds(Pred, Arity) :- &operator["union", args, kvpairs](H), &answersets[H](AS), &predicates[H, AS](Pred, Arity).The program will evaluate both nested programs and pass their answers to operator
union
. Then, the operator result is investigated using atoms &answersets
and &predicates
.
This will deliver the final result innerPreds(a, 0)
, innerPreds(b, 0)
and innerPreds(c, 0)
.--operatorpath
or --op
--operatorpath=path1,path2,...
or --op=path1,path2,...
directly
within this directory will be loaded (non-recursive
!).
--inputrewriter
or --irw
--inputrewriter=program
or --irw=program
input rewriter
. This can be an arbitrary tool that reads from standard input and writes to standard output. The complete dlvhex input will be
directed through this program before reasoning starts.
--operatorinfo
or --opinfo
--operatorinfo=OPERATOR_NAME
or --opinfo=OPERATOR_NAME
--opinfo=union
[common signature] predicate: pred1/arity1; ... predicate: predN/arityN; [belief base] name: nameOfBeliefBase1; mapping: "head1 :- body1." ... mapping: "headM :- bodyM." ... [belief base] name: nameOfBeliefBaseK; mapping: "head1 :- body1." ... mapping: "headJ :- bodyJ." [merging plan] { operator: someOperatorsName; key1: value1; ... keyN: valueN; source: { operator: subPlanOperator; ... source: {nameOfBeliefBase1}; source: {nameOfBeliefBase2}; }; source: { ... }; }Essentially the file consists of 3 sections which are described in the following subsections.
[belief base] name: nameOfBeliefBase1; mapping: "head1 :- body1."; ... mapping: "headM :- bodyM.";where the name defines a legal name for this belief base, followed by an arbitrary number of mappings. Mappings can essentially be arbitrary dlvhex code fragments. However, in reasonable applications they access the underlying (prorietary) belief base and map their content onto the common signature (see above). Alternatively they can also be defined by
[belief base] name: nameOfBeliefBase1; source: "externalfile.hex";where "externalfile.hex" is an external file containing (computation source access rules and) mapping rules. Note that mapping and source cannot be used simultaneously.
operator: XYZ. key1: value1; ... keyN: valueN; source: ...; source: ...;Such a section defines the operator to apply, the key-value pairs that shall be passed to the operator and the sub merging plans (source). A sub merging plan (after a source statement) can either be a belief base (denoted as {bbName};) or a composed merging plan (i.e. the result of a prior operator application).
Lexer | ||
Literal | => | -?Σp(((Σc|Σv)(,Σc|Σv)*))? |
PredicateName | => | [a-z] ( [a-z]|[A-Z]|[0-9])* |
KBName | => | ([a-z]|[A-Z]) ( [a-z]|[A-Z]|[0-9])* |
OPName | => | ([a-z]|[A-Z]) ( [a-z]|[A-Z]|[0-9])* |
Variable | => | [A-Z] ( [a-z]|[A-Z]|[0-9])* |
Number | => | ([1-9] [0-9]*) 0 |
General ASP Grammer | ||
Fact | => | RuleHead . |
Constraint | => | : - RuleBody . |
Query | => | not? Literal (, not? Literal)* |
RuleHead | => | Literal (v Literal)* |
RuleBody | => | Query |
Merging Plan Specific Grammer | ||
Program | => | CommonSigDef Mappings MergingPlan |
CommonSigDef | => | [common signature] PredicateDefinition* |
Mappings | => | KnowledgeBase* |
MergingPlan | => | [merging plan] MergingPlanNode |
MergingPlanNode | => | { operator : OPName ; (key : value)* (source : MergingPlanNode ;)* } | KBName |
PredicateDefinition | => | predicate : PredicateName / Number ; |
PredicateName | => | [knowledge base] name : KBName ; (MappingRule*)|ExternalSource |
MappingRule | => | mapping> : " Rule " ; |
ExternalSource | => | source : Filename ; |
stringliteral | => | "{"}c " (where Sc is the complement of set S) |
Filename | => | stringliteral |
key | => | Σc|stringliteral |
value | => | Σc|stringliteral |
mpcompiler
-parsetree
-help
-spirit
or -bison
boost spirit
resp. bison
generated parser. Default is spirit.
--
passed as additional parameter, standard input will be read additionally to the input files.--filter=
with the attributes
mentioned in the common signature, e.g., in the first example: --filter=a,b,c
mapping
statements. This was only done to provide compact code snippets
in single files. In realistic applications, one would rather use mapping rules that access some external source of computation by the use of appropriate external atoms.{a,b,c}
[common signature] predicate: a/0; predicate: b/0; predicate: c/0; [belief base] name: kb1; mapping: " a. "; [belief base] name: kb2; mapping: " b. c :- b. "; [merging plan] { operator: union; { kb1 }; { kb2 }; }
{a,c}
[common signature] predicate: a/0; predicate: b/0; predicate: c/0; [belief base] name: kb1; mapping: " a. b. c. "; [belief base] name: kb2; mapping: " b. "; [merging plan] { operator: setminus; { kb1 }; { kb2 }; }
{}
and {p(x)}
Both answer sets have minimum distance to the sources. {}
differs in 2 literals from bb1
and in 0 from bb2
and bb3
, thus 2 in total.
p(x)
differs in 1 literal from bb1
, in 1 from bb2
and in 0 from bb3
, thus also 0 in total. For details about the distance computation we refer
to the plugin's built-in documentation system.[common signature] predicate: a/0; predicate: p/1; [belief base] name: bb1; mapping: "a. p(x)."; [belief base] name: bb2; mapping: "-a. -p(x)."; [belief base] name: bb3; mapping: "-a."; [merging plan] { operator: dalal; aggregate: "sum"; {bb1}; {bb2}; {bb3}; }
{a, d}
and {a, b, d}
, because the majority of the answer sets accept d
. The third answer set, {b, -d}
, does
not follow the majority and is therefore killed.[common signature] predicate: a/0; predicate: b/0; predicate: d/0; [belief base] name: bb; mapping: " a1 v a2 v a3. a :- a1. d :- a1. b :- a2. -d :- a2. a :- a3. b :- a3. d :- a3. "; [merging plan] { operator: majorityselection; majorityOf: "d"; {bb}; }
--plugindir
(or -p
) will not be searched for operator libraries.
However, the mergingplugin provides an own command line parameter for specifying additional operator locations.
Entry point of an operator library is a method with the following signature:
std::vector<IOperator*> OPERATORIMPORTFUNCTION()
IOperator
, which is installed in the following subdirectory of the include
directory:
dlvhex/mergingplugin/IOperator.h
std::string getName()
&operator
predicate to call this operator.
In case that multiple operators with the same name are defined, the mergingplugin will print a warning on startup and ignore all but the first one.HexAnswer apply(int arity, std::vector\textless HexAnswer*>& answers, OperatorArguments& parameters) throw (OperatorException)
HexAnswer
, which is defined as vector of AtomSet
(since a HEX answer is a
set of answer-sets.
Finally, OperatorArguments
is the set of key-value pairs. It is defined as std::pair<string, string>
.
The method is expected to return the operator's result as set of answer-sets (i.e. HexAnswer
). In case of an error, an OperatorException
can be thrown which will result in a PluginError
and thus a termination of dlvhex.
General
dlvhex source code @ github.com
Description-Of-A-Project
Popular Plugins
Action Plugin
DecisionDiagrams Plugin
Description Logics Plugin
Description Logics Lite Plugin
MELD: Belief Merging Plugin
Nested HEX Plugin
MCSIE Plugin
String Plugin
dlvhex-semweb Project
Documentation
User Guide
README
doxygen
Writing Plugins in C++
Writing Plugins in Python