Course Map

From UBC Wiki

Authors: Ramit, Nia

What is the problem?

When planning your degree, looking at a list of all the courses and figuring out one by one which ones you need to take when is complicated and slow. We compiled a dataset of all the MATH and CPSC courses UBC offers, in a graph structure, and wrote functions that tell you the prerequisites of a given course, all the courses you can take given the prerequisites that you completed, etc. This makes it a lot easier to course plan than going on the SSC and individually clicking each course to see what its prerequisites are, and then comparing that to the courses you've already taken, and then also having to think about whether this course is good overall for your degree.

What is the something extra?

When a student has already taken several courses in a subject, it can be hard to look at the whole list of UBC courses and decide which ones they can take next, while also keeping in mind that they want to keep taking courses similar to those they have taken in the past, because in the past they chose courses that interested them. We think that overall, the point of an undergrad degree should be to specialize more in some subfields of the student's major. So, we wrote a function called recommend_most_advanced_courses, that takes a list of all the courses a student has previously taken, and returns a list of "most advanced courses" that they can take next. These "most advanced courses" are courses the student has not yet taken, but that have prerequisites that the student has already taken. Instead of returning all the courses that match this criteria (as the helper function find_next_courses does), we then filter out the courses that are of lesser depth on the course tree to get only the "most advanced" ones. In this way, we are recommending a list of courses that are already within the subfield the student has clearly chosen to specialize in, so they can go further in that area of study and not be recommended courses in other areas they're less interested in.

What did we learn from doing this?

While working on the project, we noticed that the strict rules and regulations of UBC's degree structure was easy to translate to Prolog code. Writing a database of facts regarding the prerequisites of UBC's courses was as simple as listing course names and their relations to other courses, and the tree structure of these courses naturally formed from describing these simple relations. We took inspiration from the examples of family trees that we saw in lecture, and it was fascinating to see how easy it is to mold that structure to represent a variety of regulatory frameworks such as a degree planner. In comparison to Haskell, we noticed that writing data definitions and relations was relatively easier in Prolog, but it was more difficult to think through how our algorithms worked, especially the ones involving lots of recursion and several helpers.

While this may just be a lack of familiarity with Prolog, both of us believe it was harder to pick up how to write functions in Prolog as opposed to in Haskell. Often while writing certain functions, we would get stuck trying to think about how to implement helpers only to realize after some digging that a library function already exists for the exact feature we were looking for. For example, the function list_to_set was one we were not expecting to have as a built-in function, and knowing that it exists in advance would make our work much faster. We also felt that scaling our project to a much larger dataset would be extremely time-consuming using Prolog given how we had to manually add each entry to our database and produce a clear list of propositions for our functions to work with.

Work division

Ramit: something extra plus expanding database

Nia: setup code plus the base functions

Links to code etc.

https://github.com/niatzvetkova/Prolog_Tree/tree/main