{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "正文开始："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. 第一章 - 基本概念: Var"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "目录：\n",
    "* 1.1 Var 的基本介绍\n",
    "* 1.2 如何生成 Var\n",
    "* 1.3 Var 的常见属性\n",
    "* 1.4 Var 的常见操作\n",
    "* 1.5 Var 的运算\n",
    "* 1.6 与 NumPy 的相互转化"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1.1 Var 的基本介绍"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Var：计图的基本数据类型\n",
    "\n",
    "在计图 (Jittor) - 开源深度学习框架中，Var 类型是最基本的数据类型。计图的所有操作，都将基于 Var 进行。所以，学习并掌握 Var 是使用计图的第一步。请不要感到畏难，我们之所以引入 Var 类型，是为了优化深度学习的计算能力与效率，目的是方便您更加高效地进行开发，请您尽情享受。  \n",
    "\n",
    "简单来说，Var 是一种特殊的数据结构，它与数组和矩阵非常相似。您可简单理解为，一维 Var 即是数组，二维 Var 即是矩阵。在计图中，我们使用 Var 来编码模型的输入和输出，以及模型的参数。\n",
    "\n",
    "**计图的 Var 与 NumPy 的 ndarray 极其相似**，但 Var 可以在 GPU 或其他专用硬件上运行，以加速计算。如果您熟悉 ndarray，您就会十分熟悉 Var 的相关操作。如果没有，请按照本教程，对 Var 类型进行快速演练。本教程已覆盖 Var 的基础操作，可以基本满足您的开发需求。如您想要更加深入了解并灵活使用 Var,敬请查阅我们的 [API 文档](https://cg.cs.tsinghua.edu.cn/jittor/assets/docs/index.html)。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1.2 如何生成 Var"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "首先，我们在 Python 中导入计图："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[38;5;2m[i 0202 22:49:45.609290 80 compiler.py:847] Jittor(1.2.2.23) src: /home/llt/.local/lib/python3.7/site-packages/jittor\u001b[m\n",
      "\u001b[38;5;2m[i 0202 22:49:45.611377 80 compiler.py:848] g++ at /usr/bin/g++\u001b[m\n",
      "\u001b[38;5;2m[i 0202 22:49:45.612691 80 compiler.py:849] cache_path: /home/llt/.cache/jittor/default/g++\u001b[m\n",
      "\u001b[38;5;2m[i 0202 22:49:45.626682 80 __init__.py:257] Found /usr/local/cuda/bin/nvcc(10.2.89) at /usr/local/cuda/bin/nvcc.\u001b[m\n",
      "\u001b[38;5;2m[i 0202 22:49:45.697894 80 __init__.py:257] Found gdb(8.1.0) at /usr/bin/gdb.\u001b[m\n",
      "\u001b[38;5;2m[i 0202 22:49:45.715477 80 __init__.py:257] Found addr2line(2.30) at /usr/bin/addr2line.\u001b[m\n",
      "\u001b[38;5;2m[i 0202 22:49:45.768340 80 compiler.py:889] pybind_include: -I/usr/include/python3.7m -I/usr/local/lib/python3.7/dist-packages/pybind11/include\u001b[m\n",
      "\u001b[38;5;2m[i 0202 22:49:45.792263 80 compiler.py:891] extension_suffix: .cpython-37m-x86_64-linux-gnu.so\u001b[m\n",
      "\u001b[38;5;2m[i 0202 22:49:45.974687 80 __init__.py:169] Total mem: 62.78GB, using 16 procs for compiling.\u001b[m\n",
      "\u001b[38;5;2m[i 0202 22:49:46.131834 80 jit_compiler.cc:21] Load cc_path: /usr/bin/g++\u001b[m\n",
      "\u001b[38;5;2m[i 0202 22:49:46.304843 80 init.cc:54] Found cuda archs: [75,]\u001b[m\n",
      "\u001b[38;5;2m[i 0202 22:49:46.491697 80 __init__.py:257] Found mpicc(2.1.1) at /usr/bin/mpicc.\u001b[m\n",
      "\u001b[38;5;2m[i 0202 22:49:46.549639 80 compiler.py:654] handle pyjt_include/home/llt/.local/lib/python3.7/site-packages/jittor/extern/mpi/inc/mpi_warper.h\u001b[m\n",
      "\u001b[38;5;2m[i 0202 22:49:46.596179 80 compile_extern.py:287] Downloading nccl...\u001b[m\n",
      "\u001b[38;5;2m[i 0202 22:49:46.683976 80 compile_extern.py:16] found /usr/local/cuda/include/cublas.h\u001b[m\n",
      "\u001b[38;5;2m[i 0202 22:49:46.686093 80 compile_extern.py:16] found /usr/lib/x86_64-linux-gnu/libcublas.so\u001b[m\n",
      "\u001b[38;5;2m[i 0202 22:49:47.293398 80 compile_extern.py:16] found /usr/local/cuda/include/cudnn.h\u001b[m\n",
      "\u001b[38;5;2m[i 0202 22:49:47.294725 80 compile_extern.py:16] found /usr/local/cuda/lib64/libcudnn.so\u001b[m\n",
      "\u001b[38;5;2m[i 0202 22:49:47.332204 80 compiler.py:654] handle pyjt_include/home/llt/.local/lib/python3.7/site-packages/jittor/extern/cuda/cudnn/inc/cudnn_warper.h\u001b[m\n",
      "\u001b[38;5;2m[i 0202 22:49:49.192471 80 compile_extern.py:16] found /usr/local/cuda/include/curand.h\u001b[m\n",
      "\u001b[38;5;2m[i 0202 22:49:49.193815 80 compile_extern.py:16] found /usr/local/cuda/lib64/libcurand.so\u001b[m\n"
     ]
    }
   ],
   "source": [
    "import jittor as jt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**从 “普通数据” 导入生成 Var**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "data: \n",
      " [[1, 2], [3, 4], [5, 6]]\n",
      "var_data: \n",
      " jt.Var([[1 2]\n",
      " [3 4]\n",
      " [5 6]], dtype=int32)\n",
      "var_data的类型是: <class 'jittor.jittor_core.Var'>\n"
     ]
    }
   ],
   "source": [
    "data = [[1, 2],[3, 4],[5, 6]]                   # 生成一个普通的列表\n",
    "print(\"data: \\n\", data)\n",
    "\n",
    "var_data = jt.array(data)                         # 通过列表生成 Var\n",
    "print(\"var_data: \\n\", var_data)\n",
    "\n",
    "print(\"var_data的类型是:\", type(var_data))                          # 打印类型，可以发现生成的是jittor.Var\n",
    "var_data = jt.Var(data)                        # 当然，jittor.Var也可以直接使用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**从 “NumPy 数组” 导入生成 Var**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "np_array: \n",
      " [[1 2]\n",
      " [3 4]\n",
      " [5 6]]\n",
      "var_np_array: \n",
      " jt.Var([[1 2]\n",
      " [3 4]\n",
      " [5 6]], dtype=int64)\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "np_array = np.array([[1, 2],[3, 4],[5, 6]])      # 生成一个 NumPy 的数组\n",
    "print(\"np_array: \\n\", np_array)\n",
    "\n",
    "var_np_array=jt.array(np_array)                    # 通过 NumPy 的数组生成 Var\n",
    "print(\"var_np_array: \\n\", var_np_array)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**从 “其他 Var 数据” 导入生成新的 Var**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Zeros Var: \n",
      " jt.Var([[0 0]\n",
      " [0 0]\n",
      " [0 0]], dtype=int32)\n",
      "Ones Var: \n",
      " jt.Var([[1 1]\n",
      " [1 1]\n",
      " [1 1]], dtype=int32)\n",
      "full Var: \n",
      " jt.Var([[5 5]\n",
      " [5 5]\n",
      " [5 5]], dtype=int32)\n",
      "Random Var: \n",
      " jt.Var([[0.27817145 0.22768587]\n",
      " [0.71629596 0.78609395]\n",
      " [0.8813336  0.5737404 ]], dtype=float32)\n"
     ]
    }
   ],
   "source": [
    "# 准备一个原始的 Var\n",
    "var_data = jt.Var([[1, 2],[3, 4],[5, 6]])\n",
    "\n",
    "# 生成一个形状相同，元素全为 0 的 Var\n",
    "var_zeros = jt.zeros_like(var_data) \n",
    "print(\"Zeros Var: \\n\", var_zeros)\n",
    "\n",
    "# 生成一个形状相同，元素全为 1 的 Var\n",
    "var_ones = jt.ones_like(var_data) \n",
    "print(\"Ones Var: \\n\", var_ones)\n",
    "\n",
    "# 生成一个形状相同，并指定元素值的 Var\n",
    "var_full = jt.full_like(var_data, 5)\n",
    "print(\"full Var: \\n\", var_full)\n",
    "\n",
    "# 生成一个形状相同，元素为随机数的 Var\n",
    "var_rand = jt.rand(var_data.shape, dtype=jt.float)    # 重写元素数据类型\n",
    "print(\"Random Var: \\n\", var_rand)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**生成一些特定的 Var**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Random Var: \n",
      " jt.Var([[0.8556649  0.16008338 0.5214482  0.98024756]\n",
      " [0.02092005 0.6033252  0.08662996 0.9897186 ]\n",
      " [0.20087309 0.07411052 0.57556623 0.54145   ]], dtype=float32)\n",
      "Ones Var: \n",
      " jt.Var([[1. 1. 1. 1.]\n",
      " [1. 1. 1. 1.]\n",
      " [1. 1. 1. 1.]], dtype=float32)\n",
      "Zeros Var: \n",
      " jt.Var([[0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]], dtype=float32)\n",
      "Arange Var 1: \n",
      " jt.Var([0 1 2 3 4 5 6 7 8], dtype=int32)\n",
      "Arange Var 2: \n",
      " jt.Var([0 2 4 6 8], dtype=int32)\n"
     ]
    }
   ],
   "source": [
    "shape = (3,4,)                                 # 指定将要生成 Var 的形状\n",
    "rand_var = jt.rand(shape)                      # 生成元素为随机数的 Var\n",
    "ones_var = jt.ones(shape)                      # 生成元素全为 1 的 Var\n",
    "zeros_var = jt.zeros(shape)                    # 生成元素全为 0 的 Var\n",
    "\n",
    "print(\"Random Var: \\n\", rand_var)\n",
    "print(\"Ones Var: \\n\", ones_var)\n",
    "print(\"Zeros Var: \\n\", zeros_var)\n",
    "\n",
    "arange_var1 = jt.arange(9)                     # 生成元素为等差数组的一维 Var (只指定一个结束参数)\n",
    "arange_var2 = jt.arange(0, 9, 2)               # 生成元素为等差数组的一维 Var (指定起始、结束、步长)\n",
    "print(\"Arange Var 1: \\n\", arange_var1)\n",
    "print(\"Arange Var 2: \\n\", arange_var2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1.3 Var 的常见属性"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Var 的形状：** 通过 var.shape 查看"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Var: \n",
      " jt.Var([[ 1  2  3  4]\n",
      " [ 5  6  7  8]\n",
      " [ 9 10 11 12]], dtype=int32)\n",
      "Shape of Var: \n",
      " [3,4,]\n"
     ]
    }
   ],
   "source": [
    "var = jt.array([[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12]])\n",
    "print(\"Var: \\n\", var)\n",
    "print(\"Shape of Var: \\n\", var.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Var 的数据类型：** 通过 var.dtype 查看"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Var: \n",
      " jt.Var([[1. 1. 1. 1.]\n",
      " [1. 1. 1. 1.]\n",
      " [1. 1. 1. 1.]], dtype=float32)\n",
      "Datatype of Var: \n",
      " float32\n"
     ]
    }
   ],
   "source": [
    "var = jt.ones((3,4))\n",
    "print(\"Var: \\n\", var)\n",
    "print(\"Datatype of Var: \\n\", var.dtype)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1.4 Var 的常见操作"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**重塑形状 Reshape**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Var1: \n",
      " jt.Var([ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23\n",
      " 24 25 26], dtype=int32)\n",
      "Shape of Var1: \n",
      " [27,]\n",
      "Var2: \n",
      " jt.Var([[[ 0  1  2]\n",
      "  [ 3  4  5]\n",
      "  [ 6  7  8]]\n",
      "\n",
      " [[ 9 10 11]\n",
      "  [12 13 14]\n",
      "  [15 16 17]]\n",
      "\n",
      " [[18 19 20]\n",
      "  [21 22 23]\n",
      "  [24 25 26]]], dtype=int32)\n",
      "Shape of Var2: \n",
      " [3,3,3,]\n",
      "Var3: \n",
      " jt.Var([[ 0  1  2  3  4  5  6  7  8]\n",
      " [ 9 10 11 12 13 14 15 16 17]\n",
      " [18 19 20 21 22 23 24 25 26]], dtype=int32)\n",
      "Shape of Var3: \n",
      " [3,9,]\n"
     ]
    }
   ],
   "source": [
    "var1 = jt.arange(27)                         # 创建一个元素为 0-26 的一维 Var1\n",
    "print(\"Var1: \\n\", var1)\n",
    "print(\"Shape of Var1: \\n\", var1.shape)\n",
    "\n",
    "var2 = var1.reshape(3,3,3)                   # 将 Var1 重塑形状为 3*3*3 的 Var2\n",
    "print(\"Var2: \\n\", var2)\n",
    "print(\"Shape of Var2: \\n\", var2.shape)\n",
    "\n",
    "var3 = var2.reshape(3,-1)                    # 参数值为 -1，代表将根据其他形状参数自动计算出合适的值，再进行重塑形状\n",
    "print(\"Var3: \\n\", var3)\n",
    "print(\"Shape of Var3: \\n\", var3.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**转置 Transpose**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 矩阵转置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Var1: \n",
      " jt.Var([[ 0  1  2]\n",
      " [ 3  4  5]\n",
      " [ 6  7  8]\n",
      " [ 9 10 11]], dtype=int32)\n",
      "Shape of Var1: \n",
      " [4,3,]\n",
      "Var1 Transpose: \n",
      " jt.Var([[ 0  3  6  9]\n",
      " [ 1  4  7 10]\n",
      " [ 2  5  8 11]], dtype=int32)\n",
      "Shape of Var1 Transpose: \n",
      " [3,4,]\n"
     ]
    }
   ],
   "source": [
    "# （提示：这里我们用 arange 初始化一个 0 到 11 的一维 Var，然后通过 reshape 将其转化为 4*3 的 Var1。）\n",
    "var1 = jt.arange(12).reshape(4,3)                           # 创建一个 4*3 的二维矩阵 Var1\n",
    "print(\"Var1: \\n\", var1)\n",
    "print(\"Shape of Var1: \\n\", var1.shape)\n",
    "\n",
    "var1_t = var1.transpose()                                   # 矩阵转置成 3*4 的二维矩阵 Var1 Transpose\n",
    "print(\"Var1 Transpose: \\n\", var1_t)\n",
    "print(\"Shape of Var1 Transpose: \\n\", var1_t.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 指定轴转置（较难）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Var1: \n",
      " jt.Var([[[ 0  1  2  3]\n",
      "  [ 4  5  6  7]\n",
      "  [ 8  9 10 11]]\n",
      "\n",
      " [[12 13 14 15]\n",
      "  [16 17 18 19]\n",
      "  [20 21 22 23]]], dtype=int32)\n",
      "Shape of Var1: \n",
      " [2,3,4,]\n",
      "Var1 Transpose: \n",
      " jt.Var([[[ 0  4  8]\n",
      "  [ 1  5  9]\n",
      "  [ 2  6 10]\n",
      "  [ 3  7 11]]\n",
      "\n",
      " [[12 16 20]\n",
      "  [13 17 21]\n",
      "  [14 18 22]\n",
      "  [15 19 23]]], dtype=int32)\n",
      "Shape of Var1 Transpose: \n",
      " [2,4,3,]\n"
     ]
    }
   ],
   "source": [
    "var1 = jt.arange(24).reshape(2,3,4)                        # 创建一个 2*3*4 的三维 Var1\n",
    "print(\"Var1: \\n\", var1)                                    # 其含义为，第一个轴上 2 个元素；第二个轴上 3 个元素；第三个轴上 4 个元素。\n",
    "print(\"Shape of Var1: \\n\", var1.shape)\n",
    "\n",
    "var1_t = var1.transpose(0,2,1)                             # 根据轴索引转置。三维轴索引为 0，1，2，调整索引顺序即代表对应轴调整顺序。\n",
    "print(\"Var1 Transpose: \\n\", var1_t)                        # 从默认的“0，1，2”调整为“0，2，1”，即代表后两轴进行互换。\n",
    "print(\"Shape of Var1 Transpose: \\n\", var1_t.shape)         # 互换后，第一个轴上 2 个元素；第二个轴上 4 个元素；第三个轴上 3 个元素。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**切片和索引**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 Var: \n",
      " jt.Var([[0 1 2]\n",
      " [3 4 5]\n",
      " [6 7 8]], dtype=int32)\n",
      "2 Var: \n",
      " jt.Var([[0 0 2]\n",
      " [3 0 5]\n",
      " [6 0 8]], dtype=int32)\n",
      "3 Line 2 in Var: \n",
      " jt.Var([3 0 5], dtype=int32)\n"
     ]
    }
   ],
   "source": [
    "var = jt.arange(9).reshape(3,3)                     # 初始化一个 3*3 的 Var\n",
    "print(1, \"Var: \\n\", var)\n",
    "\n",
    "var[:,1] = 0                                        # 利用切片，将任意行的第二个元素（即第二列）重置为 0\n",
    "print(2, \"Var: \\n\", var)\n",
    "\n",
    "line_2 = var[1]                                     # 利用索引，拿到第二行元素\n",
    "print(3, \"Line 2 in Var: \\n\", line_2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**原地操作**  \n",
    "在计图中，我们使用 assign() 函数实现在原变量上直接操作。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 Var0: \n",
      " jt.Var([[0 1 2]\n",
      " [3 4 5]], dtype=int32)\n",
      "1 Var1: \n",
      " jt.Var([[1 2 3]\n",
      " [4 5 6]], dtype=int32)\n",
      "1 Var0: \n",
      " jt.Var([[0 1 2]\n",
      " [3 4 5]], dtype=int32)\n",
      "2 Var2: \n",
      " jt.Var([[1 2 3]\n",
      " [4 5 6]], dtype=int32)\n",
      "2 Var0: \n",
      " jt.Var([[1 2 3]\n",
      " [4 5 6]], dtype=int32)\n",
      "3 Var3: \n",
      " jt.Var([[1 4]\n",
      " [2 5]\n",
      " [3 6]], dtype=int32)\n",
      "3 Var0: \n",
      " jt.Var([[1 2 3]\n",
      " [4 5 6]], dtype=int32)\n",
      "4 Var4: \n",
      " jt.Var([[1 4]\n",
      " [2 5]\n",
      " [3 6]], dtype=int32)\n",
      "4 Var0: \n",
      " jt.Var([[1 4]\n",
      " [2 5]\n",
      " [3 6]], dtype=int32)\n"
     ]
    }
   ],
   "source": [
    "var0 = jt.arange(6).reshape(2,3)              # 初始化一个 2*3 的 Var0\n",
    "print(0, \"Var0: \\n\", var0)                    # 打印查看 Var0\n",
    "\n",
    "var1 = var0.add(1)                            # 使 Var1 等于 Var0 上每个元素加 1\n",
    "print(1, \"Var1: \\n\", var1)                    # 打印发现 Var1 赋值成功\n",
    "print(1, \"Var0: \\n\", var0)                    # 但 Var0 并没有发生变化\n",
    "\n",
    "var2 = var0.assign(var0.add(1))               # 利用 assign() 函数，使 Var2 等于 Var0 上每个元素加 1\n",
    "print(2, \"Var2: \\n\", var2)                    # 打印发现 Var2 赋值成功\n",
    "print(2, \"Var0: \\n\", var0)                    # 同时 Var0 也发生了改变\n",
    "\n",
    "var3 = var0.transpose()                       # 使 Var3 等于 Var0 的转置\n",
    "print(3, \"Var3: \\n\", var3)                    # 打印发现 Var3 赋值成功\n",
    "print(3, \"Var0: \\n\", var0)                    # 但 Var0 并没有发生变化\n",
    "\n",
    "var4 = var0.assign(var0.transpose())          # 利用 assign() 函数，使 Var4 等于 Var0 的转置\n",
    "print(4, \"Var4: \\n\", var4)                    # 打印发现 Var4 赋值成功\n",
    "print(4, \"Var0: \\n\", var0)                    # 同时 Var0 也发生了改变"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1.5 Var 的运算"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**开启 GPU 加速**  \n",
    "在计图中，开启 GPU 加速的方式非常简单。我们使用 jt.flags.use_cuda 表示是否使用 GPU 训练。\n",
    "\n",
    "  \n",
    "* 如果 jt.flags.use_cuda = 0，表示使用 CPU 训练；\n",
    "* 如果 jt.flags.use_cuda = 1，表示使用 GPU 训练。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[38;5;2m[i 0130 19:00:46.379159 88 cuda_flags.cc:26] CUDA enabled.\u001b[m\n"
     ]
    }
   ],
   "source": [
    "jt.flags.use_cuda = 1         # 使用 GPU 训练 "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Var 的加法和连接**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "var1: \n",
      " jt.Var([[0 1 2]\n",
      " [3 4 5]\n",
      " [6 7 8]], dtype=int32)\n",
      "var2: \n",
      " jt.Var([[1. 1. 1.]\n",
      " [1. 1. 1.]\n",
      " [1. 1. 1.]], dtype=float32)\n"
     ]
    }
   ],
   "source": [
    "# 初始化两个Var\n",
    "var1 = jt.arange(9).reshape(3,3)\n",
    "var2 = jt.ones((3,3))\n",
    "print(\"var1: \\n\", var1)\n",
    "print(\"var2: \\n\", var2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "var3: \n",
      " jt.Var([[ 3  4  5]\n",
      " [ 6  7  8]\n",
      " [ 9 10 11]], dtype=int32)\n",
      "var4: \n",
      " jt.Var([[1. 2. 3.]\n",
      " [4. 5. 6.]\n",
      " [7. 8. 9.]], dtype=float32)\n",
      "var5: \n",
      " jt.Var([[0. 1. 2. 1. 1. 1.]\n",
      " [3. 4. 5. 1. 1. 1.]\n",
      " [6. 7. 8. 1. 1. 1.]], dtype=float32)\n"
     ]
    }
   ],
   "source": [
    "# Var 与实数相加\n",
    "var3 = var1 + 3\n",
    "print(\"var3: \\n\", var3)\n",
    "\n",
    "# 两个 Var 相加\n",
    "var4 = var1 + var2\n",
    "print(\"var4: \\n\", var4)\n",
    "\n",
    "# 连接两个 Var \n",
    "var5 = jt.concat([var1, var2], dim=1)\n",
    "print(\"var5: \\n\", var5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Var 的乘法：标量相乘 / 矩阵相乘**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "var1: \n",
      " jt.Var([[0 1 2]\n",
      " [3 4 5]\n",
      " [6 7 8]], dtype=int32)\n",
      "var2: \n",
      " jt.Var([[1. 1. 1.]\n",
      " [1. 1. 1.]\n",
      " [1. 1. 1.]], dtype=float32)\n"
     ]
    }
   ],
   "source": [
    "# 初始化两个Var\n",
    "var1 = jt.arange(9).reshape(3,3)\n",
    "var2 = jt.ones((3,3))\n",
    "print(\"var1: \\n\", var1)\n",
    "print(\"var2: \\n\", var2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* **Var 与实数相乘：**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "var3: \n",
      " jt.Var([[ 0  3  6]\n",
      " [ 9 12 15]\n",
      " [18 21 24]], dtype=int32)\n"
     ]
    }
   ],
   "source": [
    "# Var 与实数相乘\n",
    "var3 = var1 * 3\n",
    "print(\"var3: \\n\", var3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* **两个 Var 标量相乘：**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "var4: \n",
      " jt.Var([[0. 1. 2.]\n",
      " [3. 4. 5.]\n",
      " [6. 7. 8.]], dtype=float32)\n",
      "var5: \n",
      " jt.Var([[0. 1. 2.]\n",
      " [3. 4. 5.]\n",
      " [6. 7. 8.]], dtype=float32)\n",
      "var6: \n",
      " jt.Var([[0. 1. 2.]\n",
      " [3. 4. 5.]\n",
      " [6. 7. 8.]], dtype=float32)\n"
     ]
    }
   ],
   "source": [
    "# 标量相乘 方式一\n",
    "var4 = var1 * var2\n",
    "print(\"var4: \\n\", var4)\n",
    "\n",
    "# 标量相乘 方式二\n",
    "var5 = var1.multiply(var2)\n",
    "print(\"var5: \\n\", var5)\n",
    "\n",
    "# 标量相乘 方式三\n",
    "var6 = jt.multiply(var1, var2)\n",
    "print(\"var6: \\n\", var6)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* **两个 Var 矩阵相乘：**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "var7: \n",
      " jt.Var([[ 3.  3.  3.]\n",
      " [12. 12. 12.]\n",
      " [21. 21. 21.]], dtype=float32)\n",
      "var8: \n",
      " jt.Var([[ 3.  3.  3.]\n",
      " [12. 12. 12.]\n",
      " [21. 21. 21.]], dtype=float32)\n",
      "var9: \n",
      " jt.Var([[ 3.  3.  3.]\n",
      " [12. 12. 12.]\n",
      " [21. 21. 21.]], dtype=float32)\n"
     ]
    }
   ],
   "source": [
    "# 矩阵相乘 方式一\n",
    "var7 = var1 @ var2\n",
    "print(\"var7: \\n\", var7)\n",
    "\n",
    "# 矩阵相乘 方式二\n",
    "var8 = var1.matmul(var2)\n",
    "print(\"var8: \\n\", var8)\n",
    "\n",
    "# 矩阵相乘 方式三\n",
    "var9 = jt.matmul(var1, var2)\n",
    "print(\"var9: \\n\", var9)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1.6 与 NumPy 的相互转化"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**从 Var 转化成 NumPy 数组**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "var: \n",
      " jt.Var([[1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1.]], dtype=float32)\n",
      "type(var): <class 'jittor.jittor_core.Var'>\n",
      "ndarray: \n",
      " [[1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1.]]\n",
      "type(ndarray): <class 'numpy.ndarray'>\n"
     ]
    }
   ],
   "source": [
    "# 新建一个 Var\n",
    "var = jt.ones((4,5))\n",
    "print(\"var: \\n\", var)\n",
    "print(\"type(var):\", type(var))\n",
    "\n",
    "# 将其转化为 NumPy 数组\n",
    "ndarray = var.numpy()\n",
    "print(\"ndarray: \\n\", ndarray)\n",
    "print(\"type(ndarray):\", type(ndarray))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**从 NumPy 数组转化成 Var**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ndarray: \n",
      " [[1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1.]]\n",
      "type(ndarray): <class 'numpy.ndarray'>\n",
      "var: \n",
      " jt.Var([[1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1.]], dtype=float64)\n",
      "type(var): <class 'jittor.jittor_core.Var'>\n"
     ]
    }
   ],
   "source": [
    "# 新建一个 NumPy 数组\n",
    "ndarray = np.ones((4,5))\n",
    "print(\"ndarray: \\n\", ndarray)\n",
    "print(\"type(ndarray):\", type(ndarray))\n",
    "\n",
    "# 将其转化为 Var 类型\n",
    "var = jt.array(ndarray)\n",
    "print(\"var: \\n\", var)\n",
    "print(\"type(var):\", type(var))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 📣\n",
    "至此，第一章 - 基本概念: Var - 结束！\n",
    "\n",
    "恭喜您！已成功解锁了 Jittor (计图) 最核心、最基本的数据类型 - Var 类型的基本使用。  \n",
    "\n",
    "在掌握了 Var 类型的基本操作之后，您只需要进一步熟悉神经网络训练的一般模式，便可以利用 Jittor 解决更高阶、更实战的问题。  \n",
    "请不要停下脚步，只差一点点，你就可以轻松地用 Jittor 来进行神经网络的训练啦！"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
