I want to display all cars that were manucfactured after 1997.
How can it be done using nothing than queries?
These are the predicates
/* type(type reference, type of car) */
car_type(01,hatchback).
car_type(02,van).
car_type(03,off_road).
/* car(make ref, type ref, model, reg no, colour, year) */
car(01,01,escort,fsd127,blue,1999).
car(07,01,uno,tre333,blue,1996).
car(02,03,discovery,uje777,red,1995).
car(03,01,starlet,uij236,green,1991).
car(01,02,transit,ski432,green,1991).
car(07,01,bravo,juy677,red,1998).
Below is the query I inputted.
?- car(_,TYPE_REF,_,_,_,(X#>1997)),
car_type(TYPE_REF, TYPE_OF_CARS)
With the error being
false
I want to see the following output
1999 HATCHBACK
1998 HATCHBACK
Your problem is that Prolog does not evaluate arguments inside queries (the procedure you are querying may evaluate them though, but is not what happens in your fact-based source).
So you are passing the term (X#>1997) as the last argument to car/6 which will not unify with any fact.
You may instead use a free variable to query every car and then constrain the value it is bound to:
?- car(_,TYPE_REF,_,_,_,Year), Year > 1997, car_type(TYPE_REF, TYPE_OF_CARS).
TYPE_REF = 1,
Year = 1999,
TYPE_OF_CARS = hatchback ;
TYPE_REF = 1,
Year = 1998,
TYPE_OF_CARS = hatchback.
Or you may start using CLP(fd) and add the constraint first:
?- Year #> 1997, car(_,TYPE_REF,_,_,_,Year), car_type(TYPE_REF, TYPE_OF_CARS).
Year = 1999,
TYPE_REF = 1,
TYPE_OF_CARS = hatchback ;
Year = 1998,
TYPE_REF = 1,
TYPE_OF_CARS = hatchback.
Related
Any ideas on how I can re-format this expression to not return an error?
Z In-Yr Rate Inc. (Contract Eff.) =
IF (
'Sales Force_Opportunity'[Z In-Yr Rate Inc. (by Close Dt. Yr)] = "",
"",
'Sales Force_Opportunity'[Contract_Effective_Date__c]
)
Here's the error
Expressions that yield variant data-type cannot be used to define calculated columns
NOTE: 'sales force opportunity Z in-yr rate inc (by close dt yr) is a whole number and needs to be a whole number if possible
As the error message indicates, you are returning different data types with your expression:
If True: return a string
If False: return a date
This doesn't work. You have return a date in both cases like so:
Z In-Yr Rate Inc. (Contract Eff.) =
IF (
'Sales Force_Opportunity'[Z In-Yr Rate Inc. (by Close Dt. Yr)] = "",
DATE(2000, 1, 1),
'Sales Force_Opportunity'[Contract_Effective_Date__c]
)
I have activity-users relations:
% Signature: activity(Name,Day)/2
% Purpose: describe an activity at the country club and the day it takes place
%
activity(swimming,sunday).
activity(ballet,monday).
activity(judu,tuesday).
activity(soccer,wednesday).
activity(art,sunday).
activity(yoga,tuesday).
% Signature: participate(Child_name,Activity)/2
% Purpose: registration details
%
participate(dany,swimming).
participate(dany,ballet).
participate(dana,soccer).
participate(dana,judu).
participate(guy,judu).
participate(shai,soccer).
I want to create query to get all the participants of activity.
So I use bagof:
activity_participants_list(Activity_Name,List) :- ( bagof(X, participate(X,Activity_Name), List)).
But I want to get List = [] when query: activity_participants_list(dancing,List)
So I added ; List = [] to the end of the function but then
when query
activity_participants_list(A,B) i also get empty list as an answer
And query activity_participants_list(A, []) return true.
I also would like to get yoga with empty list as an answer to activity_participants_list(A,B)
What is the right way to do it?
As you found, bagof fails when the goal has no solutions. This is dumb design, unfortunately. As you also found, ; is tricky to use. Try not to be tempted to use it.
findall works similarly to bagof, and it does give an empty list of results if the goal has no solutions:
activity_participants(Activity, Participants) :-
activity(Activity, _), % we are interested in a concrete activity
findall(Participant, participate(Participant, Activity), Participants).
?- activity_participants(Activity, Participants).
Activity = swimming,
Participants = [dany] ;
Activity = ballet,
Participants = [dany] ;
Activity = judu,
Participants = [dana, guy] ;
Activity = soccer,
Participants = [dana, shai] ;
Activity = art,
Participants = [] ;
Activity = yoga,
Participants = [].
The role of the activity(Activity, _) goal is to bind Activity, this basically forces findall to succeed several times, grouped by activity. If we removed this goal, we wouldn't group by activity, and we would just get a list of all the people participating in any activity:
?- activity_participants(Activity, Participants).
Participants = [dany, dany, dana, dana, guy, shai].
hasAccount(Person,Bank,Amount) – the Person has an account at the Bank with the balance Amount,
lives(Person,City) – the Person lives in the City,
created(Person,Bank,Month,Year) – the Person opened an account at the Bank in Month of the Year.
With the predicates above, I want to try few things, say printing a list of names with accounts they have, I tried the following query.
?- hasAccount(Someone, Bank1, Balance1), hasAccount(Someone, Bank2, Balance2), not Bank1 = Bank2.
Someone = ann
Bank1 = metro_credit_union
Balance1 = 1000
Bank2 = toronto_dominion
Balance2 = 12000
Yes (0.00s cpu, solution 1, maybe more)
Someone = ann
Bank1 = toronto_dominion
Balance1 = 12000
Bank2 = metro_credit_union
Balance2 = 1000
Can you please explain why do I have reversed list again and what I can do to prevent this happening? Thank you!
why I have reversed list again
it happens since you're not stating in your query enough info to break symmetry.
You can use instead
?- hasAccount(Someone, Bank1, Balance1), hasAccount(Someone, Bank2, Balance2), Bank1 #< Bank2.
or some builtin, like findall/3 (or bagof/3)
I have a panel dataset (country-year) in Stata. For instance I have GDP in 1990,1991,..2010 for many countries.
I want to define a variable "GDP in 2006" which exists for all years and contains the 2006 value of GDP.
The way I am doing it now works but is a but clumsy so I was hoping someone would have a better idea:
qui gen gdp2006=.
replace gdp2006=gdp if year==2006
forval t=2007/2010 {
sort country year
qui replace gdp2006=gdp2006[_n-1] if year==`t'&country[_n-1]==country
}
forval t=2005(-1)1990 {
sort country year
qui replace gdp2006=gdp2006[_n+1] if year==`t'&country[_n+1]==country
}
Thanks!
You can do this in one line
egen gdp2006 = mean(gdp / (year == 2006)), by(country)
(year == 2006) evaluates as 1 or 0, so the expression
gdp / (year == 2006)
evaluates as gdp when year is 2006 and missing otherwise. Missings are ignored in calculating the mean for each country.
For a wider and more systematic discussion see http://www.stata-journal.com/article.html?article=dm0055 (which will be accessible to all in a few weeks from this posting).
P.S. The techniques you know permit shortening of your code:
gen gdp2006 = gdp if year == 2006
bysort country (gdp2006): replace gdp2006 = gdp2006[_n-1] if _n > 1
gen gdp2006_temp = gdp if year == 2006
bys country : egen gdp2006 = total(gdp2006_temp)
drop gdp2006_temp
The key here is to use the by: prefix and the fact that the total() egen function ignores missing values.
I have a database i want to write a query to return the total members in the database
member(paul,100). member(john,101). member(ryan,102). member(jabouki,103).
Should Return 4
I also have a list and i want to return the number of persons in the list
memberlist([ant,cat,sat,bat]).
Should Return 4
Query I have thus far that only return the items in the database and list.
member(MemberName,_).
memberlist(Y)
findall(X, member(X,_), L), length(L,N).
Will give you the following results:
L = [paul, john, ryan, jabouki],
N = 4.
Greetings
Solick