user906153
user906153

Reputation: 1218

Prolog - Getting Syntax Error - Operator Expected

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

Answers (4)

RGamboa
RGamboa

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

user502187
user502187

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

hardmath
hardmath

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

magus
magus

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

Related Questions