Related
I'm relatively new in Prolog.
I'm trying to multiply and add all elements of a list, but it only works for one element.
What is wrong?
%Basic
mult([],A,0).
mult([X|Xs],A,S) :-
mult(Xs,A,R),
S is (X * A),
S is S + R.
Thanks for any help.
The problem is with the line S is S + R.. In prolog, one variable cannot take on different values within the body of a clause. Here you expect the value of S to change, but this cannot work (except if R is 0, in which case S stays the same; hence why it already works for single element lists).
You need to use a different variable to store the intermediate result, and only use the output variable for the final result. E.g.:
mult([], _, 0).
mult([X|Xs], A, S):-
mult(Xs, A, R),
Tmp is (X * A),
S is Tmp + R.
I also took the liberty to fix the singleton variable warning you were getting. Although in this case it was harmless, you should never ignore them as they often point to flawed logic.
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.
Good Day,
I have a task (not homework), but test preparation question. Given a value of n where n > 0. I need to find out what 3**n value is. I do have something that works.
% expo
expo([],[]).
expo([X|T], [Y|Result]):-
number(X),
Y is 3 ^ X,
expo(T,Result).
expo([ThrowAway|Tail], [ThrowAway|Result]):-
expo(Tail,Result).
last([X]):-
write("M = "),
write(X).
last([Y|Tail]):-
last(Tail).
do_list(N) :-
findall(Num, between(0, N, Num), L),
expo(L, E),
last(E).
When I run this at the console:
do_list(4).
M = 81
true.
So it does give me what I want. But is a recursive solution necessary? I just want to generate a sequence of numbers and use those numbers as my exponent which I have done, but I had to create two lists to this.
Ideally, I'd like to do:
do_list(4, M).
M = 81
true.
Is this possible to do this without two lists? Is it possible without recursion? I'm new to Prolog, so it's taking me a little getting used to "thinking" in Prolog.
TIA,
coson
If you want to do something in all elements of a list then yes most of the times you need recursion (except from cases like when you use predicates like fundall/3 which does the recursion ...).
If you want to return your result in an argument and not just print it then you need for the above predicate two lists (one is the input and the other one is the output).
Though I don't understand why not just writing:
find_pow(Input,Output):-Output is 3^Input.
From what I understood you calculate 3^i for every i<=n and keep last element which could be done independently. So if I understood corrctly what you're trying to do, this could be done without using lists and recursion (if you use predefined pow function ^ else if you write a predicate that computes the power 3^n then you would use recursion... ).
Example:
?- find_pow(4,X).
X = 81.
I want to create a counter in prolog.
Something like starting it init/0.
Adding 1 increment/0,
and something like get_counter/1. To get the value.
But I don't know how to start something if you have init/0 with no inputs how to set something to 0.
Can someone give me some tips how I should try to do this?
I'm not a native speaker, so if it's not clear what I mean I'm sorry.
Here is something that sort of does what you are trying to achieve:
?- X0 = 0 /* init */, succ(X0, X1) /* inc */, succ(X1, X2) /* inc */.
X0 = 0,
X1 = 1,
X2 = 2.
The init is just giving the variable a value, incrementing is done with succ/2, and the getval is implicit.
However, as I already said in the comment, consider your use case! If you are trying to keep track of how deep inside a loop you are, it is perfectly fine to do it with succ/2 or even following the suggestion by #mat.
So, to count the number of foos in a list:
list_foos([], 0).
list_foos([X|Xs], N) :-
( dif(X, foo)
-> list_foos(Xs, N)
; list_foos(Xs, N0),
succ(N0, N) % or: N0 + 1 #= N
).
You should try out both succ(N0, N) and N0 + 1 #= N to see how you can use them when either one or both of the arguments to list_foos/2 are not ground.
If, however, you need to maintain a global state for some reason: say, you are dynamically changing the database and you need to generate an increasing integer key for a table. Then, you should consider the answer by #coredump. Keep in mind that it is not super easy to write code that runs on any Prolog implementation once you start using "global" variables. One attempt would be to use the predicates for manipulating the database:
:- dynamic foocounter/1.
initfoo :-
retractall(foocounter(_)),
assertz(foocounter(0)).
incrfoo :-
foocounter(V0),
retractall(foocounter(_)),
succ(V0, V),
assertz(foocounter(V)).
And then, you can now count with a global state (it does not need to be in a conjunction like your example use):
?- initfoo.
true.
?- incrfoo.
true.
?- incrfoo.
true.
?- foocounter(V).
V = 2.
This is perfectly valid code but there are many pitfalls, so use with care.
I would use ECLiPSe's non-local variables:
init :- setval(counter, 0).
increment :- incval(counter).
get_counter(V) :- getval(counter, V).
Your implementation might provide something similar. In SWI-prolog, it seems that the same can be achieved with nb_setval (non-backtrackable setval).
A declarative way to solve this is to see this as a relation between two counter values: One before the increment, and one after the increment.
You can use CLP(FD) constraints to relate the two counter values:
counter_next(C0, C) :- C0 + 1 #= C.
Such a predicate is completely pure and can be used in all directions.
A sequence of such relations describes repeatedly incrementing the counter, relating an initial value to its final state:
?- S0 = 0, counter_next(S0, S1), counter_next(S1, S).
S = 2,
S0 = 0,
S1 = 1
EDIT: Suppose you go the other way and manage to implement a 0-ary predicate increment/0, as you ask for, destructively incrementing a global resource. Then you will have severe declarative problems. For example, incrementing the counter must succeed, so we can expect to see:
?- increment.
true.
But this means that the original query is no longer equivalent to its own answer, because the query:
?- true.
true.
certainly does not increment the counter.
It also means you can no longer test and reason about your predicates in isolation, but have to think about the global resource all the time.
This in turn will make it much harder to understand and correct mistakes in your code.
Therefore, I strongly recommend you adopt a declarative way to think about this task, and make the relation between counter values before and after incrementing explicit. As an additional benefit, you can then also use these relations in the other direction, and ask for example: "Which initial counter values, if any, yield a given value when incremented?", or even more generally: "For which arguments does this relation even hold?"
I have the folowing code
isInRange(Point1,Point2,Range):-
manhatan2(Point1,Point2,Manhatan),
Range>Manhatan.
manhatan2 computes the manhatan distance between 2 points give in as a 2 element list [X,Y]
I don't understand why isInRange always evaluates to true
isInRange([0,0],[0,10],9) evaluates to true
isInRange([0,0],[0,10],100) also evaluates to true
I am pretty sure i did the manhatan function right.Have tested it with many values
Can anyone help me understand what is wrong with my code ?
%Edit starts here
So i traced the damn thing and here is more code i use
modul(A,B,R):-A<B,R is B-A.
modul(A,B,R):-A>B,R is A-B.
extractFromList([H|_],X,R):- X is 0,R is H.
extractFromList([_|T],X,R):- X1 is X-1,extractFromList(T,X1,R).
manhatan(X1,Y1,X2,Y2,R):- modul(X1,X2,R1),modul(Y1,Y2,R2),R is R1+R2.
manhatan2(P1,P2,R):-
extractFromList(P1,0,X1),
extractFromList(P1,1,Y1),
extractFromList(P2,0,X2),
extractFromList(P2,1,Y2),
manhatan(X1,Y1,X2,Y2,R).
The extract fromFromList extracts the Xth element from the given list
modul should return |A-B|
Tracing isInRange([0,0],[0,10],100) everthing whent as i whanted.
Tracing isInRange([0,0],[0,10],9) stoped when comparing the manhatan with the range and
started redoing modul(0,10,_GXXX) evaluating _GXXX to -10 and thus the Manhatan < Range condition evaluated to true thus all isInRange evaluating to true
Why does it do that ?
Why does it redo the modul computation in this way ?
The short answer:
The following code does what you want:
manhattan(L1,L2,Result) :- manhattan(L1,L2,0,Result).
manhattan([],[],Res,Res).
manhattan([H1|T1],[H2|T2],Acc,Res) :-
AccNew is Acc + abs(H1-H2),
manhattan(T1,T2,AccNew,Res).
isInRange(P1, P2, Range) :-
manhattan(P1, P2, Distance),
Range > Distance.
Longer answer:
I tried your code and it doesn't behave as you describe it.
For me, isInRange always fails, because 'modul' fails if A==B.
You should change the test on the first case to A =< B.
Or, even better, use the builtin 'abs' function.
I assume that in your previous version you didn't have a test in the second case.
In that case Prolog will try the second case when the first case leads to failure (for example because Range > Manhatan fails).
Adding the test in the second case in one way to solve this problem.