:-
). Head :- Body.​
mortal(X) :- human(X).​
mortal
` is the predicate in the head, and `human(X)
` is the goal in the body. This clause states that if `X
` is a human, then `X
` is mortal. likes(john, pizza).
parent(john, sarah).
color(red).​
mortal(X) :- human(X).
grandparent(X, Y) :- parent(X, Z), parent(Z, Y).
even(N) :- 0 is mod(N, 2).​
likes(john, pizza).
likes(john, burger).
likes(john, ice_cream).
food_lover(X) :- likes(X, _), !.
food_lover(X) :- dislikes(X, _).
?- food_lover(john).​
likes/2
` that defines John's food preferences. The `food_lover/1
` predicate is defined to determine if someone is a food lover. It first checks if the person likes any food using the `likes(X, _)
` goal. If there is a match, the cut operator (!) is encountered, committing to the choice of the person being a food lover. As a result, Prolog will not backtrack to explore the alternative rule `food_lover(X) :- dislikes(X, _).
` for the same person. The cut operator prevents any further search for alternative solutions beyond that point.food_lover(john)
` will succeed, and Prolog will not backtrack to consider the alternative rule `food_lover(X) :- dislikes(X, _).
`not/1
` or the operator `\+/1
`. These constructs provide a way to express negation and perform negation as failure in Prolog.not/1
` predicate or `\+/1
` operator work as follows:not/1
` Predicate : The `not/1
` predicate takes a single argument, which is the goal or condition to be negated. It succeeds if the goal cannot be proven (i.e., if the goal fails) and fails if the goal succeeds. It performs negation by attempting to prove the goal and backtracks if the goal succeeds, ensuring that it fails.\+/1
` Operator : The `\+/1
` operator is an alternative notation for negation in Prolog. It functions in the same way as `not/1
`. It is used by placing it before a goal or condition that you want to negate. It succeeds if the goal fails and fails if the goal succeeds.
Here's an example to illustrate the usage of logical negation in Prolog:likes(john, pizza).
likes(john, burger).
vegetarian(X) :- not(likes(X, meat)).
?- vegetarian(john).​
likes/2
` predicate that represents John's food preferences. The `vegetarian/1
` predicate is defined to determine if someone is a vegetarian. It uses the `not/1
` predicate to express the negation of liking meat. If a person does not like meat, they are considered a vegetarian.vegetarian(john)
` is executed, Prolog attempts to prove the goal by executing the `not(likes(john, meat))
` subgoal. Since John does not have any fact that states he likes meat, the subgoal fails, and the `vegetarian(john)
` query succeeds. []
` represents an empty list.[1, 2, 3]
` represents a list with elements 1, 2, and 3.[apple, orange, banana]
` represents a list of fruits.[1 | [2, 3]]
` represents a list with elements 1, 2, and 3.[apple | [orange, banana]]
` represents a list of fruits.
3. Using the List Concatenation Operator : Prolog provides a list concatenation operator (`++`) to combine two lists into a single list. It is represented as `List1 ++ List2
`, where `List1
` and `List2
` are existing lists. For example:[1, 2] ++ [3, 4]
` represents a list with elements 1, 2, 3, and 4.[apple, orange] ++ [banana]
` represents a list of fruits.list/1
` predicate that can be used to define lists explicitly. It takes a single argument, which is the list itself. For example:list([])
` represents an empty list.list([1, 2, 3])
` represents a list with elements 1, 2, and 3.list([apple, orange, banana])
` represents a list of fruits.2 + 3`, `X * Y`, `4 - Z
`is/2
` predicate. It allows you to compute the value of an arithmetic expression and bind it to a variable. The `is/2
` predicate is used as follows:X is 2 + 3 * Y
``X > 5`, `Y + Z = 10`, `A mod 2 = 0`
(even number constraint)`=/2` (unification)
: Checks if two terms unify.`==/2` (term equality)
: Checks if two terms are exactly equal.`\=/2` (term inequality)
: Checks if two terms are not equal.`<>/2` (arithmetic inequality)
: Checks if two arithmetic expressions are not equal.`</2`, `>/2`, `<=/2`, `>=/2` (arithmetic comparisons)
: Compare arithmetic expressions.X is 2 + 3 * Y
`X = 2 + 3 * Y
` :- dynamic my_predicate/arity.​
2. Modifying Predicate Clauses : With dynamic predicates, you can assert new clauses or retract existing ones at runtime. The `assertz/1` predicate is used to add a new clause to a dynamic predicate, and the `retract/1` predicate is used to remove an existing clause. For example: assertz(my_predicate(X)) :- ... % Add a new clause to my_predicate/1
retract(my_predicate(X)) :- ... % Remove a clause from my_predicate/1​
3. Runtime Flexibility : Dynamic predicates provide flexibility in modifying program behavior while the program is running. They allow you to adapt and update the knowledge base, extend rules, and handle dynamic data or changing environments. This feature is particularly useful in applications that require runtime customization or adaptability.
4. Database-Like Functionality : Dynamic predicates can be used to emulate a database-like functionality in Prolog. They enable the storage and retrieval of facts and rules at runtime, providing a mechanism to maintain a dynamic knowledge base.assertz/1
`, `retract/1
`, and others.bagof/3
` and `setof/3
` predicates are used for generating sets of solutions to a query. However, there is a key difference between these two predicates in how they handle duplicate solutions. Here's an explanation of the difference between `bagof/3
` and `setof/3
`:bagof/3
` predicate is used to generate a bag (i.e., a list) of solutions to a query.bagof/3
` will fail, and the resulting list will be empty. bagof(X, likes(X, pizza), PeopleWhoLikePizza).​
setof/3
` predicate is used to generate a sorted set of solutions to a query, removing any duplicates.setof/3
` will fail, and the resulting set will be empty. setof(X, likes(X, pizza), UniquePeopleWhoLikePizza).​
assert/1
` and `retract/1
` are used to modify the dynamic database of predicates during runtime. However, they have different purposes and behaviors. Here's the difference between `assert/1
` and `retract/1
`: assert(parent(john, mary)).​
parent(john, mary)
` to the dynamic predicate `parent/2
`.
2. `retract/1` Predicate : retract(parent(john, mary)).​
assert/1
` and `retract/1
` operate on dynamic predicates, which are explicitly declared using the `dynamic/1
` directive. Attempting to use `assert/1
` or `retract/1
` on static predicates or undefined predicates will result in an error.assert/1
` and `retract/1
` provides the ability to dynamically modify the database of facts and rules during program execution, enabling dynamic updates and customization of the knowledge base. However, caution should be exercised when using these predicates to ensure proper synchronization and maintain consistency in the program's logic. call/1
` is used to dynamically invoke predicates and goals. It allows you to evaluate a goal or predicate that is specified at runtime as an argument. Here's the purpose of the `call/1
` predicate:call/1
` is to invoke predicates or goals dynamically.call/1
` allows you to construct and evaluate goals or predicates dynamically, based on program conditions or user inputs.call/1
` is a fundamental tool in metaprogramming, where programs manipulate and generate other programs.call/1
` can be used to implement program transformations, code synthesis, and program analysis.
3. Higher-Order Programming :call/1
`.call/1
`, you can control the program's control flow dynamically by conditionally invoking different predicates or goals based on runtime conditions.findall/3
` is used to gather all solutions to a query and collect them into a list. It allows you to find and collect multiple solutions to a goal or predicate into a structured format. Here's the use of the `findall/3
` predicate:?- findall(X, likes(X, pizza), PeopleWhoLikePizza).​
catch/3
`. The `catch/3
` predicate allows you to catch and handle exceptions that occur during the execution of a goal. Here's how you can handle exceptions and errors in Prolog: catch(Goal, Exception, Handler)​
divide(X, Y, Result) :-
catch(Result is X / Y, error(Err, _), handle_error(Err, Result)).
handle_error(zero_divisor, Result) :-
write('Error: Division by zero.'),
Result = 'Infinity'.​
divide/3
` predicate attempts to calculate the division of `X
` by `Y
`. If a `zero_divisor` error occurs, the `handle_error/2
` predicate is called, which displays an error message and assigns the result as `'Infinity
'`.catch/3
`, you can define specific exception handling behavior to handle errors, recover from exceptional conditions, and control the flow of execution when exceptions occur in Prolog programs. !
`) to control the backtracking behavior and prevent unnecessary backtracking that could lead to infinite loops.once/1
`, `repeat/0
`, and `fail/0
` that can be used to control backtracking explicitly and avoid infinite loops.!
`) and the fail predicate (`fail
`), you can control backtracking and terminate loops explicitly.fail
` to force backtracking.parent(X, Y)
defines the relationship between a parent and a child.
When Prolog is asked to prove a predicate, it uses unification to match the terms in the predicate with terms in the database. If the predicate can be unified with a term in the database, then the predicate is proved.parent(X, Y)
:?- parent(X, Y).​
X
with terms in the database. If it finds a match, it will then try to unify the term Y
with the remaining terms in the database. If it finds a match for both X
and Y
, then the predicate parent(X, Y)
is proved.sort(List, Sorted) :-
quicksort(List, [], Sorted).
quicksort([], Acc, Acc).
quicksort([H|T], Acc, Sorted) :-
pivoting(H, T, L1, L2),
quicksort(L1, Acc, Sorted1),
quicksort(L2, [H|Sorted1], Sorted).
pivoting(H, T, L1, L2) :-
choose_pivot(H, T, Pivot),
partition(T, Pivot, L1, L2).
choose_pivot(H, T, Pivot) :-
length(T, N),
select(N div 2, T, Pivot).
partition(List, Pivot, Smaller, Larger) :-
smaller_than(Pivot, List, Smaller),
append(Smaller, [Pivot], List1),
not(smaller_than(Pivot, List1)),
append(List1, Larger, List).
smaller_than(Pivot, [H|T], Smaller) :-
H < Pivot,
Smaller = [H|T].
smaller_than(Pivot, [], Smaller).​
This code implements a quicksort algorithm in Prolog. The sort/3
predicate takes a list as input and returns a sorted list as output. The quicksort/3
predicate recursively sorts the list by choosing a pivot element and partitioning the list into two smaller lists, one containing elements smaller than the pivot and the other containing elements larger than the pivot. The pivoting/3
predicate chooses a pivot element by randomly selecting an element from the list. The partition/3
predicate partitions the list into two smaller lists based on the pivot element. The smaller_than/3
predicate checks if an element is smaller than a pivot element.