Reputation: 1218
I'm starting to learn Prolog, and I'm running into a compiler error with my code. I'm trying to write some code that will check if a family is in poverty if they meet certain conditions. The last line couple of lines are the poverty conditions, and that's where I'm getting the Opertator Expected
error. I'm trying to say that given the family ID, if the size of that family is one, and the income is less than 11170, then that family is in poverty. And for a family of size >8 the poverty level is 38890 plus 3960 for every additional family member. How can I correct these errors? family_in_poverty
should be returning true
or false
.
family(10392,
person(tom, fox, born(7, may, 1960), works(cnn, 152000)),
person(ann, fox, born(19, april, 1961), works(nyu, 65000)),
% here are the children...
[person(pat, fox, born(5, october, 1983), unemployed),
person(jim, fox, born(1, june, 1986), unemployed),
person(amy, fox, born(17, december, 1990), unemployed)]).
family(38463,
person(susan, rothchild, born(13, september, 1972), works(osu, 75000)),
person(jess, rothchild, born(20, july, 1975), works(nationwide, 123500)),
% here are the children...
[person(ace, rothchild, born(2, january, 2010), unemployed)]).
married(FirstName1, LastName1, FirstName2, LastName2) :-
family(_, person(FirstName1, LastName1, _, _),
person(FirstName2, LastName2, _, _), _).
married(FirstName1, LastName1, FirstName2, LastName2) :-
family(_, person(FirstName2, LastName2, _, _),
person(FirstName1, LastName1, _, _), _).
householdIncome(ID, Income) :-
family(ID, person(_, _, _, works(_, Income1)),
person(_, _, _, works(_, Income2)), _),
Income is Income1 + Income2.
exists(Person) :- family(_, Person, _, _).
exists(Person) :- family(_, _, Person, _).
exists(Person) :- family(_, _, _, Children), member(Person, Children).
householdSize(ID, Size) :-
family(ID, _, _, Children),
length(Children, ChildrenCount),
Size is 2 + ChildrenCount.
:- use_module(library(lists)). % load lists library for sumlist predicate
average(List, Avg) :-
sumlist(List, Sum),
length(List, N),
Avg is Sum / N.
family_in_poverty(FamilyID) :- householdSize(FamilyID, 1), householdIncome(ID, X), X <= 11170.
family_in_poverty(FamilyID) :- householdSize(FamilyID, 2), householdIncome(ID, X), X <= 15130.
........
family_in_poverty(FamilyID) :- householdSize(FamilyID, Y), householdIncome(ID, X), X <= 38890 + (Y - 8)*3960, Y > 8.
Upvotes: 2
Views: 17923
Reputation: 1
Simple rule-of-thumb in Prolog: the inequality symbol always points towards the equals symbol. Examples: =<, >=, @=<, @>=, etc. This is different from imperative languages, where the inequality symbol usually appears first.
Upvotes: 0
Reputation:
The error should already show here:
|: family_in_poverty(FamilyID) :- householdSize(FamilyID, 1), householdIncome(ID, X), X <= 11170.
ERROR: user://1:88:0: Syntax error: Operator expected
If you are not sure which operators your Prolog system supports, or which operators you have defined your self, you can list the current definitions via current_op/3. Here is a typical result found for SWI Prolog:
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 6.1.3)
Copyright (c) 1990-2011 University of Amsterdam, VU Amsterdam
?- setof(Z,current_op(X,Y,Z),L), write(X-Y-L), nl, fail; true.
1-fx-[$]
200-fy-[+,-,@,\]
200-xfx-[**]
200-xfy-[^]
250-yfx-[?]
400-yfx-[*,/,//,<<,>>,div,mod,rdiv,rem,xor]
500-yfx-[+,-,/\,\/]
600-xfy-[:]
700-xfx-[<,=,=..,=:=,=<,==,=@=,=\=,>,>=,@<,@=<,@>,@>=,\=,\==,\=@=,as,is]
900-fy-[\+]
990-xfx-[:=]
1000-xfy-[,]
1050-xfy-[*->,->]
1100-xfy-[;]
1105-xfy-[|]
1150-fx-[discontiguous,dynamic,initialization,meta_predicate,
module_transparent,multifile,public,thread_initialization,thread_local,volatile]
1200-fx-[:-,?-]
1200-xfx-[-->,:-]
As you can see there is no operator <= defined. Now a Prolog system when it encounters an input of the form "term atom ..." and atom is not defined as an infix or postfix operator, it issues an syntax error messages "Operator Expected" or somesuch.
What you probably want to do is an arithmetic comparison. The arithmetic comparison less or equal is denoted by the operator =< in Prolog. The operator is even defined in the ISO core standard. It behaves such that the left hand side and the right hand side are evaluated arithmetically and then compared arithmetically.
There is another operator @=< which does not evaluate and which does not an arithmetic comparison but a lexical comparison. In arithmetic comparison when comparing an integer and a float, the integer is first widened to a float. In lexical comparison the type is compared. Therefore:
?- 1 =< 1.0.
true
?- 1 @=< 1.0.
false
Best Regards
SWI Prolog Arithmetic Comparison: http://www.swi-prolog.org/pldoc/doc_for?object=section%282,%274.26%27,swi%28%27/doc/Manual/arith.html%27%29%29
SWI Prolog Lexical Comparison: http://www.swi-prolog.org/pldoc/doc_for?object=section%283,%274.7.1%27,swi%28%27/doc/Manual/compare.html%27%29%29
Upvotes: 1
Reputation: 8823
Prolog doesn't use is <=
for a numeric comparison, just =<
for less-than-or-equal.
When you use the is
keyword, this is an infix predicate is/2 that evaluates the right-hand side as a numeric expression and unifies the result with the left-hand side.
Upvotes: 4
Reputation: 1357
Not sure if this will help, but try breaking it down a bit further ie. one line for the calculation, another for the comparison:
family_in_poverty(FamilyID) :-
householdSize(FamilyID, Y),
householdIncome(ID, X),
M is 38890 + (Y - 8)*3960,
X =< M,
Y > 8.
Upvotes: 1