Goals and Outcomes
You will not receive any credit on this project if your code does not pass the “banned features” tests when using the beaker.
Setup
Go to project registration to register for the project. Make sure to sign up for cs1-25sp
projects on the left! Once you do, restart vscode
and a folder with the starter code should automatically show up in your file browser.
Project Grading
As per the syllabus, to pass the class, you must earn a non-zero score on every project. However, you must also earn a total average of at least 75% cumulatively on the projects and quizzes.
How This Project Works
This project will be structured differently from the previous ones. Think of this as a “choose your own adventure” project, where you can choose which subset of functions you want to write that are outlined below. Each function is assigned a certain number of “stars” corresponding to their difficulty and ultimately their point value.
Your Development Cycle for This Project
Step 1: Choose a function to implement.
Look at the list of function choices and choose one to attempt to implement next.
Step 2: Uncomment that function in config.py
.
Each time you write a function, you must uncomment the name of function in the file config.py
. Keep all function names that you have not written as commented out!
Debugging tip
: Isolate the the function you are working on by commenting out everything else in config.py
. Please come to OH if you need more help!
The tests will automatically ONLY use your versions of the functions you have uncommented. It will use our reference solution for any commented/unimplemented functions. This also means that the functions you write can (and often will!) use a helper function that you have not written, and the tests will still work because they will pull those helper functions from our reference solution. This is why all your tests should always pass if the code you wrote is correct!
Step 3: Run score.py
.
Before implementing a function. Run score.py
by using the play button in the top right to see what your score would be with that function implemented correctly. Note that score.py
does not
check correctness; it only indicates your final score assuming you have passed all the tests (NOT just the ones for your implemented functions). We expect you to play around with choices until
you reach your desired score. Since functions are worth different numbers of points, you should decide what to implement based on what you’re interested in. Additionally, there are “bonus” stars
(i.e., points) for every category you’ve implemented at least one function in AND every category you’ve implemented every function in!
Step 4: Write the code!!!
You got this!
The Idea
We’ve seen in previous projects that CS can be useful in many other fields, including subjects in the rest of core!
You might have seen in Ch1a that balancing chemical equations can often be quite tedious. However, we can automate this process using linear algebra (specifically, gaussian elimination methods) to find coefficients of chemical compounds, and can also extend this to find limiting reagents and yields for various chemical equations.
It’s okay if you don’t know what all these words mean! We have provided guidance for each of the functions, and you are always encouraged to go to OH for any questions (short or long!).
What’s New?
To simplify the transition between chemistry and linear algebra, we have created some new useful chemistry and math types that will be used throughout the chemistry components of the project. In
the drop-down definitions of each function, you will see the relevant chemistry and math types required, and some documentation to help understand them better. To see how they are implemented,
take a look at the file chem_types.py
in the support folder.
Just to be clear, while the tool you’re writing can be incredibly helpful in classes like Ch1a and Ma1b, we expect you to follow the Honor Code and use your best judgment if using it in any of these classes!
Remember to uncomment only the names of functions you have written, in the file config.py
, before you run tests for a function you have written. Otherwise the tests will not be running on your code!
Note: if you are running the tests by typing r
in your terminal (instead of using the beaker), you also need to run config.py
(by clicking the triangle run button on the top right corner of VSCode) before running the tests.
The Functions
-
Basic Operations on Compounds (
elements.py
)
These functions focus computing basic chemical properties for use later in other parts. -
get_all_atoms
[★★★☆☆]: Finds a list of atoms for each compound in a side of a chemical equation.Function Specification
get_all_atoms(compounds: Side) -> list[Element]
Returns a sorted list of the unique atoms (elements) that are present in the
compounds
. Each compound is iterable over its constituent atoms, and this function accumulates all unique elements from each compound and returns them in sorted order.
Hint: You should use the
sorted()
function as part of your implementation.Relevant Type Descriptions
-
Element
: A string that must be a valid element from the periodic table. -
CompoundDict
: A dictionary that represents a chemical compound by mappingElement
s toint
s, where the values represent the number of atoms of an element in the compound.
Example: \(\text{CO}_2\) would be represented by{'C': 1, 'O': 2}
. -
Side
: A list ofCompoundDict
s, representing one side of a chemical equation (e.g., reactants on the left side, or products on the right side).
Example: The leftSide
of the reaction \(2\text{CO} + \text{O}_2 \rightarrow 2\text{CO}_2\) would be[{'C': 1, 'O': 1}, {'O':2}]
and the rightSide
would be[{'C': 1, 'O': 2}]
.
-
-
molar_mass
[★★★☆☆]: Calculates the molar mass of a compoundFunction Specification
molar_mass(unp_comp: CompoundString) -> MolarMass
Returns the molar mass of
unp_comp
by (1) parsing it into aCompoundDict
, and (2) compute the sum of each individual element in the compound’s molar mass multiplied by the amount of the element present.
Hint: You will find the function
parse_compound
(fromparser.py
) and the dictionaryPERIODIC_TABLE
(created inchem_types.py
) to be useful when writing this function.Relevant Type Descriptions
-
MolarMass
: Represents the amount of a substance (element or compound) ing/mol
as afloat
. -
Element
: A string that must be a valid element from the periodic table. -
PeriodicTableEntry
: A dictionary that defines the structure of each entry in the periodic table. The dictionary includes the following key-value pairs:-
AtomicNumber
(int): the atomic number (Z) of the element -
Element
(str): the name of the element -
MolarMass
(MolarMass): the molar mass of the element
-
-
PERIODIC_TABLE
This dictionary represents the periodic table, withElement
s as keys andPeriodicTableEntry
s as values. -
CompoundDict
: A dictionary that represents a chemical compound by mappingElement
s toint
s, where the values represent the number of atoms of an element in the compound.
Example: \(\text{CO}_2\) would be represented by{'C': 1, 'O': 2}
.
-
CompoundString
: A string representation of a compound in chemical notation. To convert from aCompoundString
to aCompoundDict
, use theparse_compound
function fromsupport.parser
.
Example: \(\text{Fe}_2\text{O}_3\) would be represented by theCompoundString
’Fe₂O₃'
.
-
-
grams_to_mols
[★★☆☆☆]: Converts a quantity of grams into a quantity of moles.Function Specification
grams_to_mols(comp: CompoundString, g: Gram) -> Mol
Converts the provided number of grams of a compound to moles.
Hint: You will find the function
molar_mass
to be useful when writing this function.Relevant Type Descriptions
-
MolarMass
: Represents the amount of a substance (element or compound) ing/mol
as afloat
. -
CompoundString
: A string representation of a compound in chemical notation. To convert from aCompoundString
to aCompoundDict
, use theparse_compound()
function fromsupport.parser
.
Example: \(\text{Fe}_2\text{O}_3\) would be represented by theCompoundString
’Fe₂O₃'
.
-
Mol
: Represents the amount of a substance (element or compound) inmol
s as afloat
. -
Gram
: Represents the amount of a substance (element or compound) ingram
s as afloat
.
-
-
Balancing Chemical Equations (
solver.py
)
These functions focus on creating a system of linear equations to balance a chemical reaction. -
make_atom_vector
[★★★★☆]: Makes a vector with atom counts as coefficients.Function Specification
make_atom_vector(atoms: list[Element], compound: CompoundDict) -> MutableRationalVector
Makes a vector of atom counts for a compound based on a list of atoms provided. The vector should be the same dimension as the length of the list of atoms provided. The
i
th element of the atom vector should be aFraction
, with the argument being the count of thei
th element ofatoms
that are in the compound.Relevant Type Descriptions
-
Element
: A string that must be a valid element from the periodic table. -
CompoundDict
: A dictionary that represents a chemical compound by mappingElement
s toint
s, where the values represent the number of atoms of an element in the compound.
Example: \(\text{CO}_2\) would be represented by{'C': 1, 'O': 2}
. -
Fraction
: A representation of fractions in python. Usefrac = Fraction(p, q)
to create a fraction calledfrac
defined by \(\displaystyle \frac{p}{q}\). You can also usefrac = Fraction(p)
to create a fraction calledfrac
defined by \(p\). -
MutableRationalVector
: A representation of a vector of rational numbers (i.e.,Fraction
s) in python. You can use aMutableRationalVector
in the following ways:- Use
len(v)
to get the number of fractions in aMutableRationalVector
,v
. - Use
v[i]
to get the \(i\)th element of the vector,v
. - Use
vec = MutableRationalVector(dimensions=n)
to create a vector,vec
, of sizen
, initally filled with all zeroes.
- Use
-
-
make_compound_matrix
[★★★☆☆]: Makes a matrix of atom counts for a list of compounds.Function Specification
make_compound_matrix(side: Side, atoms: list[Element]) -> MutableRationalMatrix2D
Makes a matrix of atom counts for a list of compounds provided by
side
. Each row corresponds to a compound and each column corresponds to an element, with entries being the counts of each element in each compound. Phrased a little differently, for each compound in the list of compounds, there is a vector of atom counts in the matrix.
Hint: Remember that each entry of a
MutableRationalVector
should be aFraction
! \Hint: You can use
matrix += row
to add a row (vector) to the bottom of a matrix.Relevant Type Descriptions
-
Element
: A string that must be a valid element from the periodic table. -
CompoundDict
: A dictionary that represents a chemical compound by mappingElement
s toint
s, where the values represent the number of atoms of an element in the compound.
Example: \(\text{CO}_2\) would be represented by{'C': 1, 'O': 2}
. -
Side
: A list ofCompoundDict
s, representing one side of a chemical equation (e.g., reactants on the left side, or products on the right side). Example: The leftSide
of the reaction \(2\text{CO} + \text{O}_2 \rightarrow 2\text{CO}_2\) would be represented by[{'C': 1, 'O': 1}, {'O':2}]
, and the rightSide
of the reaction would be[{'C': 1, 'O': 2}]
. -
Fraction
: A representation of fractions in python. Usefrac = Fraction(p, q)
to create a fraction calledfrac
defined by \(\displaystyle \frac{p}{q}\). -
MutableRationalVector
: A representation of a vector of rational numbers (i.e.,Fraction
s) in python. You can use aMutableRationalVector
in the following ways:- Use
len(v)
to get the number of fractions in aMutableRationalVector
,v
. - Use
v[i]
to get the \(i\)th element of the vector,v
. - Use
vec = MutableRationalVector(dimensions=n)
to create a vector,vec
, of sizen
, initally filled with all zeroes.
- Use
-
MutableRationalMatrix2D
: A list ofMutableRationalVector
s that represents a 2D matrix. You can use aMutableRationalMatrix2D
in the following ways:- Use
matrix.dimensions
to get a tuple(i, j)
, where \(i\) is the number of rows ofmatrix
and \(j\) is the number of columns ofmatrix
. - Use
matrix[i][j]
to access the element at row \(i\) and column \(j\) of the matrix,matrix
. - Use
matrix = MutableRationalMatrix2D(dimensions=(n, m))
to create an \(n\) by \(m\) matrix calledmatrix
, initally filled with all zeroes. - To make a
RationalMatrix2D
aMutableRationalMatrix2D
, you can domatrix.mutable()
.
- Use
-
-
make_dummy_equation
[★★★☆☆]: Makes a vector with last coefficient fixed.Function Specification
make_dummy_equation(k: int)
Makes a dummy vector of dimension k, with a 1 in the last position so that the last coefficient is fixed. The dimension of this vector should be at least 2, otherwise raises a
ValueError
.
Hint: Remember that each entry of a
MutableRationalVector
should be aFraction
! \Note: Although a
MutableRationalVector
can be indexed like a list, you cannot use the index-1
to access the last element of the vector.Relevant Type Descriptions
-
Fraction
: A representation of fractions in python. Usefrac = Fraction(p, q)
to create a fraction calledfrac
defined by \(\displaystyle \frac{p}{q}\). -
MutableRationalVector
: A representation of a vector of rational numbers (i.e.,Fraction
s) in python. You can use aMutableRationalVector
in the following ways:- Use
len(v)
to get the number of fractions in aMutableRationalVector
,v
. - Use
v[i]
to get the \(i\)th element of the vector,v
. - Use
vec = MutableRationalVector(dimensions=n)
to create a vector,vec
, of sizen
, initally filled with all zeroes.
- Use
-
MutableRationalMatrix2D
: A list ofMutableRationalVector
s that represents a 2D matrix. You can use aMutableRationalMatrix2D
in the following ways:- Use
matrix.dimensions
to get a tuple(i, j)
, where \(i\) is the number of rows ofmatrix
and \(j\) is the number of columns ofmatrix
. - Use
matrix[i][j]
to access the element at row \(i\) and column \(j\) of the matrix,matrix
. - Use
matrix = MutableRationalMatrix2D(dimensions=(n, m))
to create an \(n\) by \(m\) matrix calledmatrix
, initally filled with all zeroes. - To make a
RationalMatrix2D
aMutableRationalMatrix2D
, you can domatrix.mutable()
.
- Use
-
-
make_system_of_equations
[★★★☆☆]: Constructs a matrix representing the system of equations for balancing a chemical equation.Function Specification
make_system_of_equations(react: Side, prod: Side, atoms: list[Element]) -> MutableRationalMatrix2D
Constructs a matrix representing the system of equations for balancing a chemical equation, given the reactant side (
react
) and the product side (prod
).- Make a compound matrix for the reactants and one for the products.
- Since we want the rows to have the elements’ balances, transpose the compound matrices you just made.
- We want the balances of the elements to be consistent (and add up to 0), so you should make all coefficients of the product matrix negative.
- Horizontally concatenate (augment) the modified product matrix to the modified reactant matrix.
- Finally, to prevent trivial solutions, add a dummy row to the bottom of this concatenated matrix, which should fix the last coefficient to be 1.
Hint 1: You can augment two matrices using
matrix1 | matrix2
. Remember to store the result of the matrix augmentation somewhere!
Hint 2: You can add a row to the bottom of a matrix usingmatrix += row
.
Hint 3: You can find the dimensions of a matrix by usingmatrix.dimensions
, which will return a tuple of(number_of_rows, number_of columns)
. \Note: It might be helpful to refer to the file
matrix_operations.py
to see the kinds of matrix operation functions you can call!Relevant Type Descriptions
-
Element
: A string that must be a valid element from the periodic table. -
CompoundDict
: A dictionary that represents a chemical compound by mappingElement
s toint
s, where the values represent the number of atoms of an element in the compound.
Example: \(\text{CO}_2\) would be represented by{'C': 1, 'O': 2}
. -
Side
: A list ofCompoundDict
s, representing one side of a chemical equation (e.g., reactants on the left side, or products on the right side).
Example: The leftSide
of the reaction \(2\text{CO} + \text{0}_2 \rightarrow 2\text{CO}_2\) would be represented by[{'C': 1, 'O': 1}, {'O':2}]
, and the rightSide
of the reaction would be[{'C': 1, 'O': 2}]
. -
Fraction
: A representation of fractions in python. Usefrac = Fraction(p, q)
to create a fraction calledfrac
defined by \(\displaystyle \frac{p}{q}\). -
MutableRationalVector
: A representation of a vector of rational numbers (i.e.,Fraction
s) in python. You can use aMutableRationalVector
in the following ways:- Use
len(v)
to get the number of fractions in aMutableRationalVector
,v
. - Use
v[i]
to get the \(i\)th element of the vector,v
. - Use
vec = MutableRationalVector(dimensions=n)
to create a vector,vec
, of sizen
, initally filled with all zeroes.
- Use
-
MutableRationalMatrix2D
: A list ofMutableRationalVector
s that represents a 2D matrix. You can use aMutableRationalMatrix2D
in the following ways:- Use
matrix.dimensions
to get a tuple(i, j)
, where \(i\) is the number of rows ofmatrix
and \(j\) is the number of columns ofmatrix
. - Use
matrix[i][j]
to access the element at row \(i\) and column \(j\) of the matrix,matrix
. - Use
matrix = MutableRationalMatrix2D((n, m))
to create an \(n\) by \(m\) matrix calledmatrix
, initally filled with all zeroes. - To make a
RationalMatrix2D
aMutableRationalMatrix2D
, you can domatrix.mutable()
.
- Use
-
scale_solution
[★★★★☆]: Scales a rational vector so all entries become integers instead of fractions.Function Specification
scale_solution(solution: MutableRationalVector) -> MutableRationalVector
Scales a rational vector by the smallest value for which all entries become integers instead of fractions (Entries are still of the type
Fraction
, but all denominators must be 1).
Hint 1: You can find the least common multiple (LCM) of 2 numbers by using
lcm(a, b)
.Hint 2: The denominator of a
Fraction
(which are the entries of aRationalVector
) can be found by doingf.denominator
wheref
is aFraction
.Hint 3: The least common multiple of 3 numbers
a, b, c
, is given bylcm(lcm(a,b), c)
.Hint 4: Multiplying a
Fraction
automatically converts them to the simpliest form. For example,Fraction(4,2)
will automatically becomeFraction(2,1)
.Relevant Type Descriptions
-
Fraction
: A representation of fractions in python. Usefrac = Fraction(p, q)
to create a fraction calledfrac
defined by \(\displaystyle \frac{p}{q}\). -
MutableRationalVector
: A representation of a vector of rational numbers (i.e.,Fraction
s) in python. You can use aMutableRationalVector
in the following ways:- Use
len(v)
to get the number of fractions in aMutableRationalVector
,v
. - Use
v[i]
to get the \(i\)th element of the vector,v
. - Use
vec = MutableRationalVector(dimensions=n)
to create a vector,vec
, of sizen
, initally filled with all zeroes.
- Use
-
MutableRationalMatrix2D
: A list ofMutableRationalVector
s that represents a 2D matrix. You can use aMutableRationalMatrix2D
in the following ways:- Use
matrix.dimensions
to get a tuple(i, j)
, where \(i\) is the number of rows ofmatrix
and \(j\) is the number of columns ofmatrix
. - Use
matrix[i][j]
to access the element at row \(i\) and column \(j\) of the matrix,matrix
. - Use
matrix = MutableRationalMatrix2D((n, m))
to create an \(n\) by \(m\) matrix calledmatrix
, initally filled with all zeroes. - To make a
RationalMatrix2D
aMutableRationalMatrix2D
, you can domatrix.mutable()
.
- Use
-
-
make_dictionary_solution
[★★★☆☆]: Maps compounds in a chemical equation to their balanced integer coefficients.Function Specification
make_dictionary_solution(solution: MutableRationalVector, eq: str) -> Solution
Maps compounds in a chemical equation to their balanced integer coefficients.
- First parse the equation string provided, without dictify-ing, to get the reactants and products.
- Initialize an empty solution dictionary.
- The solution dictionary should have
i
th reactant mapped to the relevant integer (inFraction
form) coefficient from the solution vector. - The solution dictionary should have
i
th product mapped to the relevant integer (inFraction
form) coefficient from the solution vector.
Hint 1: You can parse a string equation using
parse_equation()
(fromparser.py
).Hint 2: An empty solution dictionary can be created by making an empty dictionary and then casting it, as
Solution({})
.Hint 3: The
MutableRationalVector
solution
has coefficients for all the reactants first and then the coefficients of the products. So, if you want to find thei
th product’s coefficient, you have to offset the index in ‘solution’ by the number of reactants.Relevant Type Descriptions
-
CompoundString
: A string representation of a compound in chemical notation. To convert from aCompoundString
to aCompoundDict
, use theparse_compound
function fromsupport.parser
.
Example: \(\text{Fe}_2\text{O}_3\) would be represented by theCompoundString
’Fe₂O₃'
. -
SideList
: a list ofCompoundString
s for one side of an equation. -
UnparsedEquation
: A tuple containing theSideList
s for the reactants and products of the equation.
Example: For the reaction \(2\text{CO} + \text{O}_2 \rightarrow 2\text{CO}_2\), theUnparsedEquation
would be(['CO', 'O₂'], ['CO₂'])
. -
Solution
: A dictionary withCompoundString
s as keys andint
values. This type represents a solution to a chemical equation, where each compound is mapped to its coefficient in the balanced equation.
Example: For the reaction \(2\text{CO} + \text{O}_2 \rightarrow 2\text{CO}_2\), theSolution
would be{'CO': 2, 'O₂': 1, 'CO₂': 2}
. -
Fraction
: A representation of fractions in python. Usefrac = Fraction(p, q)
to create a fraction calledfrac
defined by \(\displaystyle \frac{p}{q}\). -
MutableRationalVector
: A representation of a vector of rational numbers (i.e.,Fraction
s) in python. You can use aMutableRationalVector
in the following ways:- Use
len(v)
to get the number of fractions in aMutableRationalVector
,v
. - Use
v[i]
to get the \(i\)th element of the vector,v
. - Use
vec = MutableRationalVector(dimensions=n)
to create a vector,vec
, of sizen
, initally filled with all zeroes.
- Use
-
balance_equation
[★★★☆☆]: Balances a chemical equation and returns the compounds mapped to their balanced integer coefficients.Function Specification
balance_equation(eq: str) -> Solution
Maps compounds in a chemical equation to their balanced integer coefficients.
- First parse the equation string provided, with dictify-ing, to get the reactants and products.
- Get all the atoms in the reactants.
- Make a matrix of the system of equations using the reactants, products and atoms.
- Make a transposed vector with the same number of rows as the system of equations, and set the element in the last row of the vector to be 1 (but as a
Fraction
). - Perform Gaussian elimination on the system of equations using the vector constructed above, to get the solution. Make sure to then scale the solution.
- Finally, make a dictionary of the solution using the equation, and return the dictionary.
Hint 1: You can parse a string equation using
parse_equation()
(fromparser.py
).Hint 2: A transposed n-dimensional vector is just a matrix with n rows and 1 column.
Hint 3: There are some functions from
matrix_operations.py
that might be useful here!Relevant Type Descriptions
-
CompoundString
: A string representation of a compound in chemical notation. To convert from aCompoundString
to aCompoundDict
, use theparse_compound
function fromsupport.parser
.
Example: \(\text{Fe}_2\text{O}_3\) would be represented by theCompoundString
’Fe₂O₃'
. -
Solution
: A dictionary withCompoundString
s as keys andint
values. This type represents a solution to a chemical equation, where each compound is mapped to its coefficient in the balanced equation.
Example: For the reaction \(2\text{CO} + \text{O}_2 \rightarrow 2\text{CO}_2\), theSolution
would be{'CO': 2, 'O₂': 1, 'CO₂': 2}
. -
Fraction
: A representation of fractions in python. Usefrac = Fraction(p, q)
to create a fraction calledfrac
defined by \(\displaystyle \frac{p}{q}\). -
MutableRationalVector
: A representation of a vector of rational numbers (i.e.,Fraction
s) in python. You can use aMutableRationalVector
in the following ways:- Use
len(v)
to get the number of fractions in aMutableRationalVector
,v
. - Use
v[i]
to get the \(i\)th element of the vector,v
. - Use
vec = MutableRationalVector(dimensions=n)
to create a vector,vec
, of sizen
, initally filled with all zeroes.
- Use
-
MutableRationalMatrix2D
: A list ofMutableRationalVector
s that represents a 2D matrix. You can use aMutableRationalMatrix2D
in the following ways:- Use
matrix.dimensions
to get a tuple(i, j)
, where \(i\) is the number of rows ofmatrix
and \(j\) is the number of columns ofmatrix
. - Use
matrix[i][j]
to access the element at row \(i\) and column \(j\) of the matrix,matrix
. - Use
matrix = MutableRationalMatrix2D((n, m))
to create an \(n\) by \(m\) matrix calledmatrix
, initally filled with all zeroes. - To make a
RationalMatrix2D
aMutableRationalMatrix2D
, you can domatrix.mutable()
.
- Use
-
Matrix Operations (
matrix_operations.py
)
These functions will focus on core linear algebra operations that will be useful to our eventual gaussian elimination solver. -
negate_matrix
[★★★☆☆]: Negates every entry in a 2D matrix.Matrix Definitions
Scalar Multiplication
Let \(A\) be a matrix such that \(A = \begin{bmatrix} a_{0,0} & a_{0,1} & ... & a_{0,n} \\ a_{1, 0} & ... \\ . \\ a_{m, 0} & ... & ... & a_{m,n} \\ \end{bmatrix}.\) Then, for all \(\alpha \in \mathbb{Q}, \alpha \times A = \begin{bmatrix} \alpha * a_{0,0} & \alpha * a_{0,1} & ... & \alpha * a_{0,n} \\ \alpha * a_{1, 0} & ... \\ . \\ \alpha * a_{m, 0} & ... & ... & \alpha * a_{m,n} \\ \end{bmatrix}\)
Function Specification
negate_matrix(matrix: MutableRationalMatrix2D) -> MutableRationalMatrix2D
Returns a new matrix (do not edit the input matrix) with the values of \(-1 \times \texttt{matrix}\).
Relevant Type Descriptions
-
Fraction
: A representation of fractions in python. Usefrac = Fraction(p, q)
to create a fraction calledfrac
defined by \(\displaystyle \frac{p}{q}\). -
MutableRationalVector
: A representation of a vector of rational numbers (i.e.,Fraction
s) in python. You can use aMutableRationalVector
in the following ways:- Use
len(v)
to get the number of fractions in aMutableRationalVector
,v
. - Use
v[i]
to get the \(i\)th element of the vector,v
. - Use
vec = MutableRationalVector(dimensions=n)
to create a vector,vec
, of sizen
, initally filled with all zeroes.
- Use
-
MutableRationalMatrix2D
: A list ofMutableRationalVector
s that represents a 2D matrix. You can use aMutableRationalMatrix2D
in the following ways:- Use
matrix.dimensions
to get a tuple(i, j)
, where \(i\) is the number of rows ofmatrix
and \(j\) is the number of columns ofmatrix
. - Use
matrix[i][j]
to access the element at row \(i\) and column \(j\) of the matrix,matrix
. - Use
matrix = MutableRationalMatrix2D(dimensions=(n, m))
to create an \(n\) by \(m\) matrix calledmatrix
, initally filled with all zeroes. - To make a
RationalMatrix2D
aMutableRationalMatrix2D
, you can domatrix.mutable()
.
- Use
-
-
transpose_matrix
[★★★★☆]: Transposes a matrix by swapping the rows and columns of the elements in a 2D matrix.Matrix Definitions
Matrix Transpose
Let \(A\) be an \(m\) by \(n\) matrix such that \(A = \begin{bmatrix} a_{0,0} & a_{0,1} & ... & a_{0,n} \\ a_{1, 0} & ... \\ . \\ a_{m, 0} & ... & ... & a_{m,n} \\ \end{bmatrix}.\) Then, the \(n\) by \(m\) matrix \(A^T = \begin{bmatrix} a_{0,0} & a_{1,0} & ... & a_{m,0} \\ a_{0, 1} & a_{1,1} \\ . \\ a_{0, n} & ... & ... & a_{n,m} \\ \end{bmatrix}.\)
Function Specification
transpose_matrix(matrix: MutableRationalMatrix2D) -> MutableRationalMatrix2D
Returns a new matrix (do not edit the input matrix) that represents the transpose of
matrix
.Relevant Type Descriptions
-
Fraction
: A representation of fractions in python. Usefrac = Fraction(p, q)
to create a fraction calledfrac
defined by \(\displaystyle \frac{p}{q}\). -
MutableRationalVector
: A representation of a vector of rational numbers (i.e.,Fraction
s) in python. You can use aMutableRationalVector
in the following ways:- Use
len(v)
to get the number of fractions in aMutableRationalVector
,v
. - Use
v[i]
to get the \(i\)th element of the vector,v
. - Use
vec = MutableRationalVector(dimensions=n)
to create a vector,vec
, of sizen
, initally filled with all zeroes.
- Use
-
MutableRationalMatrix2D
: A list ofMutableRationalVector
s that represents a 2D matrix. You can use aMutableRationalMatrix2D
in the following ways:- Use
matrix.dimensions
to get a tuple(i, j)
, where \(i\) is the number of rows ofmatrix
and \(j\) is the number of columns ofmatrix
. - Use
matrix[i][j]
to access the element at row \(i\) and column \(j\) of the matrix,matrix
. - Use
matrix = MutableRationalMatrix2D(dimensions=(n, m))
to create an \(n\) by \(m\) matrix calledmatrix
, initally filled with all zeroes. - To make a
RationalMatrix2D
aMutableRationalMatrix2D
, you can domatrix.mutable()
.
- Use
-
-
Gaussian Elimination (
matrix_operations.py
)
These functions will come together to use gaussian elimination to solve systems of linear equations. -
pivot_matrix
[★★★★★]: Swaps the rows of a matrix to make a specific entry on the diagnonal one.Function Specification
pivot_matrix(matrix: MutableRationalMatrix2D, k: int) -> MutableRationalMatrix2D
Returns a new
matrix
(do not edit the input matrix). Search all rows with index >= k, find the row that has the highest absolute value in column k, then swap it with row k.
Hint: You can swap two rows in a
matrix
, by callingmatrix.swap_rows(i, j)
. However, note that this returns a new matrix and doesn’t edit the matrix you call it on.Relevant Type Descriptions
-
Fraction
: A representation of fractions in python. Usefrac = Fraction(p, q)
to create a fraction calledfrac
defined by \(\displaystyle \frac{p}{q}\). -
MutableRationalVector
: A representation of a vector of rational numbers (i.e.,Fraction
s) in python. You can use aMutableRationalVector
in the following ways:- Use
len(v)
to get the number of fractions in aMutableRationalVector
,v
. - Use
v[i]
to get the \(i\)th element of the vector,v
. - Use
vec = MutableRationalVector(dimensions=n)
to create a vector,vec
, of sizen
, initally filled with all zeroes.
- Use
-
MutableRationalMatrix2D
: A list ofMutableRationalVector
s that represents a 2D matrix. You can use aMutableRationalMatrix2D
in the following ways:- Use
matrix.dimensions
to get a tuple(i, j)
, where \(i\) is the number of rows ofmatrix
and \(j\) is the number of columns ofmatrix
. - Use
matrix[i][j]
to access the element at row \(i\) and column \(j\) of the matrix,matrix
. - Use
matrix = MutableRationalMatrix2D(dimensions=(n, m))
to create an \(n\) by \(m\) matrix calledmatrix
, initally filled with all zeroes. - To make a
RationalMatrix2D
aMutableRationalMatrix2D
, you can domatrix.mutable()
.
- Use
-
-
scale_matrix
[★★★★★]: Scales the rows of a matrix to ensure all leading entries below a row are zeroes.Function Specification
scale_matrix(matrix, k)
Returns a new matrix (do not edit the input matrix) obtained by (1) scaling row
k
such thatmatrix[k][k] == 1
and (2) scaling all rows \(j > k\), by subtracting \(\alpha \times \texttt{matrix[k]}\), such thatmatrix[j][k] == 0
.
To do this:
- Divide row \(k\) of the matrix by the cell
matrix[k][k]
- For each row \(j > k\):
- Create a new row \(l\), which will be your new row \(k\) multiplied by
matrix[j][k]
. - Subtract row \(l\) from row \(j\).
- Create a new row \(l\), which will be your new row \(k\) multiplied by
Relevant Type Descriptions
-
Fraction
: A representation of fractions in python. Usefrac = Fraction(p, q)
to create a fraction calledfrac
defined by \(\displaystyle \frac{p}{q}\). -
MutableRationalVector
: A representation of a vector of rational numbers (i.e.,Fraction
s) in python. You can use aMutableRationalVector
in the following ways:- Use
len(v)
to get the number of fractions in aMutableRationalVector
,v
. - Use
v[i]
to get the \(i\)th element of the vector,v
. - Use
vec = MutableRationalVector(dimensions=n)
to create a vector,vec
, of sizen
, initally filled with all zeroes.
- Use
-
MutableRationalMatrix2D
: A list ofMutableRationalVector
s that represents a 2D matrix. You can use aMutableRationalMatrix2D
in the following ways:- Use
matrix.dimensions
to get a tuple(i, j)
, where \(i\) is the number of rows ofmatrix
and \(j\) is the number of columns ofmatrix
. - Use
matrix[i][j]
to access the element at row \(i\) and column \(j\) of the matrix,matrix
. - Use
matrix = MutableRationalMatrix2D(dimensions=(n, m))
to create an \(n\) by \(m\) matrix calledmatrix
, initally filled with all zeroes. - To make a
RationalMatrix2D
aMutableRationalMatrix2D
, you can domatrix.mutable()
.
- Use
- Divide row \(k\) of the matrix by the cell
-
ref
[★★★★★]: Uses helper functions to put a matrix in row echelon form.REF Example
Row Echelon Form
A matrix is considered to be in REF if it’s of the form:
\[\begin{bmatrix} a_0 & a_1 & ... & a_n & | & \alpha \\ 0 & b_0 & ... & b_n & | & \beta \\ . & & & & | & . \\ 0 & & & c_n & | & \gamma \\ \end{bmatrix}\]More specifically, the first non-zero element of each row must be at least 1 column to the right of the row above it.
While this matrix can tell us many things about the original matrix it came from, we will use it to formulate a unique solution for a system of linear equations.
Given a matrix:
\[\begin{bmatrix} 1 & 1 & | & 3 \\ 2 & -3 & | & 4 \\ \end{bmatrix}\]Pivoting the matrix gives:
\[\begin{bmatrix} 2 & -3 & | & 4 \\ 1 & 1 & | & 3 \\ \end{bmatrix}\]Scaling gives:
\[\begin{bmatrix} 1 & \frac{-3}{2} & | & 2 \\ 1 & 1 & | & 3 \\ \end{bmatrix} = \begin{bmatrix} 1 & \frac{-3}{2} & | & 2 \\ 0 & \frac{5}{2} & | & 1 \\ \end{bmatrix}\]Pivoting gives the same matrix. We simply scale the last row giving:
\[\begin{bmatrix} 1 & \frac{-3}{2} & | & 2 \\ 0 & 1 & | & \frac{2}{5} \\ \end{bmatrix}\]Function Specification
ref(matrix: MutableRationalMatrix2D) -> MutableRationalMatrix2D
Returns a new version of
matrix
(do not edit the input matrix) that is in row echelon form.
To do this:
- remove all zero rows from
matrix
and then, until every row has been processed:- Pivot and scale the row.
- Remove any newly created zero rows.
Hint 1: You should use
pivot_matrix
andscale_matrix
in this function. Be careful about the parameters of these functions as you call them! Also, conveniently, we can ask avector
if its zero by usingvector.is_zero_vector()
and ask a matrix to remove a row by usingremove_row
.Relevant Type Descriptions
-
Fraction
: A representation of fractions in python. Usefrac = Fraction(p, q)
to create a fraction calledfrac
defined by \(\displaystyle \frac{p}{q}\). -
MutableRationalVector
: A representation of a vector of rational numbers (i.e.,Fraction
s) in python. You can use aMutableRationalVector
in the following ways:- Use
len(v)
to get the number of fractions in aMutableRationalVector
,v
. - Use
v[i]
to get the \(i\)th element of the vector,v
. - Use
vec = MutableRationalVector(dimensions=n)
to create a vector,vec
, of sizen
, initally filled with all zeroes.
- Use
-
MutableRationalMatrix2D
: A list ofMutableRationalVector
s that represents a 2D matrix. You can use aMutableRationalMatrix2D
in the following ways:- Use
matrix.dimensions
to get a tuple(i, j)
, where \(i\) is the number of rows ofmatrix
and \(j\) is the number of columns ofmatrix
. - Use
matrix[i][j]
to access the element at row \(i\) and column \(j\) of the matrix,matrix
. - Use
matrix = MutableRationalMatrix2D(dimensions=(n, m))
to create an \(n\) by \(m\) matrix calledmatrix
, initally filled with all zeroes. - To make a
RationalMatrix2D
aMutableRationalMatrix2D
, you can domatrix.mutable()
.
- Use
- remove all zero rows from
-
back_substitute
[★★★★★]: Extracts a solution to a system of equations from a matrix in REF.Back Substitution Example
Back Substitution
Given a matrix in ref form:
\[\begin{bmatrix} 1 & \frac{3}{2} & \frac{1}{2} & | & 4 \\ 0 & 1 & \frac{2}{3} & | & 3 \\ 0 & 0 & 1 & | 2 \end{bmatrix}\]This matrix represents the system of solutions:
- \[x + \frac{3}{2}y + \frac{1}{2}z = 4\]
- \[y + \frac{2}{3}z = 3\]
- \[z = 2\]
Back Substitution is the process of taking the variable for which value you know, and substituting it into the other equations to solve for new variables, and repeating the process.
eg.
- \[z = 2\]
-
$$y = 3 - \frac{2}{3}z$$ $$x = 4 - \frac{3}{2}y - \frac{1}{2}z$$ -
$$y = 3 - \frac{2}{3} \cdot 2$$ $$x = 4 - \frac{3}{2}y - \frac{1}{2} \cdot 2$$ -
$$y = \frac{5}{3}$$ $$x = 3 - \frac{3}{2}y$$ - \[x = 3 +- \frac{3}{2} \cdot \frac{5}{3}\]
- \[x = \frac{1}{2}\]
Function Specification
back_substitute(matrix: MutableRationalMatrix2D) -> MutableRationalVector
Performs back substitution to solve the system of equations and returns the solution vector. We are altering the original matrix.
Given a matrix of
n
rows andn+1
columns in REF (see documentation), find a solution vector of sizen
that solves the system of equations represented bymatrix
.- For each row
r
, starting with the bottom row of the matrix and decrementing until you reach the first row:- For each row
s
above rowr
:- Subtract the product of the last element of row
r
and ther
th element of rows
from the last element of rows
- Subtract the product of the last element of row
- For each row
- Return the last column of the matrix as your solution vector
Relevant Type Descriptions
-
Fraction
: A representation of fractions in python. Usefrac = Fraction(p, q)
to create a fraction calledfrac
defined by \(\displaystyle \frac{p}{q}\). -
MutableRationalVector
: A representation of a vector of rational numbers (i.e.,Fraction
s) in python. You can use aMutableRationalVector
in the following ways:- Use
len(v)
to get the number of fractions in aMutableRationalVector
,v
. - Use
v[i]
to get the \(i\)th element of the vector,v
. - Use
vec = MutableRationalVector(dimensions=n)
to create a vector,vec
, of sizen
, initally filled with all zeroes.
- Use
-
MutableRationalMatrix2D
: A list ofMutableRationalVector
s that represents a 2D matrix. You can use aMutableRationalMatrix2D
in the following ways:- Use
matrix.dimensions
to get a tuple(i, j)
, where \(i\) is the number of rows ofmatrix
and \(j\) is the number of columns ofmatrix
. - Use
matrix[i][j]
to access the element at row \(i\) and column \(j\) of the matrix,matrix
. - Use
matrix = MutableRationalMatrix2D(dimensions=(n, m))
to create an \(n\) by \(m\) matrix calledmatrix
, initally filled with all zeroes. - To make a
RationalMatrix2D
aMutableRationalMatrix2D
, you can domatrix.mutable()
.
- Use
-
gaussian_elimination
[★★★☆☆]: Given two matrices, computes and returns a solution to the system of equations they represent.Function Specification
gaussian_elimination(A: MutableRationalMatrix2D, b: MutableRationalMatrix2D) -> MutableRationalVector
Takes
A | b
and uses theref
function to put intoref
form. Then, usesback_substitute
to solve and returns the solution.
Hint: To use
A | b
in your code, you can writeA | b
as we demonstrated in lecture. This returns an immutable matrix.Relevant Type Descriptions
-
Fraction
: A representation of fractions in python. Usefrac = Fraction(p, q)
to create a fraction calledfrac
defined by \(\displaystyle \frac{p}{q}\). -
MutableRationalVector
: A representation of a vector of rational numbers (i.e.,Fraction
s) in python. You can use aMutableRationalVector
in the following ways:- Use
len(v)
to get the number of fractions in aMutableRationalVector
,v
. - Use
v[i]
to get the \(i\)th element of the vector,v
. - Use
vec = MutableRationalVector(dimensions=n)
to create a vector,vec
, of sizen
, initally filled with all zeroes.
- Use
-
MutableRationalMatrix2D
: A list ofMutableRationalVector
s that represents a 2D matrix. You can use aMutableRationalMatrix2D
in the following ways:- Use
matrix.dimensions
to get a tuple(i, j)
, where \(i\) is the number of rows ofmatrix
and \(j\) is the number of columns ofmatrix
. - Use
matrix[i][j]
to access the element at row \(i\) and column \(j\) of the matrix,matrix
. - Use
matrix = MutableRationalMatrix2D(dimensions=(n, m))
to create an \(n\) by \(m\) matrix calledmatrix
, initally filled with all zeroes. - To make a
RationalMatrix2D
aMutableRationalMatrix2D
, you can domatrix.mutable()
.
- Use
-
-
Finding the Limiting Reactant (
limiting.py
)
These functions will use a balanced equation to find the limiting reactant of a reaction. -
ratio
[★★☆☆☆]: Calculates the mole ratio of a given compound.Function Specification
ratio(comp: CompoundString, solution: Solution, G: dict[CompoundString, Gram]) -> float
Calculates the mole ratio of a given compound. This function calculates the number of moles of a compound we have, and divides it by the coefficient of the compound in the balanced solution.
Hint: You should use the
G
dictionary to get the mass and thengrams_to_moles()
(fromelements.py
) for the conversion of mass into moles.Relevant Type Descriptions
-
CompoundString
: A string representation of a compound in chemical notation.
Example: \(\text{Fe}_2\text{O}_3\) would be represented by theCompoundString
’Fe₂O₃'
. -
Gram
: Represents the amount of a substance (element or compound) ingram
s as afloat
. -
Solution
: A dictionary withCompoundString
s as keys andint
values. This type represents a solution to a chemical equation, where each compound is mapped to its coefficient in the balanced equation.
Example: For the reaction \(2\text{CO} + \text{O}_2 \rightarrow 2\text{CO}_2\), theSolution
would be{'CO': 2, 'O₂': 1, 'CO₂': 2}
.
-
-
limiting_reactant
[★★☆☆☆]: Identifies the limiting reactant among a set of compounds in a chemical reaction.Function Specification
limiting_reactant(solution: Solution, G: dict[CompoundString, Gram]) -> CompoundString
This function calculates the mole ratio for each compound and returns the string representation of the component with the lowest value, using the solution dictionary (see
Solution
type definition below) andG
, a dictionary of the compounds mapped to their masses in grams.
Hint: The
ratio()
function might be helpful here!Relevant Type Descriptions
-
CompoundString
: A string representation of a compound in chemical notation.
Example: \(\text{Fe}_2\text{O}_3\) would be represented by theCompoundString
’Fe₂O₃'
. -
Solution
: A dictionary withCompoundString
s as keys andint
values. This type represents a solution to a chemical equation, where each compound is mapped to its coefficient in the balanced equation.
Example: For the reaction \(2\text{CO} + \text{O}_2 \rightarrow 2\text{CO}_2\), theSolution
would be{'CO': 2, 'O₂': 1, 'CO₂': 2}
. -
Gram
: Represents the amount of a substance (element or compound) ingram
s as afloat
.
-
-
Finding the Theoretical Yield for a Reaction (
chemical_yield.py
)
This function will use everything else to finally find the theoretical yield of a reaction. -
theoretical_yield
[★★☆☆☆]: Calculates the theoretical yield of products in a reaction based on the limiting reactant.Function Specification
theoretical_yield(solution: Solution, G: dict[CompoundString, Gram], grams: bool = False) -> ...
This function determines the yield for each compound of the products in grams or moles depending on the values of the boolean
grams
argument. It returns a dictionary mapping each compound to their respective yields.
Hint: The functions
grams_to_mols()
(fromelements.py
) andlimiting_reactant()
might be helpful here!Note: To calculate the theoretical yield of a compound in a chemical reaction, we need to know the limiting reactant, which is what limits the reaction. The theoretical yield of a singular compound, in moles, is given by the mole ratio of the limiting reactant multiplied by the coefficient of the compound in the balanced solution.
\[\text{theoretical yield of compound} = \text{mole ratio of limiting reactant} \cdot \text{coefficient of the compound in balanced solution}\]Relevant Type Descriptions
-
CompoundString
: A string representation of a compound in chemical notation. To convert from aCompoundString
to aCompoundDict
, use theparse_compound
function fromsupport.parser
.
Example: \(\text{Fe}_2\text{O}_3\) would be represented by theCompoundString
’Fe₂O₃'
. -
Gram
: Represents the amount of a substance (element or compound) ingram
s as afloat
. -
Mol
: Represents the amount of a substance (element or compound) inmol
s as afloat
. -
Solution
: A dictionary withCompoundString
s as keys andint
values. This type represents a solution to a chemical equation, where each compound is mapped to its coefficient in the balanced equation.
Example: For the reaction \(2\text{CO} + \text{O}_2 \rightarrow 2\text{CO}_2\), theSolution
would be{'CO': 2, 'O₂': 1, 'CO₂': 2}
.
-
There are no DUES for this project!