diff --git a/.github/.keep b/.github/.keep
new file mode 100644
index 00000000..e69de29b
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
diff --git a/README.md b/README.md
index 62e4d6ba..82154e8f 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
+[](https://classroom.github.com/online_ide?assignment_repo_id=20081084&assignment_repo_type=AssignmentRepo)
# MiniTorch Module 0
diff --git a/minitorch-env/bin/Activate.ps1 b/minitorch-env/bin/Activate.ps1
new file mode 100644
index 00000000..b49d77ba
--- /dev/null
+++ b/minitorch-env/bin/Activate.ps1
@@ -0,0 +1,247 @@
+<#
+.Synopsis
+Activate a Python virtual environment for the current PowerShell session.
+
+.Description
+Pushes the python executable for a virtual environment to the front of the
+$Env:PATH environment variable and sets the prompt to signify that you are
+in a Python virtual environment. Makes use of the command line switches as
+well as the `pyvenv.cfg` file values present in the virtual environment.
+
+.Parameter VenvDir
+Path to the directory that contains the virtual environment to activate. The
+default value for this is the parent of the directory that the Activate.ps1
+script is located within.
+
+.Parameter Prompt
+The prompt prefix to display when this virtual environment is activated. By
+default, this prompt is the name of the virtual environment folder (VenvDir)
+surrounded by parentheses and followed by a single space (ie. '(.venv) ').
+
+.Example
+Activate.ps1
+Activates the Python virtual environment that contains the Activate.ps1 script.
+
+.Example
+Activate.ps1 -Verbose
+Activates the Python virtual environment that contains the Activate.ps1 script,
+and shows extra information about the activation as it executes.
+
+.Example
+Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv
+Activates the Python virtual environment located in the specified location.
+
+.Example
+Activate.ps1 -Prompt "MyPython"
+Activates the Python virtual environment that contains the Activate.ps1 script,
+and prefixes the current prompt with the specified string (surrounded in
+parentheses) while the virtual environment is active.
+
+.Notes
+On Windows, it may be required to enable this Activate.ps1 script by setting the
+execution policy for the user. You can do this by issuing the following PowerShell
+command:
+
+PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
+
+For more information on Execution Policies:
+https://go.microsoft.com/fwlink/?LinkID=135170
+
+#>
+Param(
+ [Parameter(Mandatory = $false)]
+ [String]
+ $VenvDir,
+ [Parameter(Mandatory = $false)]
+ [String]
+ $Prompt
+)
+
+<# Function declarations --------------------------------------------------- #>
+
+<#
+.Synopsis
+Remove all shell session elements added by the Activate script, including the
+addition of the virtual environment's Python executable from the beginning of
+the PATH variable.
+
+.Parameter NonDestructive
+If present, do not remove this function from the global namespace for the
+session.
+
+#>
+function global:deactivate ([switch]$NonDestructive) {
+ # Revert to original values
+
+ # The prior prompt:
+ if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) {
+ Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt
+ Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT
+ }
+
+ # The prior PYTHONHOME:
+ if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) {
+ Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME
+ Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME
+ }
+
+ # The prior PATH:
+ if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) {
+ Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH
+ Remove-Item -Path Env:_OLD_VIRTUAL_PATH
+ }
+
+ # Just remove the VIRTUAL_ENV altogether:
+ if (Test-Path -Path Env:VIRTUAL_ENV) {
+ Remove-Item -Path env:VIRTUAL_ENV
+ }
+
+ # Just remove VIRTUAL_ENV_PROMPT altogether.
+ if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) {
+ Remove-Item -Path env:VIRTUAL_ENV_PROMPT
+ }
+
+ # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether:
+ if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) {
+ Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force
+ }
+
+ # Leave deactivate function in the global namespace if requested:
+ if (-not $NonDestructive) {
+ Remove-Item -Path function:deactivate
+ }
+}
+
+<#
+.Description
+Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the
+given folder, and returns them in a map.
+
+For each line in the pyvenv.cfg file, if that line can be parsed into exactly
+two strings separated by `=` (with any amount of whitespace surrounding the =)
+then it is considered a `key = value` line. The left hand string is the key,
+the right hand is the value.
+
+If the value starts with a `'` or a `"` then the first and last character is
+stripped from the value before being captured.
+
+.Parameter ConfigDir
+Path to the directory that contains the `pyvenv.cfg` file.
+#>
+function Get-PyVenvConfig(
+ [String]
+ $ConfigDir
+) {
+ Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg"
+
+ # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue).
+ $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue
+
+ # An empty map will be returned if no config file is found.
+ $pyvenvConfig = @{ }
+
+ if ($pyvenvConfigPath) {
+
+ Write-Verbose "File exists, parse `key = value` lines"
+ $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath
+
+ $pyvenvConfigContent | ForEach-Object {
+ $keyval = $PSItem -split "\s*=\s*", 2
+ if ($keyval[0] -and $keyval[1]) {
+ $val = $keyval[1]
+
+ # Remove extraneous quotations around a string value.
+ if ("'""".Contains($val.Substring(0, 1))) {
+ $val = $val.Substring(1, $val.Length - 2)
+ }
+
+ $pyvenvConfig[$keyval[0]] = $val
+ Write-Verbose "Adding Key: '$($keyval[0])'='$val'"
+ }
+ }
+ }
+ return $pyvenvConfig
+}
+
+
+<# Begin Activate script --------------------------------------------------- #>
+
+# Determine the containing directory of this script
+$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
+$VenvExecDir = Get-Item -Path $VenvExecPath
+
+Write-Verbose "Activation script is located in path: '$VenvExecPath'"
+Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)"
+Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)"
+
+# Set values required in priority: CmdLine, ConfigFile, Default
+# First, get the location of the virtual environment, it might not be
+# VenvExecDir if specified on the command line.
+if ($VenvDir) {
+ Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values"
+}
+else {
+ Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir."
+ $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/")
+ Write-Verbose "VenvDir=$VenvDir"
+}
+
+# Next, read the `pyvenv.cfg` file to determine any required value such
+# as `prompt`.
+$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir
+
+# Next, set the prompt from the command line, or the config file, or
+# just use the name of the virtual environment folder.
+if ($Prompt) {
+ Write-Verbose "Prompt specified as argument, using '$Prompt'"
+}
+else {
+ Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value"
+ if ($pyvenvCfg -and $pyvenvCfg['prompt']) {
+ Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'"
+ $Prompt = $pyvenvCfg['prompt'];
+ }
+ else {
+ Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)"
+ Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'"
+ $Prompt = Split-Path -Path $venvDir -Leaf
+ }
+}
+
+Write-Verbose "Prompt = '$Prompt'"
+Write-Verbose "VenvDir='$VenvDir'"
+
+# Deactivate any currently active virtual environment, but leave the
+# deactivate function in place.
+deactivate -nondestructive
+
+# Now set the environment variable VIRTUAL_ENV, used by many tools to determine
+# that there is an activated venv.
+$env:VIRTUAL_ENV = $VenvDir
+
+if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
+
+ Write-Verbose "Setting prompt to '$Prompt'"
+
+ # Set the prompt to include the env name
+ # Make sure _OLD_VIRTUAL_PROMPT is global
+ function global:_OLD_VIRTUAL_PROMPT { "" }
+ Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT
+ New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt
+
+ function global:prompt {
+ Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) "
+ _OLD_VIRTUAL_PROMPT
+ }
+ $env:VIRTUAL_ENV_PROMPT = $Prompt
+}
+
+# Clear PYTHONHOME
+if (Test-Path -Path Env:PYTHONHOME) {
+ Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME
+ Remove-Item -Path Env:PYTHONHOME
+}
+
+# Add the venv to the PATH
+Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH
+$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH"
diff --git a/minitorch-env/bin/activate b/minitorch-env/bin/activate
new file mode 100644
index 00000000..b1d6aee8
--- /dev/null
+++ b/minitorch-env/bin/activate
@@ -0,0 +1,70 @@
+# This file must be used with "source bin/activate" *from bash*
+# You cannot run it directly
+
+deactivate () {
+ # reset old environment variables
+ if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
+ PATH="${_OLD_VIRTUAL_PATH:-}"
+ export PATH
+ unset _OLD_VIRTUAL_PATH
+ fi
+ if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
+ PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
+ export PYTHONHOME
+ unset _OLD_VIRTUAL_PYTHONHOME
+ fi
+
+ # Call hash to forget past commands. Without forgetting
+ # past commands the $PATH changes we made may not be respected
+ hash -r 2> /dev/null
+
+ if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
+ PS1="${_OLD_VIRTUAL_PS1:-}"
+ export PS1
+ unset _OLD_VIRTUAL_PS1
+ fi
+
+ unset VIRTUAL_ENV
+ unset VIRTUAL_ENV_PROMPT
+ if [ ! "${1:-}" = "nondestructive" ] ; then
+ # Self destruct!
+ unset -f deactivate
+ fi
+}
+
+# unset irrelevant variables
+deactivate nondestructive
+
+# on Windows, a path can contain colons and backslashes and has to be converted:
+if [ "${OSTYPE:-}" = "cygwin" ] || [ "${OSTYPE:-}" = "msys" ] ; then
+ # transform D:\path\to\venv to /d/path/to/venv on MSYS
+ # and to /cygdrive/d/path/to/venv on Cygwin
+ export VIRTUAL_ENV=$(cygpath /home/zwjiang7/workspace/ai/mytorch/minitorch-module-0-XDjzw/minitorch-env)
+else
+ # use the path as-is
+ export VIRTUAL_ENV=/home/zwjiang7/workspace/ai/mytorch/minitorch-module-0-XDjzw/minitorch-env
+fi
+
+_OLD_VIRTUAL_PATH="$PATH"
+PATH="$VIRTUAL_ENV/"bin":$PATH"
+export PATH
+
+# unset PYTHONHOME if set
+# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
+# could use `if (set -u; : $PYTHONHOME) ;` in bash
+if [ -n "${PYTHONHOME:-}" ] ; then
+ _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
+ unset PYTHONHOME
+fi
+
+if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
+ _OLD_VIRTUAL_PS1="${PS1:-}"
+ PS1='(minitorch-env) '"${PS1:-}"
+ export PS1
+ VIRTUAL_ENV_PROMPT='(minitorch-env) '
+ export VIRTUAL_ENV_PROMPT
+fi
+
+# Call hash to forget past commands. Without forgetting
+# past commands the $PATH changes we made may not be respected
+hash -r 2> /dev/null
diff --git a/minitorch-env/bin/activate.csh b/minitorch-env/bin/activate.csh
new file mode 100644
index 00000000..7051ddbf
--- /dev/null
+++ b/minitorch-env/bin/activate.csh
@@ -0,0 +1,27 @@
+# This file must be used with "source bin/activate.csh" *from csh*.
+# You cannot run it directly.
+
+# Created by Davide Di Blasi .
+# Ported to Python 3.3 venv by Andrew Svetlov
+
+alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate'
+
+# Unset irrelevant variables.
+deactivate nondestructive
+
+setenv VIRTUAL_ENV /home/zwjiang7/workspace/ai/mytorch/minitorch-module-0-XDjzw/minitorch-env
+
+set _OLD_VIRTUAL_PATH="$PATH"
+setenv PATH "$VIRTUAL_ENV/"bin":$PATH"
+
+
+set _OLD_VIRTUAL_PROMPT="$prompt"
+
+if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
+ set prompt = '(minitorch-env) '"$prompt"
+ setenv VIRTUAL_ENV_PROMPT '(minitorch-env) '
+endif
+
+alias pydoc python -m pydoc
+
+rehash
diff --git a/minitorch-env/bin/activate.fish b/minitorch-env/bin/activate.fish
new file mode 100644
index 00000000..a3ed0a96
--- /dev/null
+++ b/minitorch-env/bin/activate.fish
@@ -0,0 +1,69 @@
+# This file must be used with "source /bin/activate.fish" *from fish*
+# (https://fishshell.com/). You cannot run it directly.
+
+function deactivate -d "Exit virtual environment and return to normal shell environment"
+ # reset old environment variables
+ if test -n "$_OLD_VIRTUAL_PATH"
+ set -gx PATH $_OLD_VIRTUAL_PATH
+ set -e _OLD_VIRTUAL_PATH
+ end
+ if test -n "$_OLD_VIRTUAL_PYTHONHOME"
+ set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME
+ set -e _OLD_VIRTUAL_PYTHONHOME
+ end
+
+ if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
+ set -e _OLD_FISH_PROMPT_OVERRIDE
+ # prevents error when using nested fish instances (Issue #93858)
+ if functions -q _old_fish_prompt
+ functions -e fish_prompt
+ functions -c _old_fish_prompt fish_prompt
+ functions -e _old_fish_prompt
+ end
+ end
+
+ set -e VIRTUAL_ENV
+ set -e VIRTUAL_ENV_PROMPT
+ if test "$argv[1]" != "nondestructive"
+ # Self-destruct!
+ functions -e deactivate
+ end
+end
+
+# Unset irrelevant variables.
+deactivate nondestructive
+
+set -gx VIRTUAL_ENV /home/zwjiang7/workspace/ai/mytorch/minitorch-module-0-XDjzw/minitorch-env
+
+set -gx _OLD_VIRTUAL_PATH $PATH
+set -gx PATH "$VIRTUAL_ENV/"bin $PATH
+
+# Unset PYTHONHOME if set.
+if set -q PYTHONHOME
+ set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME
+ set -e PYTHONHOME
+end
+
+if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
+ # fish uses a function instead of an env var to generate the prompt.
+
+ # Save the current fish_prompt function as the function _old_fish_prompt.
+ functions -c fish_prompt _old_fish_prompt
+
+ # With the original prompt function renamed, we can override with our own.
+ function fish_prompt
+ # Save the return status of the last command.
+ set -l old_status $status
+
+ # Output the venv prompt; color taken from the blue of the Python logo.
+ printf "%s%s%s" (set_color 4B8BBE) '(minitorch-env) ' (set_color normal)
+
+ # Restore the return status of the previous command.
+ echo "exit $old_status" | .
+ # Output the original/"old" prompt.
+ _old_fish_prompt
+ end
+
+ set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
+ set -gx VIRTUAL_ENV_PROMPT '(minitorch-env) '
+end
diff --git a/minitorch-env/bin/hypothesis b/minitorch-env/bin/hypothesis
new file mode 100755
index 00000000..a4e40210
--- /dev/null
+++ b/minitorch-env/bin/hypothesis
@@ -0,0 +1,7 @@
+#!/home/zwjiang7/workspace/ai/mytorch/minitorch-module-0-XDjzw/minitorch-env/bin/python3
+import sys
+from hypothesis.extra.cli import main
+if __name__ == '__main__':
+ if sys.argv[0].endswith('.exe'):
+ sys.argv[0] = sys.argv[0][:-4]
+ sys.exit(main())
diff --git a/minitorch-env/bin/pip b/minitorch-env/bin/pip
new file mode 100755
index 00000000..4c43d3c4
--- /dev/null
+++ b/minitorch-env/bin/pip
@@ -0,0 +1,8 @@
+#!/home/zwjiang7/workspace/ai/mytorch/minitorch-module-0-XDjzw/minitorch-env/bin/python3
+# -*- coding: utf-8 -*-
+import re
+import sys
+from pip._internal.cli.main import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/minitorch-env/bin/pip3 b/minitorch-env/bin/pip3
new file mode 100755
index 00000000..4c43d3c4
--- /dev/null
+++ b/minitorch-env/bin/pip3
@@ -0,0 +1,8 @@
+#!/home/zwjiang7/workspace/ai/mytorch/minitorch-module-0-XDjzw/minitorch-env/bin/python3
+# -*- coding: utf-8 -*-
+import re
+import sys
+from pip._internal.cli.main import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/minitorch-env/bin/pip3.12 b/minitorch-env/bin/pip3.12
new file mode 100755
index 00000000..4c43d3c4
--- /dev/null
+++ b/minitorch-env/bin/pip3.12
@@ -0,0 +1,8 @@
+#!/home/zwjiang7/workspace/ai/mytorch/minitorch-module-0-XDjzw/minitorch-env/bin/python3
+# -*- coding: utf-8 -*-
+import re
+import sys
+from pip._internal.cli.main import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/minitorch-env/bin/py.test b/minitorch-env/bin/py.test
new file mode 100755
index 00000000..5ca4692f
--- /dev/null
+++ b/minitorch-env/bin/py.test
@@ -0,0 +1,7 @@
+#!/home/zwjiang7/workspace/ai/mytorch/minitorch-module-0-XDjzw/minitorch-env/bin/python3
+import sys
+from pytest import console_main
+if __name__ == '__main__':
+ if sys.argv[0].endswith('.exe'):
+ sys.argv[0] = sys.argv[0][:-4]
+ sys.exit(console_main())
diff --git a/minitorch-env/bin/pygmentize b/minitorch-env/bin/pygmentize
new file mode 100755
index 00000000..d58533af
--- /dev/null
+++ b/minitorch-env/bin/pygmentize
@@ -0,0 +1,7 @@
+#!/home/zwjiang7/workspace/ai/mytorch/minitorch-module-0-XDjzw/minitorch-env/bin/python3
+import sys
+from pygments.cmdline import main
+if __name__ == '__main__':
+ if sys.argv[0].endswith('.exe'):
+ sys.argv[0] = sys.argv[0][:-4]
+ sys.exit(main())
diff --git a/minitorch-env/bin/pytest b/minitorch-env/bin/pytest
new file mode 100755
index 00000000..5ca4692f
--- /dev/null
+++ b/minitorch-env/bin/pytest
@@ -0,0 +1,7 @@
+#!/home/zwjiang7/workspace/ai/mytorch/minitorch-module-0-XDjzw/minitorch-env/bin/python3
+import sys
+from pytest import console_main
+if __name__ == '__main__':
+ if sys.argv[0].endswith('.exe'):
+ sys.argv[0] = sys.argv[0][:-4]
+ sys.exit(console_main())
diff --git a/minitorch-env/bin/python b/minitorch-env/bin/python
new file mode 120000
index 00000000..b8a0adbb
--- /dev/null
+++ b/minitorch-env/bin/python
@@ -0,0 +1 @@
+python3
\ No newline at end of file
diff --git a/minitorch-env/bin/python3 b/minitorch-env/bin/python3
new file mode 120000
index 00000000..ae65fdaa
--- /dev/null
+++ b/minitorch-env/bin/python3
@@ -0,0 +1 @@
+/usr/bin/python3
\ No newline at end of file
diff --git a/minitorch-env/bin/python3.12 b/minitorch-env/bin/python3.12
new file mode 120000
index 00000000..b8a0adbb
--- /dev/null
+++ b/minitorch-env/bin/python3.12
@@ -0,0 +1 @@
+python3
\ No newline at end of file
diff --git a/minitorch-env/bin/ruff b/minitorch-env/bin/ruff
new file mode 100755
index 00000000..eb5b6c96
Binary files /dev/null and b/minitorch-env/bin/ruff differ
diff --git a/minitorch-env/lib64 b/minitorch-env/lib64
new file mode 120000
index 00000000..7951405f
--- /dev/null
+++ b/minitorch-env/lib64
@@ -0,0 +1 @@
+lib
\ No newline at end of file
diff --git a/minitorch-env/pyvenv.cfg b/minitorch-env/pyvenv.cfg
new file mode 100644
index 00000000..0c939c1c
--- /dev/null
+++ b/minitorch-env/pyvenv.cfg
@@ -0,0 +1,5 @@
+home = /usr/bin
+include-system-site-packages = false
+version = 3.12.3
+executable = /usr/bin/python3.12
+command = /usr/bin/python3 -m venv /home/zwjiang7/workspace/ai/mytorch/minitorch-module-0-XDjzw/minitorch-env
diff --git a/minitorch/module.py b/minitorch/module.py
index 0a66058c..c30155af 100644
--- a/minitorch/module.py
+++ b/minitorch/module.py
@@ -32,12 +32,16 @@ def modules(self) -> Sequence[Module]:
def train(self) -> None:
"""Set the mode of this module and all descendent modules to `train`."""
# TODO: Implement for Task 0.4.
- raise NotImplementedError("Need to implement for Task 0.4")
+ self.training = True
+ for moudle in self._modules.values():
+ moudle.train()
def eval(self) -> None:
"""Set the mode of this module and all descendent modules to `eval`."""
# TODO: Implement for Task 0.4.
- raise NotImplementedError("Need to implement for Task 0.4")
+ self.training = False
+ for moudle in self._modules.values():
+ moudle.eval()
def named_parameters(self) -> Sequence[Tuple[str, Parameter]]:
"""Collect all the parameters of this module and its descendents.
@@ -48,12 +52,25 @@ def named_parameters(self) -> Sequence[Tuple[str, Parameter]]:
"""
# TODO: Implement for Task 0.4.
- raise NotImplementedError("Need to implement for Task 0.4")
+ result = []
+ for name, param in self._parameters.items():
+ result.append((name, param))
+
+ for prefix, moudle in self._modules.items():
+ for name, param in moudle.named_parameters():
+ result.append((f"{prefix}.{name}",param))
+
+ return result
+
+
def parameters(self) -> Sequence[Parameter]:
"""Enumerate over all the parameters of this module and its descendents."""
# TODO: Implement for Task 0.4.
- raise NotImplementedError("Need to implement for Task 0.4")
+ result = list(self._parameters.values())
+ for module in self._modules.values():
+ result.extend(module.parameters())
+ return result
def add_parameter(self, k: str, v: Any) -> Parameter:
"""Manually add a parameter. Useful helper for scalar parameters.
diff --git a/minitorch/operators.py b/minitorch/operators.py
index 37cc7c09..06b6a842 100644
--- a/minitorch/operators.py
+++ b/minitorch/operators.py
@@ -32,9 +32,86 @@
# $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):
+ return 1.0 if x y else y
+
+def is_close(x: float,y: float) -> float:
+ 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,d: float) -> float:
+ return d / x
+
+def inv(x: float) -> float:
+ return 1.0 / x
+
+def inv_back(x: float, d: float) -> float:
+ return -d / (x * x)
+
+def relu_back(x: float, d: float)-> float:
+ return d if x > 0.0 else 0.0
+
+def map(fn: Callable[[float], float], lst: Iterable[float]) -> Iterable[float]:
+ return [fn(x) for x in lst]
+
+def zipWith(fn: Callable[[float], float], lst1: Iterable[float], lst2:Iterable[float]) -> Iterable[float]:
+ return [fn(x1, x2) for x1, x2 in zip(lst1, lst2)]
+
+def reduce(fn: Callable[[float, float], float], lst: Iterable[float]) -> float:
+ lst = list(lst) # 转为 list 以便取第一个
+ if len(lst) == 0:
+ return 0.0
+ if len(lst) == 1:
+ return lst[0]
+ result = lst[0]
+ for i in range(1, len(lst)):
+ result = fn(result, lst[i])
+ return result
+
+def negList(lst: Iterable[float]) -> Iterable[float]:
+ return map(neg, lst)
+
+def addLists(lst1: Iterable[float], lst2: Iterable[float]) -> Iterable[float]:
+ return zipWith(add, lst1, lst2)
+
+
+def sum(lst: Iterable[float]) -> float:
+ return reduce(add, lst)
+
+def prod(lst: Iterable[float]) -> float:
+ return reduce(mul, lst)
# ## Task 0.3
# Small practice library of elementary higher-order functions.
diff --git a/tests/test_operators.py b/tests/test_operators.py
index f6e555af..b780dabb 100644
--- a/tests/test_operators.py
+++ b/tests/test_operators.py
@@ -108,7 +108,17 @@ def test_sigmoid(a: float) -> None:
* It is strictly increasing.
"""
# TODO: Implement for Task 0.2.
- raise NotImplementedError("Need to implement for Task 0.2")
+ s=sigmoid(a)
+
+ assert 0.0 <= s <= 1.0
+
+ assert_close(1.0 - s, sigmoid(-a))
+
+ if a == 0:
+ assert_close(s, 0.5)
+
+ if a < 10:
+ assert sigmoid(a) < sigmoid(a + 1e-3)
@pytest.mark.task0_2
@@ -116,7 +126,8 @@ def test_sigmoid(a: float) -> None:
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) == 1.0 and lt(b, c) == 1.0:
+ assert lt(a, c) == 1.0
@pytest.mark.task0_2
@@ -125,7 +136,9 @@ def test_symmetric() -> None:
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")
+ for i in range(-10, 11):
+ for j in range(-10, 1):
+ assert_close(mul(i,j), mul(i,j))
@pytest.mark.task0_2
@@ -134,14 +147,19 @@ def test_distribute() -> None:
: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")
-
+ for x in range(-5, 6):
+ for y in range(-5, 6):
+ for z in range(-5, 6):
+ left = mul(z, add(x, y))
+ right = add(mul(x, z), mul(y, z))
+ assert_close(left, right)
@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")
+ for x in range(-10, 11):
+ assert_close(neg(neg(x)), float(x))
# ## Task 0.3 - Higher-order functions
@@ -169,7 +187,9 @@ def test_sum_distribute(ls1: List[float], ls2: List[float]) -> None:
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")
+ sum1_plus_sum2 = sum(ls1) + sum(ls2)
+ sum_of_add_lists = sum(addLists(ls1, ls2))
+ assert_close(sum1_plus_sum2, sum_of_add_lists)
@pytest.mark.task0_3