From c0e4bef7aec9a9a13ea52098dbaa11f75604a957 Mon Sep 17 00:00:00 2001
From: "github-classroom[bot]"
<66690702+github-classroom[bot]@users.noreply.github.com>
Date: Tue, 8 Jul 2025 13:31:04 +0000
Subject: [PATCH 1/5] GitHub Classroom Autograding Workflow
---
.github/workflows/classroom.yml | 67 +++++++++++++++++++++++++++++++++
1 file changed, 67 insertions(+)
create mode 100644 .github/workflows/classroom.yml
diff --git a/.github/workflows/classroom.yml b/.github/workflows/classroom.yml
new file mode 100644
index 00000000..694e0c44
--- /dev/null
+++ b/.github/workflows/classroom.yml
@@ -0,0 +1,67 @@
+name: Autograding Tests
+'on':
+- workflow_dispatch
+- repository_dispatch
+permissions:
+ checks: write
+ actions: read
+ contents: read
+jobs:
+ run-autograding-tests:
+ runs-on: ubuntu-latest
+ if: github.actor != 'github-classroom[bot]'
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ - name: Setup
+ id: setup
+ uses: classroom-resources/autograding-command-grader@v1
+ with:
+ test-name: Setup
+ setup-command: sudo -H pip3 install -qr requirements.txt; sudo -H pip3 install
+ flake8==5.0.4
+ command: flake8 --ignore "N801, E203, E266, E501, W503, F812, E741, N803,
+ N802, N806" minitorch/ tests/ project/; mypy minitorch/*
+ timeout: 10
+ - name: Task 0.1
+ id: task-0-1
+ uses: classroom-resources/autograding-command-grader@v1
+ with:
+ test-name: Task 0.1
+ setup-command: sudo -H pip3 install -qr requirements.txt
+ command: pytest -m task0_1
+ timeout: 10
+ - name: Task 0.2
+ id: task-0-2
+ uses: classroom-resources/autograding-command-grader@v1
+ with:
+ test-name: Task 0.2
+ setup-command: sudo -H pip3 install -qr requirements.txt
+ command: pytest -m task0_2
+ timeout: 10
+ - name: Task 0.3
+ id: task-0-3
+ uses: classroom-resources/autograding-command-grader@v1
+ with:
+ test-name: Task 0.3
+ setup-command: sudo -H pip3 install -qr requirements.txt
+ command: pytest -m task0_3
+ timeout: 10
+ - name: Task 0.4
+ id: task-0-4
+ uses: classroom-resources/autograding-command-grader@v1
+ with:
+ test-name: Task 0.4
+ setup-command: sudo -H pip3 install -qr requirements.txt
+ command: pytest -m task0_4
+ timeout: 10
+ - name: Autograding Reporter
+ uses: classroom-resources/autograding-grading-reporter@v1
+ env:
+ SETUP_RESULTS: "${{steps.setup.outputs.result}}"
+ TASK-0-1_RESULTS: "${{steps.task-0-1.outputs.result}}"
+ TASK-0-2_RESULTS: "${{steps.task-0-2.outputs.result}}"
+ TASK-0-3_RESULTS: "${{steps.task-0-3.outputs.result}}"
+ TASK-0-4_RESULTS: "${{steps.task-0-4.outputs.result}}"
+ with:
+ runners: setup,task-0-1,task-0-2,task-0-3,task-0-4
From 0104b83555a312918c9632834ab5b7ebadba5e4f Mon Sep 17 00:00:00 2001
From: "github-classroom[bot]"
<66690702+github-classroom[bot]@users.noreply.github.com>
Date: Tue, 8 Jul 2025 13:31:04 +0000
Subject: [PATCH 2/5] GitHub Classroom Feedback
---
.github/.keep | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 .github/.keep
diff --git a/.github/.keep b/.github/.keep
new file mode 100644
index 00000000..e69de29b
From e1f2c918b34fcd03c055c52c05adb868e234ffdc Mon Sep 17 00:00:00 2001
From: "github-classroom[bot]"
<66690702+github-classroom[bot]@users.noreply.github.com>
Date: Tue, 8 Jul 2025 13:31:05 +0000
Subject: [PATCH 3/5] Setting up GitHub Classroom Feedback
From eae831d381232fe78c3ae82a44854f3adfaba6f1 Mon Sep 17 00:00:00 2001
From: "github-classroom[bot]"
<66690702+github-classroom[bot]@users.noreply.github.com>
Date: Tue, 8 Jul 2025 13:31:08 +0000
Subject: [PATCH 4/5] add online IDE url
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index 62e4d6ba..8a47e6df 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
+[](https://classroom.github.com/online_ide?assignment_repo_id=19910318&assignment_repo_type=AssignmentRepo)
# MiniTorch Module 0
From 77862e5eee808116cf32e34ef89598a29799e8dd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9E=97=E8=B6=85?=
Date: Wed, 9 Jul 2025 01:03:39 +0800
Subject: [PATCH 5/5] task0_1 task0_2 task0_3
---
minitorch/datasets.py | 24 +++++++---
minitorch/operators.py | 100 +++++++++++++++++++++++++++++++++++++++-
tests/test_operators.py | 28 +++++------
3 files changed, 129 insertions(+), 23 deletions(-)
diff --git a/minitorch/datasets.py b/minitorch/datasets.py
index b3bd9faa..699cad04 100644
--- a/minitorch/datasets.py
+++ b/minitorch/datasets.py
@@ -67,19 +67,29 @@ def circle(N):
def spiral(N):
-
def x(t):
return t * math.cos(t) / 20.0
def y(t):
return t * math.sin(t) / 20.0
- X = [(x(10.0 * (float(i) / (N // 2))) + 0.5, y(10.0 * (float(i) / (N //
- 2))) + 0.5) for i in range(5 + 0, 5 + N // 2)]
- X = X + [(y(-10.0 * (float(i) / (N // 2))) + 0.5, x(-10.0 * (float(i) /
- (N // 2))) + 0.5) for i in range(5 + 0, 5 + N // 2)]
+
+ X = [
+ (x(10.0 * (float(i) / (N // 2))) + 0.5, y(10.0 * (float(i) / (N // 2))) + 0.5)
+ for i in range(5 + 0, 5 + N // 2)
+ ]
+ X = X + [
+ (y(-10.0 * (float(i) / (N // 2))) + 0.5, x(-10.0 * (float(i) / (N // 2))) + 0.5)
+ for i in range(5 + 0, 5 + N // 2)
+ ]
y2 = [0] * (N // 2) + [1] * (N // 2)
return Graph(N, X, y2)
-datasets = {'Simple': simple, 'Diag': diag, 'Split': split, 'Xor': xor,
- 'Circle': circle, 'Spiral': spiral}
+datasets = {
+ "Simple": simple,
+ "Diag": diag,
+ "Split": split,
+ "Xor": xor,
+ "Circle": circle,
+ "Spiral": spiral,
+}
diff --git a/minitorch/operators.py b/minitorch/operators.py
index 37cc7c09..161103b4 100644
--- a/minitorch/operators.py
+++ b/minitorch/operators.py
@@ -32,7 +32,71 @@
# $f(x) = |x - y| < 1e-2$
-# TODO: Implement for Task 0.1.
+def mul(x: float, y: float) -> float:
+ return x * y
+
+
+def id(x: float) -> float:
+ return x
+
+
+def add(x: float, y: float) -> float:
+ return x + y
+
+
+def neg(x: float) -> float:
+ return -x
+
+
+def lt(x: float, y: float) -> bool:
+ return x < y
+
+
+def eq(x: float, y: float) -> bool:
+ return x == y
+
+
+def max(x: float, y: float) -> float:
+ return x if x > y else y
+
+
+def is_close(x: float, y: float) -> bool:
+ return abs(x - y) < 1e-2
+
+
+def sigmoid(x: float) -> float:
+ if x >= 0:
+ return 1.0 / (1.0 + math.exp(-x))
+ else:
+ return math.exp(x) / (1.0 + math.exp(x))
+
+
+def relu(x: float) -> float:
+ return x if x > 0 else 0.0
+
+
+def log(x: float) -> float:
+ return math.log(x)
+
+
+def exp(x: float) -> float:
+ return math.exp(x)
+
+
+def log_back(x: float, y: float) -> float:
+ return y / x
+
+
+def inv(x: float) -> float:
+ return 1.0 / x
+
+
+def inv_back(x: float, y: float) -> float:
+ return -y / (x * x)
+
+
+def relu_back(x: float, y: float) -> float:
+ return y if x > 0 else 0.0
# ## Task 0.3
@@ -51,4 +115,36 @@
# - prod: take the product of lists
-# TODO: Implement for Task 0.3.
+def map(fn: Callable[[float], float], ls: Iterable[float]) -> Iterable[float]:
+ return [fn(x) for x in ls]
+
+
+def zipWith(
+ fn: Callable[[float, float], float], ls1: Iterable[float], ls2: Iterable[float]
+) -> Iterable[float]:
+ return [fn(x, y) for x, y in zip(ls1, ls2)]
+
+
+def reduce(
+ fn: Callable[[float, float], float], ls: Iterable[float], start: float
+) -> float:
+ res = start
+ for x in ls:
+ res = fn(res, x)
+ return res
+
+
+def negList(ls: Iterable[float]) -> Iterable[float]:
+ return map(neg, ls)
+
+
+def addLists(ls1: Iterable[float], ls2: Iterable[float]) -> Iterable[float]:
+ return zipWith(add, ls1, ls2)
+
+
+def sum(ls: Iterable[float]) -> float:
+ return reduce(add, ls, 0.0)
+
+
+def prod(ls: Iterable[float]) -> float:
+ return reduce(mul, ls, 1.0)
diff --git a/tests/test_operators.py b/tests/test_operators.py
index f6e555af..dfce0429 100644
--- a/tests/test_operators.py
+++ b/tests/test_operators.py
@@ -107,41 +107,42 @@ def test_sigmoid(a: float) -> None:
* It crosses 0 at 0.5
* It is strictly increasing.
"""
- # TODO: Implement for Task 0.2.
- raise NotImplementedError("Need to implement for Task 0.2")
+ assert 0.0 <= sigmoid(a) <= 1.0
+ assert_close(sigmoid(-a), 1.0 - sigmoid(a))
+ assert_close(sigmoid(0.0), 0.5)
+ assert sigmoid(a) >= sigmoid(a - 1.0)
@pytest.mark.task0_2
@given(small_floats, small_floats, small_floats)
def test_transitive(a: float, b: float, c: float) -> None:
"""Test the transitive property of less-than (a < b and b < c implies a < c)"""
- # TODO: Implement for Task 0.2.
- raise NotImplementedError("Need to implement for Task 0.2")
+ if lt(a, b) and lt(b, c):
+ assert lt(a, c)
@pytest.mark.task0_2
-def test_symmetric() -> None:
+@given(small_floats, small_floats)
+def test_symmetric(a: float, b: float) -> None:
"""Write a test that ensures that :func:`minitorch.operators.mul` is symmetric, i.e.
gives the same value regardless of the order of its input.
"""
- # TODO: Implement for Task 0.2.
- raise NotImplementedError("Need to implement for Task 0.2")
+ assert_close(mul(a, b), mul(b, a))
@pytest.mark.task0_2
-def test_distribute() -> None:
+@given(small_floats, small_floats, small_floats)
+def test_distribute(x: float, y: float, z: float) -> None:
r"""Write a test that ensures that your operators distribute, i.e.
:math:`z \times (x + y) = z \times x + z \times y`
"""
- # TODO: Implement for Task 0.2.
- raise NotImplementedError("Need to implement for Task 0.2")
+ assert_close(mul(z, add(x, y)), add(mul(z, x), mul(z, y)))
@pytest.mark.task0_2
def test_other() -> None:
"""Write a test that ensures some other property holds for your functions."""
- # TODO: Implement for Task 0.2.
- raise NotImplementedError("Need to implement for Task 0.2")
+ assert_close(mul(0.0, 0.0), 0.0)
# ## Task 0.3 - Higher-order functions
@@ -168,8 +169,7 @@ def test_sum_distribute(ls1: List[float], ls2: List[float]) -> None:
"""Write a test that ensures that the sum of `ls1` plus the sum of `ls2`
is the same as the sum of each element of `ls1` plus each element of `ls2`.
"""
- # TODO: Implement for Task 0.3.
- raise NotImplementedError("Need to implement for Task 0.3")
+ assert_close(sum(addLists(ls1, ls2)), sum(ls1) + sum(ls2))
@pytest.mark.task0_3