Core Curriculum
The department has eight core curriculum courses that are required by most specializations. CPSC 121 is the only course that falls under two streams (Systems and Theory). The core courses are contained under one of three streams, each of which represents a different subdiscipline and has defined learning outcomes. The learning outcomes for each area and course can be found by expanding its title below.
Software Engineering
Learning Outcomes for Software Engineering
 Build modern industrialcalibre systems by selecting and using welldefined software engineering processes that iteratively integrate requirements, design, construction, validation, and other phases of development.
 Elicit, deconstruct, and refine functional requirements and quality attributes such that they are described succinctly, completely, and precisely.
 Devise, justify, and communicate, high and lowlevel designs to support a given set of requirements and in support of future evolutionary needs.
 Implement a program and manage implementation and product release across team members, and versions of the application.
 Iteratively analyse and refine implementations of a design of reasonable complexity incorporating emergent design implications and applying codelevel restructuring.
 Independently acquire knowledge of unfamiliar software artifacts, technologies, languages, frameworks, and architectures.
 Validate systems using blackbox testing, whitebox testing, and testdriven design, to reason about, and improve the quality of a software system.
 Carry out design and implementation activities incorporating ethical and security implications of design and codelevel choices and software process and methodological approaches.
 Carry out work in a team, using software process and software structure to guide the allocation of tasks, and project planning.
CPSC 110  Computation, Programs and Programming
CPSC 110  Computation, Programs and Programming
Fundamental program and computation structures. Introductory programming skills. Computation as a tool for information processing, simulation and modelling, and interacting with the world.
 Understand a systematic design process. This is demonstrated by being able to write programs for a reasonably complex task, where multiple parts of the design method are required.
 Understand that programs are written both to run on computers and for people to read. This is demonstrated by being able to write code that is readable, well organized, documented, and tested.
 Understand the relation between information and data. This is demonstrated by being able to design the data representation for a reasonably complex problem, and to describe the information encoded in the given data.
 Understand that programs have structure beyond that of the language constructs. Understand that this structure comes from data and other design patterns, and is critical to writing and reading complex programs. This is demonstrated by being able to identify correspondences between a data definition and a program that operates on that data, and by being able to identify other design patterns in a program.
 Understand that one can replace repetitive code with an abstraction in a systematic way. Understand that this is at the heart of designing libraries. This is demonstrated by being able to produce examples of code before and after abstraction: before, where one can see the repeated code, and after, where one can see the abstraction and verify that it provides the solution to the original problem, as well as several other similar problems. Students should also be able to design a program that uses existing libraries or existing code to solve a new problem.
 Understand that programs can be described using notations other than code, and that these models can facilitate program design. This is demonstrated by being able to identify correspondences between noncode models of a program and the program itself and by being able to use noncode models in program design.
CPSC 210  Software Construction
CPSC 210  Software Construction
 Specify a new program, given a small problem description, by identifying relevant data abstractions, and specifying the associated behaviour of those abstractions.
 Validate the program’s behaviour against its specification prior to implementation using test driven design, through writing unit tests that achieve basic code coverage.
Implement the program in Java, choosing the internal structure of its abstractions, and carry out implementation choices.  Design software using basic Object oriented design principles (coupling, cohesion, single responsibility, substitution), robustness, and design patterns where applicable.
 Analyse the structure and behaviour of an existing small to medium sized codebase by making static and dynamic models and identifying design idioms, including design patterns, present in the code.
 Evolve a small to medium sized codebase by changing or augmenting behaviour of the code through alteration, subtyping or composition.
 Recover from common structural issues through identifying those issues, and selecting and applying the appropriate refactorings.
 Communicate (orally through code demonstration) implementation choices, and the rationale for those choices.
CPSC 310  Introduction to Software Engineering
CPSC 310  Introduction to Software Engineering
Specification, design, validation, evolution and construction of modern software systems, within the context of socially and professionally relevant domains such as ethics, intellectual property, and information security.
 Evaluate software engineering processes used to build modern industrialcalibre systems by justifying their benefits and tradeoffs.
 Elicit, deconstruct, and refine functional requirements and quality attributes such that they are described succinctly, completely, and precisely.
 Devise and justify high and lowlevel designs to support a given set of requirements and in support of future evolutionary needs.
 Iteratively derive implementations of a design of reasonable complexity incorporating emergent design implications, and applying codelevel restructuring for the sake of facilitating changes.
 Carry out the implementation of a design incorporating ethical and security implications of codelevel choices and software process and methodological approaches.
 Independently acquire and apply modern and unfamiliar technology and language stacks.
 Validate systems using both blackbox and whitebox approaches to reason about, and improve the quality of a software system.
Systems
Learning Outcomes for Systems
 Identify the different layers of abstraction at which we can describe program execution (e.g., hardware, ISA, machine level, high level languages) and compare these different levels with respect to how data and execution are represented.
 Describe how and why system components and functionality can be partitioned between hardware, operating system software, and application software.
 Design and implement a system that takes into account best practices of security, memory management, concurrency, and parallelism in both its software and hardware components.
 Design and build software that interacts directly with the system call APIs, making appropriate computational tradeoffs in runtime efficiency, memory and storage efficiency, and parallelism.
 Evaluate and improve one or more of a system’s latency, throughput, and memory consumption.
CPSC 121  Models of Computation (also under Theory)
CPSC 121  Models of Computation
Physical and mathematical structures of computation. Boolean algebra and combinations logic circuits; proof techniques; functions and sequential circuits; sets and relations; finite state machines; sequential instruction execution.
 Model computational systems (e.g., programs and circuits) and apply valid reasoning to these models, i.e. prove relevant properties or reason through functionality of computational systems using predicate logic, propositional logic and state machines.
 Clearly and precisely communicate computational models to computer scientists.
 Identify alternate methods to solve or simplify a variety of problems by translating between (1) English language, (2) simple formal representations (i.e., propositional and shallowly nested predicate logic statements) and (3) closely related equivalent formal representations, and then use the different representations to solve the problem.
 Write proofs for simple theorems by translating the theorem into firstorder logic, decomposing the statement, and applying an appropriate prooftechnique such as direct proofs, indirect proofs by contrapositive, indirect proofs by contradiction, proofs by weak and strong mathematical induction. Justify why each step of the proof is correct.
 Prove features of simple algorithms (e.g.,selection sort, recursive binary search, or quicksort) correct or bound in their running time. Justify why each step of the proof is correct.
 Create regular expressions and DFAs to solve problems that are important in programming.
CPSC 213  Introduction to Computer Systems
 Using a hardware based model of execution, reason about the limitations, vulnerabilities and idiosyncrasies of the behaviour of a particular program, specifically concerning performance, bugs and security vulnerabilities.
 Using a hardware based model of data, reason about how programs access data using different types of variables, including the implicit and explicit use of memory references.
 Translate a statement from a highlevel programming language into assembly language; from a large block of assembly language, identify groups of instructions that correspond to high level language features and then write an equivalent high level programming language expression.
 Identify and correct memory management bugs, particularly in languages with explicit deallocation, and use best practices to write code that is less likely to incur such issues.
 Compare and contrast how Java and C are translated into a language the CPU understands; identify common features that are implemented in significantly different ways in either language (for instance, memory management, and the duality of subtype polymorphism in Java and function pointers in C). In doing so, explain the tradeoffs associated with each.
 Reason about the execution of concurrent programs, incl. real time interrupts, and use both asynchronous programming and threads to write concurrent and/or parallel programs. Explain the tradeoffs associated with each.
 Solve problems using monitors, condition variables and semaphores.
CPSC 313  Computer Hardware and Operating Systems
CPSC 313  Computer Hardware and Operating Systems

Explain the benefits of, and challenges associated with, instructionlevel parallelism and its implementation.

Describe at least one highlevel architecture for a pipelined CPU. Correctly analyze examples of the timing of instructions passing through this architecture to identify dependencies and hazards.

Explain why different types of memory need to be used in modern computers, and how the constraints on physical size, capacity and speed affect the performance of computer code. Correctly analyze examples of memory access patterns and locality to compute the steps required to retrieve the information and/or to update the memory state, while maintaining optimal performance for future accesses.

Explain the issues that must be considered while designing file systems and some common solutions for these issues. Given a file system specification, correctly analyze examples of typical file system operations to identify how to retrieve necessary information or update the file system state. Explain the role that caching, buffering, and partial failure play in the implementation and use of files systems, including differentiating between the role that mechanism and policy play in the operating system and in applications that access file data.

Explain how a modern operating system can share a computer’s processing and memory resources among multiple untrusted and competing processes. Correctly analyze examples of virtual memory accesses in individual processes to (1) compute the steps required to retrieve the information and/or update the memory state, and to (2) identify when hardware can perform an operation autonomously and when the operating system has to be invoked.

Optimize C code in order to make it run faster by refining its locality and use of processor and memory resources. Optimize at least one version of Assembly code to make it run faster by reducing the number of hazards in typical pipelined CPUs.
Theory
Learning Outcomes for Theory Learning
Translate between formal and English language or code representations of problems, algorithms, and data structures and use these representations effectively to solve problems.
 Implement basic data structures (stacks, queues, lists, trees…) and appropriate algorithms using them (search, sort, copy …)
 Translate between English and firstorder logic and derive new propositions using the transformation rules
 Solve simple logic problems with mathematical reasoning (enumeration, algebra, pigeonhole principle, powers of two, constraint satisfaction, simple probability…)
 Perform set theory operations (Cartesian products, power sets…) with proper notation
Adapt an existing algorithm or ADT to approach a novel problem by identifying useful characteristics of the existing solution(s) from which to build a new one.
 Use advanced algorithm design techniques, like dynamic programming, to create an efficient (or more efficient) algorithm
 Abstract a realworld problem and represent the important aspects of it in order to solve it computationally
 Identify alternative approaches to an algorithm or proof
 Reduce a novel complex problem into an existing alreadysolved problem by applying transformations to the input and output
Communicate and prove the space and time cost tradeoffs between algorithms and design choices, using these considerations to justify the selection of a particular algorithm or approach.
 Derive (or recall from memory) time complexity (best, worst, average, tight…) of provided code/pseudocode/algorithm
 Use the definitions of P, NP and NPcompleteness to classify the complexity class of a problem
 Describe the tradeoffs between usage of different algorithms/data structures using their properties
 Prove properties by cases, counterexample, contradiction or induction.
CPSC 121  Models of Computation (also under Systems)
CPSC 121  Models of Computation
Physical and mathematical structures of computation. Boolean algebra and combinations logic circuits; proof techniques; functions and sequential circuits; sets and relations; finite state machines; sequential instruction execution.
 Model computational systems (e.g., programs and circuits) and apply valid reasoning to these models, i.e. prove relevant properties or reason through functionality of computational systems using predicate logic, propositional logic and state machines.
 Clearly and precisely communicate computational models to computer scientists.
 Identify alternate methods to solve or simplify a variety of problems by translating between (1) English language, (2) simple formal representations (i.e., propositional and shallowly nested predicate logic statements) and (3) closely related equivalent formal representations, and then use the different representations to solve the problem.
 Write proofs for simple theorems by translating the theorem into firstorder logic, decomposing the statement, and applying an appropriate prooftechnique such as direct proofs, indirect proofs by contrapositive, indirect proofs by contradiction, proofs by weak and strong mathematical induction. Justify why each step of the proof is correct.
 Prove features of simple algorithms (e.g.,selection sort, recursive binary search, or quicksort) correct or bound in their running time. Justify why each step of the proof is correct.
 Create regular expressions and DFAs to solve problems that are important in programming.
CPSC 221  Basic Algorithms and Data Structures
CPSC 221  Basic Algorithms and Data Structures
 Define and articulate the functionality of classic data structures such as Stacks, Queues, Dictionaries, Priority Queues, etc. by their Abstract Data Type (ADT).
 Design algorithms and structures to implement novel ADTs based on properties of the data and intended use of the data.
 Implement classic and novel data structures in modern C++, including arrays, linked lists, balanced binary search trees, hash tables, etc.
 Analyze the efficiency (time and space) of algorithms and data structures using asymptotic notation (BigO, BigOmega, BigTheta).
 Prove algorithm correctness using iterative and recursive methods.
 Evaluate asymptotic time and space tradeoffs between implementation options.
 Identify the structures and algorithms necessary for solving complex problems.
 Synthesize and apply algorithmic and analytical design choices to form complete software solutions of classic problems.
CPSC 320  Intermediate Algorithm Design and Analysis
CPSC 320  Intermediate Algorithm Design and Analysis
Systematic study of basic concepts and techniques in the design and analysis of algorithms, illustrated from various problem areas. Topics include: models of computation; choice of data structures; graphtheoretic, algebraic, and text processing algorithms.
 Identify the algorithm technique (such as divide and conquer, prune and search, greedy strategies, or dynamic programming) used in a given algorithm.
 Select, adapt, and evaluate promising algorithmic techniques and/or data structures for a given problem by analyzing the problem’s properties.
 Design and prove the correctness of a solution to a problem using a specified algorithm technique, given sufficient information about the form of that problem’s solution.
 Select, evaluate and apply promising mathematical techniques (such as asymptotic notations, recurrence relations, and decision trees) to prove reasonably tight upper and lower bounds on the running time of algorithms.
 Decide how and when to reduce a known problem to another problem of interest, either to obtain an efficient solution to the latter, or to prove that such a solution is unlikely to exist in the context of NPhardness.
 Explore and apply promising mathematical techniques for modelling (such as predicate logic, graphs, or asymptotic notations) and analysis (such as asymptotic runtime analysis, recurrence relations, or decision trees) to specify and prove important properties of algorithmic problems and their solutions.