? users online
  • Logout
    • Open hangout
    • Open chat for current file
<div class="notebook">

<div class="nb-cell markdown" name="md1">
# Travel Recommendation System
----
### 1. Introduction
- Objective:  
The aim of this project is to develop a Travel Recommendation System using Prolog that suggests travel destinations based on user preferences.

----
### 2. System Overview
- Language: 
	- Prolog

- Features:
	- Collects user preferences
    
	- Matches user preferences with city data
    
	- Recommends cities based on exact and closest matches
    
	- Provides sightseeing spots for each recommended city
	
    - Offers an option to search for another destination or end the session

----
</div>

<div class="nb-cell markdown" name="md2">
### 3. Program
</div>

<div class="nb-cell program" name="p1">
% City information
city_info(karachi, urban, affordable, 4, hot, moderate, local_cuisine, urdu, ['Mazar-e-Quaid', 'Clifton Beach', 'Mohatta Palace']).
city_info(lahore, cultural, affordable, 4, hot, moderate, local_cuisine, punjabi, ['Badshahi Mosque', 'Lahore Fort', 'Shalimar Gardens']).
city_info(islamabad, nature, moderate, 3, mild, moderate, local_cuisine, urdu, ['Faisal Mosque', 'Daman-e-Koh', 'Rawal Lake']).
city_info(paris, cultural, expensive, 4, mild, high, gourmet, french, ['Eiffel Tower', 'Louvre Museum', 'Notre-Dame Cathedral']).
city_info(barcelona, cultural, moderate, 3, mild, moderate, local_cuisine, spanish, ['Sagrada Familia', 'Park Güell', 'La Rambla']).
city_info(doha, urban, expensive, 4, hot, high, gourmet, arabic, ['Museum of Islamic Art', 'Souq Waqif', 'Katara Cultural Village']).
city_info(beirut, cultural, moderate, 3, mild, moderate, local_cuisine, arabic, ['Beirut Souks', 'Pigeon Rocks', 'National Museum of Beirut']).
city_info(damascus, historical, affordable, 4, mild, moderate, local_cuisine, arabic, ['Umayyad Mosque', 'Azm Palace', 'Souq al-Hamidiyya']).
city_info(new_york, cultural, expensive, 3, moderate, high, international_cuisine, english, ['Statue of Liberty', 'Central Park', 'Times Square']).
city_info(cairo, historical, affordable, 5, hot, moderate, local_cuisine, arabic, ['Pyramids of Giza', 'Egyptian Museum', 'Khan el-Khalili']).
city_info(bangkok, beaches, moderate, 5, hot, low, street_food, thai, ['Grand Palace', 'Wat Arun', 'Chatuchak Market']).
city_info(sydney, beaches, expensive, 4, mild, high, international_cuisine, english, ['Sydney Opera House', 'Bondi Beach', 'Sydney Harbour Bridge']).
city_info(cape_town, nature, affordable, 5, mild, moderate, local_cuisine, english, ['Table Mountain', 'V&amp;A Waterfront', 'Robben Island']).
city_info(vancouver, outdoor, expensive, 4, moderate, high, international_cuisine, english, ['Stanley Park', 'Granville Island', 'Capilano Suspension Bridge']).
city_info(rio_de_janeiro, beaches, moderate, 5, hot, moderate, street_food, portuguese, ['Christ the Redeemer', 'Copacabana Beach', 'Sugarloaf Mountain']).
city_info(dubai, luxury, expensive, 5, hot, high, gourmet, arabic, ['Burj Khalifa', 'Dubai Mall', 'Palm Jumeirah']).
city_info(amsterdam, cultural, moderate, 3, mild, high, international_cuisine, dutch, ['Rijksmuseum', 'Anne Frank House', 'Van Gogh Museum']).
city_info(hong_kong, urban, expensive, 4, hot, high, street_food, chinese, ['Victoria Peak', 'Tsim Sha Tsui Promenade', 'Disneyland Hong Kong']).
city_info(san_francisco, outdoor, expensive, 3, moderate, high, gourmet, english, ['Golden Gate Bridge', 'Alcatraz Island', 'Fisherman\'s Wharf']).
city_info(mexico_city, cultural, affordable, 4, mild, moderate, street_food, spanish, ['Zócalo', 'Frida Kahlo Museum', 'Chapultepec Park']).
city_info(seoul, cultural, expensive, 3, cold, high, street_food, korean, ['Gyeongbokgung Palace', 'Bukchon Hanok Village', 'N Seoul Tower']).
city_info(auckland, nature, expensive, 4, mild, high, local_cuisine, english, ['Sky Tower', 'Waiheke Island', 'Auckland War Memorial Museum']).
city_info(marrakech, historical, affordable, 5, hot, low, local_cuisine, arabic, ['Jemaa el-Fnaa', 'Bahia Palace', 'Majorelle Garden']).
city_info(istanbul, historical, moderate, 4, mild, moderate, street_food, turkish, ['Hagia Sophia', 'Topkapi Palace', 'Grand Bazaar']).
city_info(berlin, cultural, affordable, 3, cold, high, street_food, german, ['Brandenburg Gate', 'Berlin Wall', 'Museum Island']).
city_info(singapore, urban, expensive, 4, hot, high, street_food, english, ['Marina Bay Sands', 'Gardens by the Bay', 'Sentosa Island']).
city_info(bora_bora, nature, expensive, 5, hot, high, gourmet, french, ['Matira Beach', 'Mount Otemanu', 'Coral Gardens']).
city_info(new_delhi, cultural, affordable, 4, hot, moderate, street_food, hindi, ['Red Fort', 'India Gate', 'Qutub Minar']).
city_info(venice, historical, expensive, 3, hot, high, gourmet, italian, ['St. Mark\'s Basilica', 'Grand Canal', 'Rialto Bridge']).
city_info(athens, historical, moderate, 4, hot, moderate, local_cuisine, greek, ['Acropolis', 'Parthenon', 'Plaka']).
city_info(tokyo, urban, expensive, 4, mild, high, international_cuisine, japanese, ['Tokyo Tower', 'Meiji Shrine', 'Shibuya Crossing']).
city_info(prague, cultural, moderate, 3, cold, moderate, local_cuisine, czech, ['Prague Castle', 'Charles Bridge', 'Old Town Square']).
city_info(budapest, historical, affordable, 4, cold, moderate, local_cuisine, hungarian, ['Buda Castle', 'Chain Bridge', 'Parliament Building']).
city_info(sao_paulo, urban, affordable, 3, hot, moderate, local_cuisine, portuguese, ['Ibirapuera Park', 'Paulista Avenue', 'Municipal Market']).
city_info(kyoto, cultural, expensive, 4, mild, moderate, local_cuisine, japanese, ['Kinkaku-ji', 'Fushimi Inari Shrine', 'Arashiyama Bamboo Grove']).

% Declare user_preference/2 as a dynamic predicate
:- dynamic user_preference/2.

% User interface
get_user_preferences :-
    nl, write('Enter your Preferences!'), nl,
    get_preference(climate, 'What type of climate do you prefer? (hot, mild, cold, moderate) ', valid_climate),
    get_preference(budget, 'What is your budget range? (affordable, moderate, expensive) ', valid_budget),
    get_preference(activity, 'What type of activities do you enjoy - choose one? (cultural, historical, beaches, nature, outdoor, luxury, urban) ', valid_activity),
    get_preference(safety, 'What level of safety do you prefer? (high, moderate, low) ', valid_safety),
    get_preference(food, 'What type of food do you enjoy? (local_cuisine, international_cuisine, street_food, gourmet) ', valid_food),
    get_preference(language, 'What language do you prefer? (english, spanish, french, arabic, chinese, japanese, urdu, punjabi, hindi) ', valid_language).

get_preference(Preference, Prompt, Validation) :-
    write(Prompt), read_line(Value),
    (call(Validation, Value) -&gt; assert(user_preference(Preference, Value));
    write('Invalid input, please try again.'), nl, get_preference(Preference, Prompt, Validation)).

% Validation of inputs
valid_climate(Weather) :-
    member(Weather, [hot, mild, cold, moderate]).

valid_budget(Budget) :-
    member(Budget, [affordable, moderate, expensive]).

valid_activity(Activity) :-
    member(Activity, [cultural, historical, beaches, nature, outdoor, luxury, urban]).

valid_safety(Safety) :-
    member(Safety, [high, moderate, low]).

valid_food(Food) :-
    member(Food, [local_cuisine, international_cuisine, street_food, gourmet]).

valid_language(Language) :-
    member(Language, [english, spanish, french, arabic, chinese, japanese, urdu, punjabi, hindi]).

% Read a line of input and remove trailing newline character
read_line(X) :-
    prompt(_, ''),
    read_line_to_string(user_input, String),
    string_chars(String, Chars),
    remove_trailing_newline(Chars, TrimmedChars),
    atom_chars(X, TrimmedChars).

% Remove trailing newline character from a list of characters
remove_trailing_newline([], []).
remove_trailing_newline(['\n'], []).
remove_trailing_newline([H|T], [H|Trimmed]) :-
    remove_trailing_newline(T, Trimmed).

% Recommendation logic
recommend_destination(City) :-
    user_preference(climate, Weather),
    user_preference(budget, Budget),
    user_preference(activity, Activity),
    user_preference(safety, Safety),
    user_preference(food, Food),
    user_preference(language, Language),
    city_info(City, Activity, Budget, _, Weather, Safety, Food, Language, _).

get_travel_recommendations :-
    retractall(user_preference(_, _)),
    get_user_preferences,
    findall(City, recommend_destination(City), Recommendations),
    (Recommendations \= [] -&gt; display_recommendations(Recommendations); 
    write('No exact match found for your preferences. Finding closest matches...'), nl,
    find_closest_matches).

display_recommendations([]) :- !.
display_recommendations([H | T]) :-
    write('Recommended destination: '), write(H), nl,
    display_sightseeing_spots(H),
    display_recommendations(T).

display_sightseeing_spots(City) :-
    city_info(City, _, _, _, _, _, _, _, Spots),
    write('Best sightseeing spots in '), write(City), write(': '), write(Spots), nl.

% Finding closest matches
find_closest_matches :-
    findall(City, city_info(City, _, _, _, _, _, _, _, _), Cities),
    score_cities(Cities, ScoredCities),
    include(min_score(3), ScoredCities, FilteredCities),
    (FilteredCities \= [] -&gt; (
        keysort(FilteredCities, SortedCities),
        reverse(SortedCities, DescendingCities),
        top_n(3, DescendingCities, TopCities),
        display_closest_recommendations(TopCities)
    ); write('No suitable matches found based on your preferences.'), nl).

min_score(MinScore, Score-_) :-
    Score &gt;= MinScore.

score_cities([], []).
score_cities([City | Rest], [Score-City | ScoredRest]) :-
    city_info(City, Activity, Budget, _, Weather, Safety, Food, Language, _),
    findall(1, (
        (user_preference(climate, Weather));
        (user_preference(budget, Budget));
        (user_preference(activity, Activity));
        (user_preference(safety, Safety));
        (user_preference(food, Food));
        (user_preference(language, Language))
    ), Matches),
    length(Matches, Score),
    score_cities(Rest, ScoredRest).

top_n(0, _, []) :- !.
top_n(_, [], []) :- !.
top_n(N, [H | T], [H | NT]) :-
    N1 is N - 1,
    top_n(N1, T, NT).

display_closest_recommendations([]) :- !.
display_closest_recommendations([Score-City | T]) :-
    write('Recommended destination: '), write(City), write(' - matches: '), write(Score), nl,
    write_preferences_matched(City), nl,
    display_closest_recommendations(T).

write_preferences_matched(City) :-
    city_info(City, Activity, Budget, _, Weather, Safety, Food, Language, _),
    findall(P, (
        (user_preference(climate, Weather), P = 'climate');
        (user_preference(budget, Budget), P = 'budget');
        (user_preference(activity, Activity), P = 'activity');
        (user_preference(safety, Safety), P = 'safety');
        (user_preference(food, Food), P = 'food');
        (user_preference(language, Language), P = 'language')
    ), Preferences),
    write('You will find here: '), write(Preferences).

% Ask if user wants to find another destination or is done
ask_for_next_action :-
    nl,
    write('Do you want to look for another travel destination? (yes/no) '),
    read_line(Response),
    normalize_response(Response, Normalized),
    process_response(Normalized).

normalize_response(Response, Normalized) :-
    downcase_atom(Response, Normalized).

process_response(yes) :-
    get_travel_recommendations,
    ask_for_next_action.
process_response(no) :-
    nl, write('Thank you.'), nl.
process_response(_) :-
    write('Invalid response. Please enter yes or no.'), nl,
    ask_for_next_action.

% Main predicate to start the program
main :-
    get_travel_recommendations,
    ask_for_next_action.

</div>

<div class="nb-cell markdown" name="md4">
----
### 4. Query
</div>

<div class="nb-cell query" name="q1">
main.
</div>

<div class="nb-cell markdown" name="md3">
----
### 5. Data Structures and Predicates
- City Information: 
	- city_info(city, activity, budget, rating, climate, safety, food, language, sights).
 The city_info/9 predicate stores data for each city. 
- User Preferences: 
The user_preference/2 predicate stores user input dynamically.

----
### 6. User Interface
- Getting User Preferences
- Input Validation

----
### 7. Recommendation Logic
- Exact Matches:
	- recommend_destination/1: Finds cities that exactly match user preferences.
	- get_travel_recommendations/0: Manages the process of collecting preferences and finding recommendations.
- Closest Matches:
	- find_closest_matches/0: Finds and scores cities that closely match user preferences.
	- score_cities/2: Scores each city based on the number of matching preferences.
	- min_score/2: Filters cities based on a minimum score.
	- top_n/3: Selects the top N highest-scoring cities.
- Displaying Recommendations:
	- display_recommendations/1: Outputs exact match recommendations.
	- display_closest_recommendations/1: Outputs closest match recommendations.
	- display_sightseeing_spots/1: Displays sightseeing spots for each city.
	- write_preferences_matched/1: Lists the matched preferences for each city.

----
### 8. Conclusion
- Summary: 
This Travel Recommendation System successfully demonstrates how Prolog can be used to create a rule-based expert system for recommending travel destinations.
- Future Work: 
Future improvements could include integrating more detailed user preferences, enhancing the scoring algorithm, and creating a more user-friendly interface.
</div>

</div>