Related
I have a predicate that takes two arguments in which the first argument can be a compound one and the second argument is always B. I have also defined some new operators like + and &.
pvc(A, B) :- somestuff(A, B).
Here the user may type something like pvc((x+y)&(A+b), B).
As a beginner in Prolog, what I want to do is to convert the compound A to all lowercase and call somestuff with new AN. So it shall be somestuff((x+y)&(a+b), B).
I tried something like pvc(A, B) :- downcase_atom(A,AN),somestuff(AN, B). But it doesn't seem like to be the correct way. I will appreciate any help.
So, you will need to induct on the structure of your thing, and the easiest way to do this is with the univ operator =../2. First handle your base case, which you did:
downcase_compound(A, B) :- atom(A), downcase_atom(A, B).
Now you will take the structure apart and induct on it using univ:
downcase_compound(A, B) :-
compound(A),
A =.. [Functor|Args],
downcase_compound(Functor, DowncaseFunctor),
maplist(downcase_compound, Args, DowncaseArgs),
B =.. [DowncaseFunctor|DowncaseArgs].
The trick here is simply breaking your compound down into bits you can use, and then recursively calling downcase_compound/2 on those bits. See it in action:
?- downcase_compound((x+y,('A'+b)), X).
X = (x+y, a+b)
Hello good people of programming .
Logic programming is always fascinating compare to imperative programming.
As pursuing unknown of logic programming, there is some problems encountering arithmetic expressions.
Here is the code I have done so far.
number_atom(N) :-
(number(N) -> functor(N, _, _); functor(N, _, _), atom(N)).
arithmeticAdd_expression(V,V,Val,Val).
arithmeticAdd_expression(N, _Var, _Val, N) :-
number_atom(N).
arithmeticAdd_expression(X+Y, Var, Val, R) :-
arithmeticAdd_expression(X, Var, Val, RX),
arithmeticAdd_expression(Y, Var, Val, RY),
(number(RX), number(RY) -> R is RX + RY; R = RX + RY).
Taking add operation as example:
arithmeticAdd_expression(Expression, Variable, Value, Result)
?- arithmeticAdd_expression(a+10, a, 1, Result).
?- Result = 11;
?- Result = a + 10.
?- arithmeticAdd_expression(a+10, b, 1, Result).
?- Result = a + 10.
What I would like to achieve is that
if the atom(s) in the Expression can only be substituted by given Variable and value, then Result is the number only like the example shown above(Result = 11). Else, the Result is the Expression itself only. My problem with the code is somewhere there, I just could figure it out. So, Please someone can help me? Thank you.
An important attraction of logic programming over, say, functional programming is that you can often use the same code in multiple directions.
This means that you can ask not only for a particular result if the inputs are given, but also ask how solutions look like in general.
However, for this to work, you have to put some thought into the way you represent your data. For example, in your case, any term in your expression that is still a logical variable may denote either a given number or an atom that should be interpreted differently than a plain number or an addition of two other terms. This is called a defaulty representation because you have to decide what a variable should denote by default, and there is no way to restrict its meaning to only one of the possible cases.
Therefore, I suggest first of all to change the representation so that you can symbolically distinguish the two cases. For example, to represent expressions in your case, let us adopt the convention that:
atoms are denoted by the wrapper a/1
numbers are denoted by the wrapper n/1.
and as is already the case, (+)/2 shall denote addition of two expressions.
So, a defaulty term like b+10 shall now be written as: a(b)+n(10). Note the use of the wrappers a/1 and n/1 to make clear which case we are dealing with. Such a representation is called clean. The wrappers are arbitrarily (though mnemonically) chosen, and we could have used completely different wrappers such as atom/1 and number/1, or atm/1 and nmb/1. The key property is only that we can now symbolically distinguish different cases by virtue of their outermost functor and arity.
Now the key advantage: Using such a convention, we can write for example: a(X)+n(Y). This is a generalization of the earlier term. However, it carries a lot more information than only X+Y, because in the latter case, we have lost track of what these variables stand for, while in the former case, this distinction is still available.
Now, assuming that this convention is used in expressions, it becomes straight-forward to describe the different cases:
expression_result(n(N), _, _, n(N)).
expression_result(a(A), A, N, n(N)).
expression_result(a(A), Var, _, a(A)) :-
dif(A, Var).
expression_result(X+Y, Var, Val, R) :-
expression_result(X, Var, Val, RX),
expression_result(Y, Var, Val, RY),
addition(RX, RY, R).
addition(n(X), n(Y), n(Z)) :- Z #= X + Y.
addition(a(X), Y, a(X)+Y).
addition(X, a(Y), X+a(Y)).
Note that we can now use pattern matching to distinguish the cases. No more if-then-elses, and no more atom/1 or number/1 tests are necessary.
Your test cases work as expected:
?- expression_result(a(a)+n(10), a, 1, Result).
Result = n(11) ;
false.
?- expression_result(a(a)+n(10), b, 1, Result).
Result = a(a)+n(10) ;
false.
And now the key advantage: With such a pure program (please see logical-purity for more information), we can also ask "What do results look like in general?"
?- expression_result(Expr, Var, N, R).
Expr = R, R = n(_1174) ;
Expr = a(Var),
R = n(N) ;
Expr = R, R = a(_1698),
dif(_1698, Var) ;
Expr = n(_1852)+n(_1856),
R = n(_1896),
_1852+_1856#=_1896 ;
Expr = n(_2090)+a(Var),
R = n(_2134),
_2090+N#=_2134 .
Here, I have used logical variables for all arguments, and I get quite general answers from this program. This is why I have used clpfd constraints for declarative integer arithmetic.
Thus, your immediate issue can be readily solved by using a clean representation, and using the code above.
Only one very small challenge remains: Maybe you actually want to use a defaulty representation such as c+10 (instead of a(c)+n(10)). The task you are then facing is to convert the defaulty representation to a clean one, for example via a predicate defaulty_clean/2. I leave this as an easy exercise. Once you have a clean representation, you can use the code above without changes.
I am trying to develop a prolog procedure that will convert numbers in any given list to a list of their square roots, using the univ (=..). So far I have
convert(X,Y): number(X), Y is X^2.
use([],_,[]).
use([_|X],convert,L):-
convert(X,Y),
L =..[convert,X,Y].
This evaluates false, what could be wrong in my logic or execution?
You could also use maplist/3 to define use/2 with convert/2 as defined in your post:
use(X,Y) :- maplist(convert, X, Y).
?- use([1,2,3],L).
L = [1,4,9]
Note that use/2 is simply failing for lists that contain anything but numbers:
?- use([1,2,3,a],L).
no
There are multiple errors:
why passing the name of the predicate convert/2?
Most important I see no recursive call!!
You ignore head element of the list by writing [_|X] which means a list with a head element and a tail X.
You try to use convert on X which is a list and assign the atom convert(X,Y) to L. Note that prolog is not a procedural language, convert(X,Y) will work only by just calling convert(X,Y) and the result will be in Y, you can't make assignments like: L = convert(X,Y) this will only assign the atom convert(X,Y) to L.
You don't need the operator =.., as a simple solution would be:
convert(X,Y):- number(X), Y is X^2.
use([],[]).
use([H|T],[Y|T1]):-
convert(H,Y),
use(T,T1).
I'm new in Prolog and I was trying to solve sucha problem so i wish if anybody could help.
I want to implement a ternary predicate flatten_term(Term, Function_symbol, Flattened_term)
that succeeds if Flattened_term is obtained from Term by flattening out all
nested occurrences of Function_symbol. It is assumed that Term contains no
Prolog variables and no lists without checking the list.
?- flatten_term(f(f(x)), f, Flattened_term).
Flattened_term = f(x).
?- flatten_term(f(x), f, Flattened_term).
Flattened_term = f(x).
?- flatten_term(a, f, Flattened_term).
Flattened_term = a.
?- flatten_term(g(f(x)), f, Flattened_term).
Flattened_term = g(f(x)).
?- flatten_term(g(f(f(x))), f, Flattened_term).
Flattened_term = g(f(x)).
I'm using the code below in order to count the items in a term. Maybe this is similar to what you are looking for?
?- flatten_term(5+3*x=10,List).
List = [=, +, 5, *, 3, x, 10].
This is the source code:
flatten_term(Term,[Term]):-
atomic(Term),!.
flatten_term(Term,Flat):-
Term =.. TermList,
flatten_term_list(TermList,Flat),!.
flatten_term_list([],[]):-!.
flatten_term_list([H|T],List):-
flatten_term(H,HList),
flatten_term_list(T,TList),
append(HList,TList,List),!.
As noted, you really should show an example of your work. But, here's a few hints for you to get you started:
Flattening a list-of-lists like [a,[b,c],d,[e,[f,g,h]]] is just a simple recursive tree walk. There are several questions here on Stack Overflow that demonstrate how to do this, For instance, this question, How to implement flatten list in prolog ,with tail recursion?
There are a number of predicates concerning type checking and the analysis, construction and decomposition of terms:
http://www.swi-prolog.org/pldoc/man?section=typetest
http://www.swi-prolog.org/pldoc/man?section=manipterm
In particular, compound terms can be decomposed to a list using the univ operator =../2:
foo(alpha,bravo,charlie) =.. L
which yields L = [foo,alpha,bravo,charlie].
One should also note that '=../2` is used to convert a list into a compound term:
T =.. [foo,alpha,bravo,charlie]
which yields, as one might expect T = foo(alpha,bravo,charlie).
Good luck!
I am using Swi-Prolog for what I think is a slightly weird use of Prolog. Reason I say that is 'cause I don't know what people use Prolog for normally aside from Watson.
In any case, I am making a prolog program for defining emotions based off what I tell it like:
emotion(anxiety,emotion):-
emotion(anxiety,prime).
emotion(fear,emotion):-
emotion(anxiety,prime),
emotion(when,prime),
emotion(bad,prime).
emotion(horrified,emotion):-
emotion(surprise,prime),
(emotion(fear,emotion);emotion(aversion,prime)).
The primes are unary so they're not the issue.
I can find emotion(X,Y). which will be everything that I defined with two arguments.
The issue is how can I find words based off the definitions? Could I tell prolog to find all emotions that contained some kind of definition of anxiety? Which would technically be anxiety as an emotion, fear and one of the "horrified" since I made it be definable through either surprise and fear (which entails anxiety) or surprise and aversion.
Is there a command I can use or would I have to program something in order to have prolog produce such a list?
I can find emotion(X,Y).
If you actually enter ?- emotion(X,Y). you'll get just false. as answer.
When you will add some of the facts required by these rules, for instance, assert(emotion(anxiety,prime)). you will get X=anxiety Y=emotion.
(I think that you should have distinct predicates for 'raw data' and categorization.)
Prolog allows inspecting programs, the primary 'reflexive' built in is clause/2. On your program:
?- clause(emotion(X,Y),Body).
X = anxiety,
Y = emotion,
Body = emotion(anxiety, prime) ;
X = fear,
Y = emotion,
Body = (emotion(anxiety, prime), emotion(when, prime), emotion(bad, prime)) ;
X = horrified,
Y = emotion,
Body = (emotion(surprise, prime), (emotion(fear, emotion);emotion(aversion, prime))).
This allows to meta interpret programs (see here for a clear introduction), and to inspect any detail, after providing the 'navigation' tools. Of course, a statement like some kind of definition of anxiety must be detailed: does anxiety occurs as primal, etc etc.
For instance
?- [user].
|: occurs(E,emotion(E,_)).
|: occurs(E,(A,B)) :- occurs(E,A);occurs(E,B).
|: occurs(E,(A;B)) :- occurs(E,A);occurs(E,B).
|: % user://1 compiled 0,20 sec, 4 clauses
true.
?- findall(E, (clause(emotion(E,_),B), occurs(anxiety,B)),L).
L = [anxiety, fear].