Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 54 additions & 6 deletions minitorch/autodiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,61 @@ def central_difference(f: Any, *vals: Any, arg: int = 0, epsilon: float = 1e-6)

class Variable(Protocol):
def accumulate_derivative(self, x: Any) -> None:
"""
Accumulates the derivative (gradient) for this Variable.

Args:
x (Any): The gradient value to be accumulated.
"""
pass

@property
def unique_id(self) -> int:
"""
Returns:
int: The unique identifier of this Variable.
"""
pass

def is_leaf(self) -> bool:
"""
Returns whether this Variable is a leaf node in the computation graph.

Returns:
bool: True if this Variable is a leaf node, False otherwise.
"""
pass

def is_constant(self) -> bool:
"""
Returns whether this Variable represents a constant value.

Returns:
bool: True if this Variable is constant, False otherwise.
"""
pass

@property
def parents(self) -> Iterable["Variable"]:
"""
Returns the parent Variables of this Variable in the computation graph.

Returns:
Iterable[Variable]: The parent Variables of this Variable.
"""
pass

def chain_rule(self, d_output: Any) -> Iterable[Tuple["Variable", Any]]:
"""
Implements the chain rule to compute the gradient contributions of this Variable.

Args:
d_output (Any): The gradient of the output with respect to the Variable.

Returns:
Iterable[Tuple[Variable, Any]]: An iterable of tuples, where each tuple
contains a parent Variable and the corresponding gradient contribution.
"""
pass


Expand All @@ -61,30 +99,40 @@ def topological_sort(variable: Variable) -> Iterable[Variable]:

Returns:
Non-constant Variables in topological order starting from the right.

Hints:
1. Ensure that you visit the computation graph in a post-order depth-first search.
2. When the children nodes of the current node are visited, add the current node
at the front of the result order list.
"""
# BEGIN ASSIGN1_1
# BEGIN ASSIGN2_1
# TODO

raise NotImplementedError("Task Autodiff Not Implemented Yet")
# END ASSIGN1_1
# END ASSIGN2_1


def backpropagate(variable: Variable, deriv: Any) -> None:
"""
Runs backpropagation on the computation graph in order to
compute derivatives for the leave nodes.
compute derivatives for the leaf nodes.

Args:
variable: The right-most variable
deriv : Its derivative that we want to propagate backward to the leaves.

No return. Should write to its results to the derivative values of each leaf through `accumulate_derivative`.
No return. Should write its results to the derivative values of each leaf through `accumulate_derivative`.

Hints:
1. Traverse nodes in topological order
2. If the node is a leaf, the derivative should be accumulated
3. Otherwise, the derivative should be propagated via chain rule
"""
# BEGIN ASSIGN1_1
# BEGIN ASSIGN2_1
# TODO

raise NotImplementedError("Task Autodiff Not Implemented Yet")
# END ASSIGN1_1
# END ASSIGN2_1


@dataclass
Expand Down