Application
I want to create a python function (e.g., Laplacian(expr)). The Laplacian operator is defined as taking the sum of the second partial derivatives of expr with respect to each variable (e.g., Laplacian(f(x,y,z)) is diff(f,x,x) + diff(f,y,y) + diff(f,z,z). In the expression, there may be arbitrary constants c,k, etc that are not variables as far as the expression is concerned. Just as you cannot take the derivative diff(f,126), taking the derivative of the expression with respect to c is not defined.
Need I need to be able to extract the non-constant free symbols from an expression.
Problem
Though I can construct c = Symbol('c', constant=True, number=True) in Sympy, c.is_constant() evaluates to False. Similarly, g(c).is_constant() evaluates to false. For my application, the symbol c should have the exact same behavior as E.is_constant() == True and g(E).is_constant() == True, as it is a number.
Caveats
I cannot register c as a singleton, as it is only defined with respect to this particular proof or expression.
I cannot construct it in the same way values like E are constructed, as there is no specific numeric value for it to be assigned to.
I cannot simply add a constants keyword to Laplacian, as I do not know all such constants that may appear (just as it would not make sense to add constants=[1,2,3,4,...] to solve()).
I cannot simply add a variables keyword to Laplacian, as I do not know the variables that appear in the expression.
The desired usage is as follows:
>>> C = ... # somehow create the constant
>>> symbols_that_arent_constant_numbers(g(C))
set()
>>> symbols_that_arent_constant_numbers(g(C, x))
{x}
>>> g(C).is_constant()
True
stretch goals: It would be awesome to have an arbitrary constant symbol that absorbs other constant terms in the same way that constantsimp operates. Consider introducing an integration constant c into an expression, and then multiplying that expression by I. As far as we are concerned algebraically, cI=c without loosing any generality.
Note
Per Oscar Benjamin's comments on question, current best practices when constructing a sympy-style method (like Laplacian) is to pass a constants or variables keyword into a method. Bare that in mind when applying the following solution. Furthermore, free_symbols has many applications within Sympy, so using another class that has established semantics may have unexpected side-effects.
(I am not accepting my own solution in the event that a better one comes along, as Mr. Benjamin has pointed out there are many open related issues.)
Solution
Sympy provides a mechanism to create such a constant: sympy.physics.units.quantities.Quantity. Its behavior is equivalent to Symbol and singleton constants, but most notably it does not appear as a free symbol. This can help prevent code from interpreting it as a variable that may be differentiated, etc.
from sympy.physics.units.quantities import Quantity
C = Quantity('C')
print("C constant? : ", C.is_constant())
print("C free symbols : ", C.free_symbols)
print("x constant? : ", x.is_constant())
print("g(C) constant? : ", g(C).is_constant())
print("g(x) constant? : ", g(x).is_constant())
print("g(C,x) constant : ", g(C,x).is_constant())
print("g(C) free symbols : ", g(C).free_symbols)
print("g(C,x) free symbols: ", g(C,x).free_symbols)
assert C.is_constant()
assert C.free_symbols == set([])
assert g(C).is_constant()
assert g(C, x).is_constant() == g(x).is_constant() # consistent interface
assert g(C).free_symbols == set([])
assert g(C, x).free_symbols == set([x])
assert [5/C] == solve(C*x -5, x)
The above snippet produces the following output when tested in sympy==1.5.1:
C constant? : True
C free symbols : set()
x constant? : False
g(C) constant? : True
g(x) constant? : None
g(C,x) constant : None
g(C) free symbols : set()
g(C,x) free symbols: {x}
Note that while g(C).is_constant()==True, we see that g(x).is_constant() == None, as well as g(C,x).is_constant() == None. Consequently, I only assert that those two applications have a consistent interface.
/*
sig a {
}
sig b {
}
*/
pred rel_test(r : univ -> univ) {
# r = 1
}
run {
some r : univ -> univ {
rel_test [r]
}
} for 2
Running this small test, $r contains one element in every generated instance. When sig a and sig b are uncommented, however, the first instance is this:
In my explanation, $r has 9 tuples here and still, the predicate which asks for a one tuple relation succeeds. Where am I wrong?
An auxiliary question: are these two declarations equivalent?
pred rel_test(r : univ -> univ)
pred rel_test(r : set univ -> univ)
The problem is that with the Forbid Overflow option set to No the integer semantics in Alloy is wrap around, and with the default scope of 3 (bits), then indeed 9=1, as you can confirm in the evaluator.
With the signatures a and b commented the biggest relation that can be generated with scope 2 has 4 tuples (since the max size of univ is 2), so the problem does not occur.
It also does not occur in the latest build because I believe it comes with the Forbid Overflow option set to Yes by default, and with that option the semantics of integers rules out instances where overflows occur, precisely the case when you compute the size of the relation with 9 tuples. More details about this alternative integer semantics can be found in the paper "Preventing arithmetic overflows in Alloy" by Aleksandar Milicevic and Daniel Jackson.
On the main question: what version of Alloy are you using? I'm unable to replicate the behavior you describe (using Alloy 4.2 of 22 Feb 2015 on OS X 10.6.8).
On the auxiliary question: it appears so. (The language reference is not quite as explicit as one might wish, but it begins one part of its discussion of multiplicities with "If the right-hand expression denotes a unary relation ..." and (in what I take to be the context so defined) "the default multiplicity is one"; the conditional would make no sense if the default multiplicity were always one.
On the other hand, the same interpretive logic would lead to the conclusion that the language reference believes that unary multiplicity keywords are only allowed before expressions denoting unary relations (which would appear to make r: set univ -> univ ungrammatical). But Alloy accepts the expression and parses it as set (univ -> univ). (The alternative parse, (set univ) -> univ, would be very hard to assign a meaning to.)
Imagine we have the familytree module below (simple example) :
:- module(familytree, [
father/2,
mother/2,
%[...]
]).
father(X,Y) :- male(X),parent(X,Y).
father(unknown, _) :- male(unknown).
mother(X,Y) :- female(X),parent(X,Y).
mother(unknown, _) :- female(unknown).
sister(X,Y) :- female(X),parent(Z,X),parent(Z,Y), X \= Y.
%[... other relation predicates ... ]
I want to use this module predicates with different "dbs", for examples with :
:- module(familytree_xyz, []).
male(james).
male(fred).
male(mike).
female(betty).
female(sandra).
parent(james, fred).
parent(betty, fred).
Or :
:- module(familytree_simpson, []).
male(homer).
male(bart).
female(marge).
female(lisa).
parent(homer, bart).
%[...]
I need :
to choose db on runtime, not on compilation.
to use one or more dbs in same time.
to extend db, for eg. create a “familytree_simpson_extended” db module with other Simpson family members extending “familytree_simpson” db module (see above example)
to be swi-prolog compliant.
For now, I tried to play with term_expansion/2, discontiguous/1, multifile/1, dynamic/1 and thread_local/1 directives, but :
term_expansion/2 seems only usable on compile time,
discontiguous/1, multifile/1, not adapted,
dynamic dbs in prolog are seen as an “Evil” practice, however lot of packages and libraries use its (pengines, broadcast module,http lib, for examples).
thread_local/1 is not very documented and seems not often used in prolog source code (swi-prolog).
With playing with dynamic predicate, I update previous code as follow :
%familytree.pl
:- module(familytree, [
familytree_cleanup_db/0,
familytree_use_db/1,
%[... previous declarations ...]
]).
dynamic male/1, female/1, parent/2.
familytree_cleanup_db :-
retractall(male/1),
retractall(female/1),
retractall(parent/2).
familytree_use_db(ModuleName) :-
assert(male(X) :- ModuleName:male(X)),
assert(female(X) :- ModuleName:female(X)),
assert(parent(X,Y) :- ModuleName:parent(X,Y)).
%[... previous predicates ...]
And :
%main.pl
% use familytree tool predicates
:- use_module(familytree).
%load all familytree dbs at compile time.
:- use_module(familytree_xyz).
:- use_module(familytree_simpson).
:- use_module(familytree_simpson_extended).
main_xyz:-
familytree_cleanup_db,
familytree_use_db(familytree_xyz),
process.
main_simpson_all :-
familytree_cleanup_db,
familytree_use_db(familytree_simpson),
familytree_use_db(familytree_simpson_extended),
process.
process :-
findall(X, father(X,_), Xs),
write(Xs).
And it's ok to use with different db as follow :
?- main_simpson_all.
[homer,homer,abraham]
true.
?- main_xyz.
[james]
true.
So, sorry for the length of the post. Questions :
What are the criteria, pros/cons to consider with this dynamic predicates solution ? is it a good solution ?
What are the best practice / specific design pattern for prolog to do that in a clean / robust code ?**
What's about using thread_local/1 instead dynamic/1 and encapsulate call to new thread to avoid cleanup db?
Expanding my comment, the Logtalk solution is straightforward. First, define a root object with the family relations predicate:
:- object(familytree).
:- public([
father/2, mother/2,
sister/2, brother/2
]).
:- public([
parent/2,
male/1, female/1
]).
father(Father, Child) :-
::male(Father),
::parent(Father, Child).
mother(Mother, Child) :-
::female(Mother),
::parent(Mother, Child).
sister(Sister, Child) :-
::female(Sister),
::parent(Parent, Sister),
::parent(Parent, Child),
Sister \== Child.
brother(Brother, Child) :-
::male(Brother),
::parent(Parent, Brother),
::parent(Parent, Child),
Brother \== Child.
:- end_object.
Note that the lookup of the definitions of the male/1, female/1, and parent/2 starts in self, i.e. in the object, the database, that will receive the queries about the family relations. An example, derived from your sample code would be:
:- object(simpsons,
extends(familytree)).
male(homer).
male(bart).
female(marge).
female(lisa).
parent(homer, bart).
parent(homer, lisa).
parent(marge, bart).
parent(marge, lisa).
:- end_object.
An example query can be:
?- simpsons::parent(homer, Child).
Child = bart ;
Child = lisa.
You can them as many family databases as you want, load them at the same time, and define specializations of them at will. For example:
:- object(simpsons_extended,
extends(simpsons)).
male(Male) :-
^^male(Male).
male(abe).
male(herb).
female(Male) :-
^^female(Male).
female(gaby).
female(mona).
parent(Parent, Child) :-
^^parent(Parent, Child).
parent(abe, homer).
parent(abe, herb).
parent(gaby, herb).
parent(mona, homer).
:- end_object.
This solution fulfills all your requirements. SWI-Prolog is one of the supported Prolog compilers. You can install Logtalk using on of its installers. Alternatively, for SWI-Prolog, you can simply type:
?- pack_install(logtalk).
Update
In your comment to this solution, you asked about injecting a database into the family tree object logic. That's easy but it also requires a different approach. First define familytree as:
:- object(familytree).
:- public([
father/2, mother/2,
sister/2, brother/2
]).
:- public([
parent/2,
male/1, female/1
]).
:- multifile([
parent/2,
male/1, female/1
]).
father(Father, Child) :-
male(Father),
parent(Father, Child).
mother(Mother, Child) :-
female(Mother),
parent(Mother, Child).
sister(Sister, Child) :-
female(Sister),
parent(Parent, Sister),
parent(Parent, Child),
Sister \== Child.
brother(Brother, Child) :-
male(Brother),
parent(Parent, Brother),
parent(Parent, Child),
Brother \== Child.
:- end_object.
Note that is this alternative, we call male/1, female/1, and parent/2 as local predicates but they are also declared as multifile predicates. Now we need to "inject" a family database in the familytree object:
:- category(simpsons).
:- multifile([
familytree::male/1,
familytree::female/1,
familytree::parent/2
]).
familytree::male(homer).
familytree::male(bart).
familytree::female(marge).
familytree::female(lisa).
familytree::parent(homer, bart).
familytree::parent(homer, lisa).
familytree::parent(homer, maggie).
familytree::parent(marge, bart).
familytree::parent(marge, lisa).
familytree::parent(marge, maggie).
:- end_category.
Usage example (assuming familytree.lgt and simpsons.lgt files):
?- {familytree, simpsons}.
...
yes
A couple of sample queries:
?- familytree::parent(homer, Child).
Child = bart ;
Child = lisa ;
Child = maggie.
?- familytree::male(Male).
Male = homer ;
Male = bart.
?- familytree::father(Father, Child).
Father = homer,
Child = bart ;
Father = homer,
Child = lisa ;
Father = homer,
Child = maggie ;
false.
Since the source database obviously plays an important role in your use case, I suggest to make its dedicated identifier explicit in your definitions, so that it is always clear which family source you are actually referencing:
db_male(xyz, james).
db_male(simpsons, bart).
db_female(xyz, betty).
db_female(simpsons, marge).
db_parent_of(xyz, james, fred).
So, you basically have the public and multifile db_male/2, db_female/2, db_parent_of/3 predicates.
Self-contained modules can extend the existing definitions with their own source knowledge bases, made explicit in the first argument. This is where term_expansion/2 and the like may help you: Since the database name is the same within each single module, you can write expansion code that augments module-specific definitions of male/1, female/1 etc. with the suitable db argument and rewrites this to db_male/2 etc. Notice that this rewriting need only happen at compilation time. At run-time, you can supply any DB you choose as the first argument of these predicates.
It is also obvious how global definitions of female/1, male/1 may look like:
male(M) :- db_male(_, M).
Notice also that I am using names like parent_of/2 to make clear which argument is what.
assertz/1 can be used to dynamically augment each individual database when required, again supplying the name explicitly. However, for clean and robust code, I would do as much as possible at compilation time.
An alternative is the use of Prolog dicts. They have been introduced by SWI-Prolog and since release 1.3.0 they are also available in Jekejeke Prolog. If the receiver is not needed, one can simply use an underscore.
File simpson.pl:
:- module(simpson, [gender/3, parent/3]).
:- reexport(familytree).
_.gender(homer) := male.
_.gender(bart) := male.
_.gender(marge) := female.
_.gender(lisa) := female.
_.parent(homer) := bart.
_.parent(homer) := lisa.
_.parent(homer) := maggie.
_.parent(marge) := bart.
_.parent(marge) := lisa.
_.parent(marge) := maggie.
File xyz.pl:
:- module(xyz, [gender/3, parent/3]).
:- reexport(familytree).
_.gender(james) := male.
_.gender(fred) := male.
_.gender(mike) := male.
_.gender(betty) := female.
_.gender(sandra) := female.
_.parent(james) := fred.
_.parent(betty) := fred.
File familytree.pl:
:- module(familytree, [father/3]).
M.father(X) := Y :-
male = M.gender(X),
Y = M.parent(X).
To make the familytree also visible in simpson and xyz use reexport/1. This allows sending a message to simpson or xyz, but nevertheless a method from familytree will be processed. Here is an example run:
Welcome to SWI-Prolog (threaded, 64 bits, version 7.7.19)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
?- Y = simpson{}.father(X).
Y = bart,
X = homer ;
Y = lisa,
X = homer ;
Y = maggie,
X = homer ;
false.
?- Y = xyz{}.father(X).
Y = fred,
X = james ;
false.
The exports of gender/3, parent/3, etc.. will go away with the upcoming release 1.3.1 of Jekejeke Prolog when we have made ('.')/3 call-site aware. But the result for Jekejeke Prolog is the same:
Jekejeke Prolog 3, Runtime Library 1.3.0
(c) 1985-2018, XLOG Technologies GmbH, Switzerland
?- Y = simpson{}.father(X).
Y = bart,
X = homer ;
Y = lisa,
X = homer ;
Y = maggie,
X = homer ;
No
?- Y = xyz{}.father(X).
Y = fred,
X = james ;
No
I am parsing a C++ like declaration with this scaled down grammar (many details removed to make it a fully working example). It fails to work mysteriously (at least to me). Is it related to the use of context dependent predicate? If yes, what is the proper way to implement the "counting the number of child nodes logic"?
grammar CPPProcessor;
cppCompilationUnit : decl_specifier_seq? init_declarator* ';' EOF;
init_declarator: declarator initializer?;
declarator: identifier;
initializer: '=0';
decl_specifier_seq
locals [int cnt=0]
#init { $cnt=0; }
: decl_specifier+ ;
decl_specifier : #init { System.out.println($decl_specifier_seq::cnt); }
'const'
| {$decl_specifier_seq::cnt < 1}? type_specifier {$decl_specifier_seq::cnt += 1;} ;
type_specifier: identifier ;
identifier:IDENTIFIER;
CRLF: '\r'? '\n' -> channel(2);
WS: [ \t\f]+ -> channel(1);
IDENTIFIER:[_a-zA-Z] [0-9_a-zA-Z]* ;
I need to implement the standard C++ rule that no more than 1 type_specifier is allowed under an decl_specifier_seq.
Semantic predicate before type_specifier seems to be the solution. And the count is naturally declared as a local variable in decl_specifier_seq since nested decl_specifier_seq are possible.
But it seems that a context dependent semantic predicate like the one I used will produce incorrect parsing i.e. a semantic predicate that references $attributes. First an input file with correct result (to illustrate what a normal parse tree looks like):
int t=0;
and the parse tree:
But, an input without the '=0' to aid the parsing
int t;
0
1
line 1:4 no viable alternative at input 't'
1
the parsing failed with the 'no viable alternative' error (the numbers printed in the console is debug print of the $decl_specifier_cnt::cnt value as a verification of the test condition). i.e. the semantic predicate cannot prevent the t from being parsed as type_specifier and t is no longer considered a init_declarator. What is the problem here? Is it because a context dependent predicate having $decl_specifier_seq::cnt is used?
Does it mean context dependent predicate cannot be used to implement "counting the number of child nodes" logic?
EDIT
I tried new versions whose predicate uses member variable instead of the $decl_specifier_seq::cnt and surprisingly the grammar now works proving that the Context Dependent predicate did cause the previous grammar to fail:
....
#parser::members {
public int cnt=0;
}
decl_specifier
#init {System.out.println("cnt:"+cnt); }
:
'const'
| {cnt<1 }? type_specifier {cnt++;} ;
A normal parse tree is resulted:
This gives rise to the question of how to support nested rule if we must use member variables to replace the local variables to avoid context sensitive predicates?
And a weird result is that if I add a /*$ctx*/ after the predicate, it fails again:
decl_specifier
#init {System.out.println("cnt:"+cnt); }
:
'const'
| {cnt<1 /*$ctx*/ }? type_specifier {cnt++;} ;
line 1:4 no viable alternative at input 't'
The parsing failed with no viable alternative. Why the /*$ctx*/ causes the parsing to fail like when $decl_specifier_seq::cnt is used although the actual logic uses a member variable only?
And, without the /*$ctx*/, another issue related to the predicate called before #init block appears(described here)
ANTLR 4 evaluates semantic predicates in two cases.
The generated code evaluates a semantic predicate during parsing, and throws an exception of the evaluation returns false. All predicates traversed during parsing are evaluated in this way, including context-dependent predicates and predicates which do not appear at the left side of a decision.
The prediction method evaluates predicates in order to make correct decisions during parsing. In this case, predicates which appear anywhere other than the left edge of the decision being evaluated are assumed to return true (i.e. they are ignored). In addition, context-dependent predicates are only evaluated if the context data is available. The prediction algorithm will not create context structures that were not already provided by the parsing code. If a context-dependent predicate is encountered during prediction and no context is available, the predicate is assumed to return true (i.e. it is ignored for that decision).
The code generator does not evaluate the semantics of the target language, so it has no way to know that $ctx is semantically irrelevant when it appears in /*$ctx*/. Both cases result in the predicate being treated as context-dependent.