```python
[i**2 for i in range(1,100,2)] # List Comprehensions
```

    [1,
     9,
     25,
     49,
     81,
     121,
     169,
     225,
     289,
     361,
     441,
     529,
     625,
     729,
     841,
     961,
     1089,
     1225,
     1369,
     1521,
     1681,
     1849,
     2025,
     2209,
     2401,
     2601,
     2809,
     3025,
     3249,
     3481,
     3721,
     3969,
     4225,
     4489,
     4761,
     5041,
     5329,
     5625,
     5929,
     6241,
     6561,
     6889,
     7225,
     7569,
     7921,
     8281,
     8649,
     9025,
     9409,
     9801]

```python
99**2
```

    9801

```python
S = """In the prior chapter we met Python’s two looping statements, while and for. Although
they can handle most repetitive tasks programs need to perform, the need to iterate
over sequences is so common and pervasive that Python provides additional tools to
make it simpler and more efficient."""
{v: k for v, k in enumerate(S.split())} # Dict comprehensions
```

    {0: 'In',
     1: 'the',
     2: 'prior',
     3: 'chapter',
     4: 'we',
     5: 'met',
     6: 'Python’s',
     7: 'two',
     8: 'looping',
     9: 'statements,',
     10: 'while',
     11: 'and',
     12: 'for.',
     13: 'Although',
     14: 'they',
     15: 'can',
     16: 'handle',
     17: 'most',
     18: 'repetitive',
     19: 'tasks',
     20: 'programs',
     21: 'need',
     22: 'to',
     23: 'perform,',
     24: 'the',
     25: 'need',
     26: 'to',
     27: 'iterate',
     28: 'over',
     29: 'sequences',
     30: 'is',
     31: 'so',
     32: 'common',
     33: 'and',
     34: 'pervasive',
     35: 'that',
     36: 'Python',
     37: 'provides',
     38: 'additional',
     39: 'tools',
     40: 'to',
     41: 'make',
     42: 'it',
     43: 'simpler',
     44: 'and',
     45: 'more',
     46: 'efficient.'}

```python
L1 = list(range(1,100,2))
```

```python
L2 = list(range(0,101,2))
```

```python
zip(L1,L2)
```

    <zip at 0x29085895948>

```python
type(enumerate(L1))
```

    enumerate

```python
for i, j in zip(L1, L2):
    print(i,'==>', j)
```

    1 ==> 0
    3 ==> 2
    5 ==> 4
    7 ==> 6
    9 ==> 8
    11 ==> 10
    13 ==> 12
    15 ==> 14
    17 ==> 16
    19 ==> 18
    21 ==> 20
    23 ==> 22
    25 ==> 24
    27 ==> 26
    29 ==> 28
    31 ==> 30
    33 ==> 32
    35 ==> 34
    37 ==> 36
    39 ==> 38
    41 ==> 40
    43 ==> 42
    45 ==> 44
    47 ==> 46
    49 ==> 48
    51 ==> 50
    53 ==> 52
    55 ==> 54
    57 ==> 56
    59 ==> 58
    61 ==> 60
    63 ==> 62
    65 ==> 64
    67 ==> 66
    69 ==> 68
    71 ==> 70
    73 ==> 72
    75 ==> 74
    77 ==> 76
    79 ==> 78
    81 ==> 80
    83 ==> 82
    85 ==> 84
    87 ==> 86
    89 ==> 88
    91 ==> 90
    93 ==> 92
    95 ==> 94
    97 ==> 96
    99 ==> 98

# Iterators：A First Look
>>> The for loop can work on any sequence type in Python
Sequence types: lists, tuples, strings, files, zip object, enumerate, map, range, np.array, np.arange, etc..

```python
for i in map(ord, str(L1)):
    print(i, end = ' ')
```

    91 49 44 32 51 44 32 53 44 32 55 44 32 57 44 32 49 49 44 32 49 51 44 32 49 53 44 32 49 55 44 32 49 57 44 32 50 49 44 32 50 51 44 32 50 53 44 32 50 55 44 32 50 57 44 32 51 49 44 32 51 51 44 32 51 53 44 32 51 55 44 32 51 57 44 32 52 49 44 32 52 51 44 32 52 53 44 32 52 55 44 32 52 57 44 32 53 49 44 32 53 51 44 32 53 53 44 32 53 55 44 32 53 57 44 32 54 49 44 32 54 51 44 32 54 53 44 32 54 55 44 32 54 57 44 32 55 49 44 32 55 51 44 32 55 53 44 32 55 55 44 32 55 57 44 32 56 49 44 32 56 51 44 32 56 53 44 32 56 55 44 32 56 57 44 32 57 49 44 32 57 51 44 32 57 53 44 32 57 55 44 32 57 57 93

```python
import numpy as np
```

```python
for i in np.arange(1,100,2):
    print(i, end = ' ')
```

    1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99

```python
67 in np.arange(1,100,2)
```

    True

>>> sequence type = iterable objectAn iterable object: 1. A physically stored sequence (Physically exists)
                    2. An object that produces one result at a time (in the context of an iteration tool) (virtually exists)

```python
list(zip(L1,L2))[1]
```

    (3, 2)

```python
L = []
for i in np.arange(1,100,2):
    i +=1
    L.append(i)
```

# The Iteration Protol: File Iterators

```python
file = open('woshicik.txt',encoding = 'utf-8')
```
>>> The difference between readline method and __next__ method lies in that readline returns an empty string
at the end of file while the later returns a built-in StopIteration exception

```python
for i in range(987):
    file.__next__()
```

```python
file.readline()
```

    ''

* iterable == iterator
iterable: support iter function # For example; file
iterator: an object return by iter, support next function

```python
iter(file) # because file supports iter()
I = iter(file) # I is iterator because it is an object return by iter()
```

```python
next(I)
```

    '暗影烈焰\n'

```python
S = """The net effect of this magic is that, as mentioned in Chapter 9, the best way to read a
text file line by line today is to not read it at all—instead, allow the for loop to automatically call __next__ to advance to the next line on each iteration. The file object’s
iterator will do the work of automatically loading lines as you go. The following, for
example, reads a file line by line, printing the uppercase version of each line along the
way, without ever explicitly reading from the file at all:"""
```

```python
for line in open('script1.txt','r'):
    print(line.upper())
```

    HELLO, BUDDY! I AM FINE. HOW ABOUT YOU? YOU KNOW DURING THE OUTBREAK OF COVID-19, I'M PLAYING VIDEO GAMES ALL THE TIME. I REALLY HAVE A GOOD TIME, MAN. DON'T WORRY. BTW, WHAT ARE YOU RECENTLY UP TO?THIS VIRUS IS REALLY CRAZY. I HEARD THAT MANY FACTORIES IN THE WORLD HAVE BEEN SHUT DOWN TRY TO DO SOMETHING, MAN. YOU CAN MAKE VIDEO CHATS WITH YOUR FAMILIES AND YOUR FRIENDS LIKE ME.

```python
f = open('script1.txt','w') #没打开一次，运行write命令就会覆盖相应的文件内容
f.write('This interface is exactly what we call the iteration protocol in Python. Any object with')
```

    88

```python
f.close()
```

```python
f = open('script1.txt','r')
```

```python
for line in open('script1.txt','r'):
    print(line.upper())
```

    THIS INTERFACE IS EXACTLY WHAT WE CALL THE ITERATION PROTOCOL IN PYTHON. ANY OBJECT WITH

```python
open('script1.txt','w').write('text file line by line today is to not read it at all—instead, allow the for loop to auto')
```

    89

```python
for line in open('script1.txt','r'):
    print(line.upper())
```

    THE NET EFFECT OF THIS MAGIC IS THAT, AS MENTIONED IN CHAPTER 9, THE BEST WAY TO READ A

    TEXT FILE LINE BY LINE TODAY IS TO NOT READ IT AT ALL-INSTEAD, ALLOW THE FOR LOOP TO AUTO-

# The best practice to load file's content into memory is to use file iterators to read by lines, rather than use the readline method (the older way)
>>> Three reasons:
    1. Simlest to code;
    2. Quickest to run;
    3. Save the memory usage.

```python
file2 = open('ceshiwenjian2.txt','w')
```

```python
file2.write('This interface is exactly what we call the iteration protocol in Python. Any object with \n')
```

    90

```python
file2.write('a __next__ method to advance to a next result, which raises StopIteration at the end \n')
```

    86

```python
file2.close()
```

```python
open('ceshiwenjian2.txt','r').read()
```

    'This interface is exactly what we call the iteration protocol in Python. Any object with \na __next__ method to advance to a next result, which raises StopIteration at the end \n'

```python
from sympy import *
```

```python
init_session()
```

    IPython console for SymPy 1.4 (Python 3.7.4-64-bit) (ground types: python)

    These commands were executed:
    >>> from __future__ import division
    >>> from sympy import *
    >>> x, y, z, t = symbols('x y z t')
    >>> k, m, n = symbols('k m n', integer=True)
    >>> f, g, h = symbols('f g h', cls=Function)
    >>> init_printing()

    Documentation can be found at https://docs.sympy.org/1.4/

```python
eye(4)
```

```python
from sympy import sin, Interval
from sympy.abc import theta
```

```python
solve(sin(theta) + 1/2*sin(2*theta) + 1/3*sin(3*theta), theta, domain = Interval(0, pi))
```

```python
simplify(sin(theta) + 1/2*sin(2*theta) + 1/3*sin(3*theta))
```

```python
@vectorize(0,1)
def vdiff(f,y):
    return diff(f,y)
```

```python
vdiff([f(x, y, z), g(x, y, z), h(x, y, z)], [x, y, z])
```

```python
s = symbols("s",cls=Function)
vdiff(s(x,y,z),[x,y,z])
```

```python
diff(s,D.x)*D.i + diff(s, D.y)*D.j +  diff(s,D.z)*D.k
```

# 比如说解决比较常规的一元二次方程，a*x^2 + b*x + c = 0

```python
a, b, c = symbols('a b c')
```

```python
solveset(a*x**2 + b*x + c, x)
```

# 解决更高级的一元三次方程，ax^3 + bx^2 + cx + d = 0

```python
d = symbols('d')
```

```python
solveset(a*x**3 + b*x**2 + c*x + d, x)
```

# 求导数

```python
from sympy import sin, cos, tan
diff(sin(x)**2+ sin(x)*cos(x)+tan(x),(x,4))
```

# 求积分

```python
from sympy import integrate
```

```python
integrate(tan(x),x)
```

```python
integrate(sin(x),x)
```

# 求偏微分方程

```python
from sympy import Eq
from sympy.solvers.pde import pdsolve
```

```python
u = f(x, y)
ux = diff(u,x)
uy = diff(u,y)
```

```python
ux, uy
```

```python
eq = Eq(1+(2*(ux/u)+(3*(uy/u))),0)
```

```python
eq
```

```python
pdsolve(eq)
```

```python
from sympy.abc import *
```

```python
import os
```

```python
os.getcwd()
```

    'C:\\Users\\NickC'

```python
import pandas as pd
```

```python
df = pd.read_csv('C://Users/NickC/seaborn-data/flights.csv')
```

```python
df
```

      year
      month
      passengers

      0
      1949
      January
      112

      1
      1949
      February
      118

      2
      1949
      March
      132

      3
      1949
      April
      129

      4
      1949
      May
      121

      ...
      ...
      ...
      ...

      139
      1960
      August
      606

      140
      1960
      September
      508

      141
      1960
      October
      461

      142
      1960
      November
      390

      143
      1960
      December
      432

144 rows × 3 columns

```python
import os # 导入操作系统 Operating System
dir(os)
```

    ['DirEntry',
     'F_OK',
     'MutableMapping',
     'O_APPEND',
     'O_BINARY',
     'O_CREAT',
     'O_EXCL',
     'O_NOINHERIT',
     'O_RANDOM',
     'O_RDONLY',
     'O_RDWR',
     'O_SEQUENTIAL',
     'O_SHORT_LIVED',
     'O_TEMPORARY',
     'O_TEXT',
     'O_TRUNC',
     'O_WRONLY',
     'P_DETACH',
     'P_NOWAIT',
     'P_NOWAITO',
     'P_OVERLAY',
     'P_WAIT',
     'PathLike',
     'R_OK',
     'SEEK_CUR',
     'SEEK_END',
     'SEEK_SET',
     'TMP_MAX',
     'W_OK',
     'X_OK',
     '_Environ',
     '__all__',
     '__builtins__',
     '__cached__',
     '__doc__',
     '__file__',
     '__loader__',
     '__name__',
     '__package__',
     '__spec__',
     '_execvpe',
     '_exists',
     '_exit',
     '_fspath',
     '_get_exports_list',
     '_putenv',
     '_unsetenv',
     '_wrap_close',
     'abc',
     'abort',
     'access',
     'altsep',
     'chdir',
     'chmod',
     'close',
     'closerange',
     'cpu_count',
     'curdir',
     'defpath',
     'device_encoding',
     'devnull',
     'dup',
     'dup2',
     'environ',
     'error',
     'execl',
     'execle',
     'execlp',
     'execlpe',
     'execv',
     'execve',
     'execvp',
     'execvpe',
     'extsep',
     'fdopen',
     'fsdecode',
     'fsencode',
     'fspath',
     'fstat',
     'fsync',
     'ftruncate',
     'get_exec_path',
     'get_handle_inheritable',
     'get_inheritable',
     'get_terminal_size',
     'getcwd',
     'getcwdb',
     'getenv',
     'getlogin',
     'getpid',
     'getppid',
     'isatty',
     'kill',
     'linesep',
     'link',
     'listdir',
     'lseek',
     'lstat',
     'makedirs',
     'mkdir',
     'name',
     'open',
     'pardir',
     'path',
     'pathsep',
     'pipe',
     'popen',
     'putenv',
     'read',
     'readlink',
     'remove',
     'removedirs',
     'rename',
     'renames',
     'replace',
     'rmdir',
     'scandir',
     'sep',
     'set_handle_inheritable',
     'set_inheritable',
     'spawnl',
     'spawnle',
     'spawnv',
     'spawnve',
     'st',
     'startfile',
     'stat',
     'stat_result',
     'statvfs_result',
     'strerror',
     'supports_bytes_environ',
     'supports_dir_fd',
     'supports_effective_ids',
     'supports_fd',
     'supports_follow_symlinks',
     'symlink',
     'sys',
     'system',
     'terminal_size',
     'times',
     'times_result',
     'truncate',
     'umask',
     'uname_result',
     'unlink',
     'urandom',
     'utime',
     'waitpid',
     'walk',
     'write']

```python
%mkdir Python_iter_next
```

```python
os.rmdir('C:/Users/NickC/Python_iter_next/')
```

```python
os.utime?
```

    Signature: os.utime(path, times=None, *, ns=None, dir_fd=None, follow_symlinks=True)
    Docstring:
    Set the access and modified time of path.

    path may always be specified as a string.
    On some platforms, path may also be specified as an open file descriptor.
      If this functionality is unavailable, using it raises an exception.

    If times is not None, it must be a tuple (atime, mtime);
        atime and mtime should be expressed as float seconds since the epoch.
    If ns is specified, it must be a tuple (atime_ns, mtime_ns);
        atime_ns and mtime_ns should be expressed as integer nanoseconds
        since the epoch.
    If times is None and ns is unspecified, utime uses the current time.
    Specifying tuples for both times and ns is an error.

    If dir_fd is not None, it should be a file descriptor open to a directory,
      and path should be relative; path will then be relative to that directory.
    If follow_symlinks is False, and the last element of the path is a symbolic
      link, utime will modify the symbolic link itself instead of the file the
      link points to.
    It is an error to use dir_fd or follow_symlinks when specifying path
      as an open file descriptor.
    dir_fd and follow_symlinks may not be available on your platform.
      If they are unavailable, using them will raise a NotImplementedError.
    Type:      builtin_function_or_method

```python
os.remove?
```

    Signature: os.remove(path, *, dir_fd=None)
    Docstring:
    Remove a file (same as unlink()).

    If dir_fd is not None, it should be a file descriptor open to a directory,
      and path should be relative; path will then be relative to that directory.
    dir_fd may not be implemented on your platform.
      If it is unavailable, using it will raise a NotImplementedError.
    Type:      builtin_function_or_method

```python
import os
```

```python
os.system('"D:\Foxit Reader\FoxitReader.exe" F:/GettingStartedGuide.pdf')
```

    0

```python
f = open('untitled3.py')
```

```python
f.read().rstrip() # Read 或者 readline 文件末尾的时候会给出空的字符串
```

    '# -*- coding: utf-8 -*-\n"""\nCreated on Tue Feb 18 22:04:07 2020\n\n@author: NickC\n"""\n\n#KocheDraw1\nimport turtle\ndef koch(size,n):\n  if n==1:\n    turtle.fd(size)\n  else:\n    for i in [0,60,-120,60]:\n      turtle.left(i)\n      koch(size/3,n-1)\ndef main():\n  turtle.setup(600,600)\n  turtle.penup()\n  turtle.speed(10)\n  turtle.hideturtle()\n  turtle.pensize(2)\n  turtle.goto(-200,100)\n  turtle.pendown()\n  level=4\n  koch(400,level)\n  turtle.right(120)\n  koch(400, level)\n  turtle.right(120)\n  koch(400, level)\n  turtle.penup()\n  turtle.done()\nmain()'

```python
f.__next__() # __next__这个呢，在文件末尾会返回 ‘停止迭代’的错误
```

```python
from sympy import *
f.readline()
init_session() # 如果上面的命令是read或者readline,这一行的命令就会被执行； 而如果上一行命令是
               # __next__这个命令的话，这一行的命令就不会被执行
```

    IPython console for SymPy 1.4 (Python 3.7.4-64-bit) (ground types: python)

    These commands were executed:
    >>> from __future__ import division
    >>> from sympy import *
    >>> x, y, z, t = symbols('x y z t')
    >>> k, m, n = symbols('k m n', integer=True)
    >>> f, g, h = symbols('f g h', cls=Function)
    >>> init_printing()

    Documentation can be found at https://docs.sympy.org/1.4/

```python
next(f)
```

    '# -*- coding: utf-8 -*-\n'

```python
os.getcwd()
```

    'C:\\Users\\NickC'

```python
os.system(" D:/Notepad/notepad.exe C:/Users/NickC/untitled3.py")
```

```python
L = list(range(1,25,1))
```

```python
L.__next__()
```

```python
I = iter(L)
```

```python
type(I)
```

    list_iterator

```python
f.__next__()
```

    '# -*- coding: utf-8 -*-\n'

```python
next(f).rstrip()
```

    'Created on Tue Feb 18 22:04:07 2020'

```python
iter?
```

    Docstring:
    iter(iterable) -> iterator
    iter(callable, sentinel) -> iterator

    Get an iterator from an object.  In the first form, the argument must
    supply its own iterator, or be a sequence.
    In the second form, the callable is called until it returns the sentinel.
    Type:      builtin_function_or_method

```python
iter(f) is f
```

    True

```python
type(a), type(b)  #疑问
```

    (int, int)

```python
a
```

    True

```python
L = [1,2,3]
```

```python
iter(L) is L
```

    False

```python
f = open('untitled3.py')
```

```python
f.read()  #
```

    '# -*- coding: utf-8 -*-\n"""\nCreated on Tue Feb 18 22:04:07 2020\n\n@author: NickC\n"""\n\n#KocheDraw1\nimport turtle\ndef koch(size,n):\n  if n==1:\n    turtle.fd(size)\n  else:\n    for i in [0,60,-120,60]:\n      turtle.left(i)\n      koch(size/3,n-1)\ndef main():\n  turtle.setup(600,600)\n  turtle.penup()\n  turtle.speed(10)\n  turtle.hideturtle()\n  turtle.pensize(2)\n  turtle.goto(-200,100)\n  turtle.pendown()\n  level=4\n  koch(400,level)\n  turtle.right(120)\n  koch(400, level)\n  turtle.right(120)\n  koch(400, level)\n  turtle.penup()\n  turtle.done()\nmain()'

```python
L = [1,2,3]
```

```python
for x in L:
    print(x**2, end=' ')
```

    1 4 9

```python
I = iter(L)
while True:
    try:
        x = next(I)
    except StopIteration:
        break
    print(x**2, end = ' ')
```

    1 4 9

```python
class keyword(Exception):
    pass

def doomed(x):
    if x == 'Stop':
        raise keyword

while True:
    try:
        x = input('Please type something to continue:')
        doomed(x)
    except keyword:
        break
    print(x, end = '\n')
```

    Please type something to continue: Who am I

    Who am I

    Please type something to continue: why are you?

    why are you?

    Please type something to continue: iterator

    iterator

    Please type something to continue: Stop

```python
try:
    x = input('please type something to continue:')
    doomed(x)
except keyword:
    print('you typed nothing,buddy.')
```

    please type something to continue: Stop

    you typed nothing,buddy.

```python
from manimlib.imports import *

class Shapes(Scene):
    def construct(self):
        circle = Circle()
        square = Square()
        line = Line(np.array([3,0,0]),np.array([5,0,0]))
        triangle = Polygon(np.array([0,0,0]),np.array([1,1,0]),np.array([1,-1,0]))

        self.add(line)
        self.play(ShowCreation(circle))
        self.play(GrowFromCenter(square))
        self.play(Transform(square,triangle))
```

```python
class MoreShapes(Scene):
    def construct(self):
        circle = Circle(color=PURPLE_A)
        square = Square(fill_color=GOLD_B,fill_opacity=1, color=GOLD_A)
        square.move_to(UP+LEFT)
        circle.surround(square)
        rectangle = Rectangle(height=2, width =3)
        ellipse= Ellipse(width=3, height=1, color=RED)
        ellipse.shift(2*DOWN+2*RIGHT)
        pionter = CurvedArrow(2*RIGHT,5*RIGHT, color= MAROON_C)
        arrow = Arrow(LEFT,UP)
        arrow.next_to(cicle,DOWN+LEFT)
        rectangle.next_to(arrow, DOWN+LEFT)
        ring = Annulus(inner_radius=.5, outer_radius=1, color=BLUE)
        ring.next_to(ellipse,RIGHT)

        self.add(pointer)
        self.play(FadeIn(square))
        self.play(Rotating(square),FadeIn(circle))
        self.play(GrowArrow(arrow))
        self.play(GrowFromCenter(rectangle),GrowFromCenter(ellipse),GrowFromCenter(ring))
```

```python
init_sess
```

    IPython console for SymPy 1.4 (Python 3.7.4-64-bit) (ground types: python)

    These commands were executed:
    >>> from __future__ import division
    >>> from sympy import *
    >>> x, y, z, t = symbols('x y z t')
    >>> k, m, n = symbols('k m n', integer=True)
    >>> f, g, h = symbols('f g h', cls=Function)
    >>> init_printing()

    Documentation can be found at https://docs.sympy.org/1.4/

```python
latex(2**x = t**k)
```

```python
pH = symbols('pH')
```

```python
latex(x*(y*z)**t)
```

    'x \\left(y z\\right)^{t}'

```python
class AddingText(Scene):
    def construct(self):
        my_first_text = TextMobject("室温下，向下列溶液中通入相应的气体").to_edge(UP)
        second_line = TextMobject('至溶液 pH＝7(通入气体对溶液体积的影响可忽略)')
        second_line.next_to(my_first_text, DOWN)
        third_line = TextMobject("溶液中部分微粒的物质的量浓度关系正确的是")
        third_line.next_to(second_line,DOWN)

        fourth_line= TextMobject('室温下                             ').set_color(RED)
        fourth_line.next_to(second_line, UP)

        fifth_line = TextMobject('pH＝7                               ').set_color(RED)
        fifth_line.next_to(fourth_line,DOWN)

        sixth_line = TextMobject('正确                                ').set_color(RED)
        sixth_line.next_to(fifth_line,DOWN)

        self.play(ShowCreation(my_first_text))
        self.play(ShowCreation(second_line))
        self.wait(1)
        self.play(ShowCreation(third_line))
        self.wait(1)
        self.play(Transform(my_first_text,fourth_line))
        self.wait(1)
        self.play(Transform(second_line, fifth_line))
        self.wait(1)
        self.play(Transform(third_line,sixth_line))

        fourth_line.shift(6*LEFT)
        fifth_line.shift(6*LEFT+4*DOWN)
        self.wait(2)
```

```python
class RotateAndHighlight(Scene):
    def construct(self):
        square= Square(side_length=5, fill_color=YELLOW, fill_opacity=1)
        label = TextMobject("Text at an angle")
        label.bg = BackgroundRectangle(label,fill_opacity=1)
        label_group=VGroup(label.bg,label)

        label_group.rotate(TAU/8)

        label2 = TextMobject("Boxed text", color=BLACK)
        label2.bg = SurroundingRectangle(label2,color=BLUE, fill_color=RED, fill_opacity=.5)
        label2_group= VGroup(label2,label2.bg)
        label2_group.next_to(label_group,DOWN)

        label3 = TextMobject('Rainbow')
        label3.scale(2)
        label3.set_color_by_gradient(RED,ORANGE,YELLOW, GREEN, BLUE, PURPLE)
        label3.to_edge(DOWN)

        self.add(square)
        self.play(FadeIn(label_group))
        self.play(FadeIn(label2_group))
        self.play(FadeIn(label3))
```

```python
# Creating text
class AddingText(Scene):
    def construct(self):
        my_first_text = TextMobject("Writing with manim is fun")
        second_line = TextMobject('and easy to do!')
        second_line.next_to(my_first_text,DOWN)
        third_line = TextMobject("for me and you!")
        third_line.next_to(my_first_text,DOWN)
        self.add(my_first_text,second_line)
        self.wait(2)
        self.play(Transform(second_line,third_line))
        self.wait(2)
        second_line.shift(3*DOWN)
        self.play(ApplyMethod(my_first_text.shift,3*UP))
```

```python
# Changing Text
class AddingMoreText(Scene):
    def construct(self):
        quote = TextMobject("Imagination is more important than knowledge ")
        quote.set_color(RED)
        quote.to_edge(UP)
        quote2 = TextMobject("A person who never made a mistake never tried anything new ")
        quote2.set_color(YELLOW)
        author= TextMobject("-Albert Einstein")
        author.scale(0.75)
        author.next_to(quote.get_corner(DOWN+RIGHT),DOWN)

        self.add(quote)
        self.add(author)
        self.wait(2)
        self.play(Transform(quote,quote2),ApplyMethod(author.move_to, quote2.get_corner(DOWN+RIGHT)+DOWN+2*LEFT))

        self.play(ApplyMethod(author.scale,1.5))
        author.match_color(quote2)
        self.play(FadeOut(quote))
```

```python
# Mathematical Equations

class BasicEquations(Scene):
    def construct(self):
        eq1 = TextMobject("$\\frac{d^{2}}{d x^{2}} \\tan{\\left(x \\right)} = 2 \\left(\\tan^{2}{\\left(x \\right)} + 1\\right) \\tan{\\left(x \\right)}$")
        eq1.shift(2*UP)
        eq2 = TextMobject('$\\sum_{n=1}^{n} n^{2} = \\frac{n \\left(2 n^{2} + 3 n + 1\\right)}{6}$')
        eq2.shift(2*DOWN)

        self.play(Write(eq1))
        self.play(Write(eq2))
```

```python
latex('\\vec{x}_0 \\cdot  \\vec{Y}_1 = 3')
```

    '\\vec{x}_0 \\cdot  \\vec{Y}_1 = 3'

```python
latex(Eq(Derivative(tan(x),(x,2)), diff(tan(x),(x,2))))
```

    '\\frac{d^{2}}{d x^{2}} \\tan{\\left(x \\right)} = 2 \\left(\\tan^{2}{\\left(x \\right)} + 1\\right) \\tan{\\left(x \\right)}'

```python
latex(Eq(Sum(n**2,(n,1,k)), simplify(Sum(n**2,(n,1,k)).doit())))
```

    '\\sum_{n=1}^{k} n^{2} = \\frac{k \\left(2 k^{2} + 3 k + 1\\right)}{6}'

```python

```

```python
simplify(Sum(n**2,(n,1,n)).doit())
```

```python
class AddingText(Scene):
    def construct(self):
        my_first_text = TextMobject("室温下，向下列溶液中通入相应的气体").to_edge(UP)
        second_line = TextMobject('至溶液 pH＝7(通入气体对溶液体积的影响可忽略)')
        second_line.next_to(my_first_text, DOWN)
        third_line = TextMobject("溶液中部分微粒的物质的量浓度关系正确的是")
        third_line.next_to(second_line,DOWN)

        fourth_line= TextMobject('室温下                             ').set_color(RED)
        fourth_line.next_to(second_line, UP)

        fifth_line = TextMobject('pH＝7                               ').set_color(RED)
        fifth_line.next_to(fourth_line,DOWN)

        sixth_line = TextMobject('正确                                ').set_color(RED)
        sixth_line.next_to(fifth_line,DOWN)

        self.play(ShowCreation(my_first_text))
        self.play(ShowCreation(second_line))
        self.wait(1)
        self.play(ShowCreation(third_line))
        self.wait(1)
        self.play(Transform(my_first_text,fourth_line))
        self.wait(1)
        self.play(Transform(second_line, fifth_line))
        self.wait(1)
        self.play(Transform(third_line,sixth_line))

        fourth_line.shift(6*LEFT)
        fifth_line.shift(6*LEFT+4*DOWN)
        self.wait(2)

# Coloring Equations
class ColoringEquations(Scene):
    # Grouping and coloring parts of equations
    def construct(self):
        line1 = TextMobject("\\sum_{n=1}^{k} n^{2} \\text{ = } \\frac{k \\left(2 k^{2} + 3 k + 1\\right)}{6}", tex_to_color_map={'=': YELLOW})
        line2 = TextMobject("\\frac{d^{2}}{d x^{2}} \\tan{\\left(x \\right)} = 2 \\left(\\tan^{2}{\\left(x \\right)} + 1\\right) \\tan{\\left(x \\right)}")
        line2.set_color_by_tex_to_color_map({"=": YELLOW, "\\frac{d^{2}}{d x^{2}} \\tan{\\left(x \\right)}": RED})
        sentence = VGroup(line1,line2)
        sentence.arrange_submobjects(DOWN,buff=MED_LARGE_BUFF)
        self.play(Write(sentence))
```

```python
# Coloring Equations
class ColoringEquations(Scene):
    # Grouping and coloring parts of equations
    def construct(self):
        line1 = TextMobject("This is something I want to do", tex_to_color_map={"something": YELLOW})
        line2 = TextMobject("I tried and I wouldn't give up my dream \\\\", "I believe my dream Even nobody cares \\\\",tex_to_color_map={"I believe my dream": RED})

        sentence = VGroup(line1,line2)
        sentence.arrange_submobjects(DOWN,buff=MED_LARGE_BUFF)
        self.play(Write(sentence))

```

```python
# Aligning Text and Using Braces
class UsingBraces(Scene):
    def construct(self):
        eq1A = TextMobject("4*x+3*y")
        eq1B = TextMobject("=")
        eq1c = TextMobject("0")
        eq2A = TextMobject("5*x-2y")
        eq2B = TextMobject("=")
        eq2C = TextMobject("3")
        eq1B.next_to(eq1A,RIGHT)
        eq1C.next_to(eq1B,RIGHT)
        eq2A.shift(DOWN)
        eq2B.shift(DOWN)
        eq2C.shift(DOWN)
        eq2A.align_to(eq1A,LEFT)
        eq2B.align_to(eq1B,LEFT)
        eq2C.align_to(eq1C,LEFT)

        eq_group=VGroup(eq1A,eq2A)
        braces=Brace(eq_group,LEFT)
        eq_text = braces.get_text("A pair of equations")

        self.add(eq1A,eq1B,eq1c)
        self.add(eq2A,eq2B,eq2C)
        self.play(GrowFromCenter(braces),Write(eq_text))

#Using Braces Concise
class UsingBracesConcise(Scene):
    def construct(self):
        eq1_text = ["4","x","+","3",'y',"=",'0']
        eq2_text = ['5','x','-','2','y','=','3']
        eq1_mob = TextMobject(*eq1_text)
        eq2_mob = TextMobject(*eq2_text)
        eq1_mob.set_color_by_tex_to_color_map({"x":RED_B,'y': GREEN_C})
        eq2_mob.set_color_by_tex_to_color_map({"x":RED_B,'y':GREEN_C})

        for i, item in enumerate(eq2_mob):
            item.align_to(eq1_mob[i],LEFT)
        eq1= VGroup(*eq1_mob)
        eq2 = VGroup(*eq2_mob)
        eq2.shift(DOWN)
        eq_group=VGroup(eq1,eq2)
        braces = Brace(eq_group,LEFT)
        eq_text= braces.get_text("A pair pf equations")

        self.play(Write(eq1),Write(eq2))
        self.play(GrowFromCenter(braces),Write(eq_text))
```

```python
#Using Braces Concise
class UsingBracesConcise(Scene):
    def construct(self):
        eq1_text = ["4","x","+","3",'y',"=",'0']
        eq2_text = ['5','x','-','2','y','=','3']
        eq1_mob = TextMobject(*eq1_text)
        eq2_mob = TextMobject(*eq2_text)
        eq1_mob.set_color_by_tex_to_color_map({"x":RED_B,'y': GREEN_C})
        eq2_mob.set_color_by_tex_to_color_map({"x":RED_B,'y':GREEN_C})

        for i, item in enumerate(eq2_mob):
            item.align_to(eq1_mob[i],LEFT)
        eq1= VGroup(*eq1_mob)
        eq2 = VGroup(*eq2_mob)
        eq2.shift(DOWN)
        eq_group=VGroup(eq1,eq2)
        braces = Brace(eq_group,LEFT)
        eq_text= braces.get_text("A pair pf equations")

        self.play(Write(eq1),Write(eq2))
        self.play(GrowFromCenter(braces),Write(eq_text))

# Graphing Functions
class PlotFunctions(GraphScene):
    CONFIG = {
        "x_min": -10,
        "x_max":10.3,
        "y_max": 1.5,
        "y_min":-1.5,
        'graph_origin': ORIGIN,
        "function": RED,
        "axes_color": GREEN,
        "x_labeled_nums": range(-10,12,2),
    }

    def construct(self):
        self.setup_axes(animate=True)
        func_graph= self.get_graph(self.func_to_graph,color=RED_B)
        func_graph2 = self.get_graph(self.func_to_graph2)
        vert_line = self.get_vertical_line_to_graph(TAU,func_graph,color=YELLOW)
        graph_lab = self.get_graph_label(func_graph,label='\\cos(x)')
        graph_lab2 = self.get_graph_label(func_graph2, label='\\sin(x)', x_val=-10, direction=UP/2)
        two_pi = TextMobject("$x=2 \\pi$")
        label_coord= self.input_to_graph_point(TAU, func_graph)
        two_pi.next_to(label_coord,RIGHT+UP)

        self.play(ShowCreation(func_graph),ShowCreation(func_graph2))
        self.play(ShowCreation(vert_line),ShowCreation(graph_lab),ShowCreation(graph_lab2),ShowCreation(two_pi))
    def func_to_graph(self,x):
        return np.cos(x)

    def func_to_graph2(self,x):
        return np.sin(x)
```

```python
# Graphing Functions
class PlotFunctions(GraphScene):
    CONFIG = {
        "x_min": -10,
        "x_max":10.3,
        "y_max": 1.5,
        "y_min":-1.5,
        'graph_origin': ORIGIN,
        "function": RED,
        "axes_color": GREEN,
        "x_labeled_nums": range(-10,12,2),
    }

    def construct(self):
        self.setup_axes(animate=True)
        func_graph= self.get_graph(self.func_to_graph,color=RED_B)
        func_graph2 = self.get_graph(self.func_to_graph2)
        vert_line = self.get_vertical_line_to_graph(TAU,func_graph,color=YELLOW)
        graph_lab = self.get_graph_label(func_graph,label='\\cos(x)')
        graph_lab2 = self.get_graph_label(func_graph2, label='\\sin(x)', x_val=-10, direction=UP/2)
        two_pi = TextMobject("$x=2 \\pi$")
        label_coord= self.input_to_graph_point(TAU, func_graph)
        two_pi.next_to(label_coord,RIGHT+UP)

        self.play(ShowCreation(func_graph),ShowCreation(func_graph2))
        self.play(ShowCreation(vert_line),ShowCreation(graph_lab),ShowCreation(graph_lab2),ShowCreation(two_pi))
    def func_to_graph(self,x):
        return np.cos(x)

    def func_to_graph2(self,x):
        return np.sin(x)

# The config Dictionary
class GraphScene(Scene):
    CONFIG = {
        "x_min": -1,
        "x_max": 10,
        "x_axis_width": 9
        "x_tick_frequency": 1
        "x_leftmost_tick": None, # Change if different from x_min
        "x_labeled_nums": None,
        "x_axis_label": "$x$",
        "y_min": -1,
        "y_max": 10,
        "y_axis_height": 6,
        "y_tick_frequency": 1,
        "y_bottom_tick": None, # Change if different from y_min
        "y_labeled_nums": None,
        "y_axis_label": "$y$",
        "axes_color": GREY,
        "graph_origin": 2.5*DOWN+4*LEFT,
        "exclude_zero_label":True,
        "num_graph_anchor_points":25,
        "default_graph_colors": [BLUE,GREEN,YELLOW],
        "default_derivative_color": GREEN,
        "default_input_color": YELLOW,
        "default_riemann_start_color": BLUE,
        "default_riemann_end_color": GREEN,
        "area_opacity": 0.8,
        "num_rects": 50,
    }

class Scene(Container):
    CONFIG = {
        "camera_class": Camera,
        "camera_config":{},
        "frame_duration": LOW_QUALITY_FRAME_DURATION,
        "construct_args": [],
        "skip_animations": False,
        "ignore_waits": False,
        "write_to_movie": False,
        "save_frames": False,
        "save_pngs":False,
        "pngs_mode": "RGBA",
        "movie_file_extension": ".mp4",
        "name": None,
        "always_continually_update": False,
        "random_seed": 0,
        "start_at_animation_number": None,
        "end_at_animation_number": None,
        "livestreaming": False,
        "to_twitch": False,
        "twitch_key": None,
    }
```

```python
# Graphing Functions
class PlotFunctions(GraphScene):
    CONFIG = {
        "x_min": -10,
        "x_max":10.3,
        "y_max": 1.5,
        "y_min":-1.5,
        'graph_origin': ORIGIN,
        "function": RED,
        "axes_color": GREEN,
        "x_labeled_nums": range(-10,12,2),
    }

    def construct(self):
        self.setup_axes(animate=True)
        func_graph= self.get_graph(self.func_to_graph,color=RED_B)
        func_graph2 = self.get_graph(self.func_to_graph2)
        vert_line = self.get_vertical_line_to_graph(TAU,func_graph,color=YELLOW)
        graph_lab = self.get_graph_label(func_graph,label='\\cos(x)')
        graph_lab2 = self.get_graph_label(func_graph2, label='\\sin(x)', x_val=-10, direction=UP/2)
        two_pi = TextMobject("$x=2 \\pi$")
        label_coord= self.input_to_graph_point(TAU, func_graph)
        two_pi.next_to(label_coord,RIGHT+UP)

        self.play(ShowCreation(func_graph),ShowCreation(func_graph2))
        self.play(ShowCreation(vert_line),ShowCreation(graph_lab),ShowCreation(graph_lab2),ShowCreation(two_pi))
    def func_to_graph(self,x):
        return np.cos(x)

    def func_to_graph2(self,x):
        return np.sin(x)

# More Graphing
class ExampleApproximation(GraphScene):
    CONFIG = {
        "function": lambda
    }
```

```python
from sympy import *
```

```python
init_session()
```

    IPython console for SymPy 1.4 (Python 3.7.4-64-bit) (ground types: python)

    These commands were executed:
    >>> from __future__ import division
    >>> from sympy import *
    >>> x, y, z, t = symbols('x y z t')
    >>> k, m, n = symbols('k m n', integer=True)
    >>> f, g, h = symbols('f g h', cls=Function)
    >>> init_printing()

    Documentation can be found at https://docs.sympy.org/1.4/

```python
# Graphing Functions
class PlotFunctions(GraphScene):
    CONFIG = {
        "x_min": -10,
        "x_max":10.3,
        "y_max": 1.5,
        "y_min":-1.5,
        'graph_origin': ORIGIN,
        "function": RED,
        "axes_color": GREEN,
        "x_labeled_nums": range(-10,12,2),
    }

    def construct(self):
        self.setup_axes(animate=True)
        func_graph= self.get_graph(self.func_to_graph,color=RED_B)
        func_graph2 = self.get_graph(self.func_to_graph2)
        vert_line = self.get_vertical_line_to_graph(TAU,func_graph,color=YELLOW)
        graph_lab = self.get_graph_label(func_graph,label='\\cos(x)')
        graph_lab2 = self.get_graph_label(func_graph2, label='\\sin(x)', x_val=-10, direction=UP/2)
        two_pi = TextMobject("$x=2 \\pi$")
        label_coord= self.input_to_graph_point(TAU, func_graph)
        two_pi.next_to(label_coord,RIGHT+UP)

        self.play(ShowCreation(func_graph),ShowCreation(func_graph2))
        self.play(ShowCreation(vert_line),ShowCreation(graph_lab),ShowCreation(graph_lab2),ShowCreation(two_pi))
    def func_to_graph(self,x):
        return np.cos(x)

    def func_to_graph2(self,x):
        return np.sin(x)

# A Simple Vector Field
class SimpleField(Scene):
    CONFIG = {
        "plane_kwargs": {
            "color": RED
        },
    }
    def construct(self):
        plane = NumberPlane(**self.plane_kwargs)
        plane.add(plane.get_axis_labels())
        self.add(plane)

        points = [x*RIGHT+y*UP
                  for x in np.arange(-5,5,1)
                  for y in np.arange(-5,5,1)
                 ]
        vec_field = []
        for point in points:
            z = np.random.random_sample()
            field = z*RIGHT+np.sqrt(1-z**2)*UP
            result = Vector(field).shift(point)
            vec_field.append(result)

        draw_field = VGroup(*vec_field)

        self.play(ShowCreation(draw_field))
```

```python
import numpy as np
```

```python
np.random.random_sample()
```

```python
RIGHT = symbols("RIGHT")
UP = symbols("UP")
points = [x*RIGHT+y*UP
                  for x in np.arange(-5,5,1)
                  for y in np.arange(-5,5,1)
                 ]
```

```python
# A Simple Vector Field
class SimpleField(Scene):
    CONFIG = {
        "plane_kwargs": {
            "color": RED
        },
    }
    def construct(self):
        plane = NumberPlane(**self.plane_kwargs)
        plane.add(plane.get_axis_labels())
        self.add(plane)

        points = [x*RIGHT+y*UP
                  for x in np.arange(-5,5,1)
                  for y in np.arange(-5,5,1)
                 ]
        vec_field = []
        for point in points:
            z = np.random.random_sample()
            field = z*RIGHT+np.sqrt(1-z**2)*UP
            result = Vector(field).shift(point)
            vec_field.append(result)

        draw_field = VGroup(*vec_field)

        self.play(ShowCreation(draw_field))

class FieldWithAxes(Scene):
    CONFIG = {
        "plane_kwargs":
        {"color": RED_B},
    "point_charge_loc": 0.5*RIGHT-1.5*UP,
        }
    def construct(self):
        plane = NumberPlane(**self.plane_kwargs)
        plane.add(plane.get_axis_labels())
        self.add(plane)

        field = VGroup(*[self.calc_field(x*RIGHT+y*UP)
                        for x in np.arange(-9,9,1)
                        for y in np.arange(-5,5,1)
                        ])
        self.play(ShowCreation(field))
        self.wait(2)
        self.play(Rotating(field))

    def calc_field(self,point):
        x, y = point[:2]
        Rx, Ry = self.point_charge_loc[:2]
        r = math.sqrt((x-Rx)**2+(y-Ry)**2)
        efield= (point-self.point_charge_loc)/r**3
        #efield = np.array((-y,x,0))/math.sqrt(x**2+y**2)
        #efield = np.array((-2*(y%2)+1, -2*(xy%2)+1,0))/3
        return Vector(efield).shift(point)
```

```python
# A variable
class FieldWithAxes(Scene):
    CONFIG = {
        "plane_kwargs":
        {"color": RED_B},
    "point_charge_loc": 0.5*RIGHT-1.5*UP,
        }
    def construct(self):
        plane = NumberPlane(**self.plane_kwargs)
        plane.add(plane.get_axis_labels())
        self.add(plane)

        field = VGroup(*[self.calc_field(x*RIGHT+y*UP)
                        for x in np.arange(-9,9,1)
                        for y in np.arange(-5,5,1)
                        ])
        self.play(ShowCreation(field))
        self.wait(2)
        self.play(Rotating(field))

    def calc_field(self,point):
        x, y = point[:2]
        Rx, Ry = self.point_charge_loc[:2]
        r = math.sqrt((x-Rx)**2+(y-Ry)**2)
        efield= (point-self.point_charge_loc)/r**3
        #efield = np.array((-y,x,0))/math.sqrt(x**2+y**2)
        #efield = np.array((-2*(y%2)+1, -2*(xy%2)+1,0))/3
        return Vector(efield).shift(point)

# Field of a moving charge
class MovingCharges(Scene):
    CONFIG = {
        "plane_kwargs": {
            "color": RED_B
        }, "point_charge_loc": 0.5*RIGHT -1.5*UP,
    }
    def construct(self):
        plane = NumberPlane(**self.plane_kwargs)
        plane.add(plane.get_axis_labels())
        self.add(plane)

        field = VGroup(*[self.calc_field(x*RIGHT+y*UP)
                        for x in np.arange(-9,9,1)
                        for y in np.arange(-5,5,1)
                        ])
        self.field = field
        source_charge = self.Positron().move_to(self.point_charge_loc)
        self.play(FadeIn(source_charge))
        self.play(ShowCreation(field))
        self.moving_charge()

    def calc_field(self,point):
        x, y = point[:2]
        Rx, Ry = self.point_charge_loc[:2]
        r = math.sqrt((x-Rx)**2+(y-Ry)**2)
        efield = (point-self.point_charge_loc)/r**3
        return Vector(efield).shift(point)
    def moving_charge(self):
        numb_charges = 4
        possible_points = [v.get_start() for v in self.field]
        points = random.sample(possible_points,numb_charges)
        particles = VGroup(*[
            self.Positron().move_to(point)
            for point in points
        ])
        for particle in particles:
            particle.velocity= np.array((0,0,0))

        self.play(FadeIn(particles))
        self.moving_particles = particles
        self.add_foeground_mobjects(self.moving_particles)
        self.always_continually_update = True
        self.wait(10)

    def field_at_point(self,point):
        x,y = point[:2]
        Rx, Ry = self.point_charge_loc[:2]
        r = math.sqrt((x-Rx)**2+(y-Ry)**2)
        efield = (point-self.point_charge_loc)/r**3
        return efield
    def continual_update(self, *args, **kwargs):
        if hasattr(self, "moving_particles"):
            dt = self.frame_duration
            for p in self.moving_particles:
                accel = self.field_at_point(p.get_center())
                p.velocity = p.velocity+ accel*dt
                p.shift(p.velocity*dt)
    class Positron(Circle):
        CONFIG = {
            "radius": 0.2,
            "stroke_width": 3.0,
            "color": RED,
            "fill_color": RED,
            "fill_opacity": 0.5,
        }

        def __init__(self, **kwargs):
            Circle.__init__(self, **kwargs)
            plus = TextMobject("+")
            plus.scale(0.7)
            plus.move_to(self)
            self.add(plus)
```

```python
from manimlib.imports import *

class AddingText(Scene):
    def construct(self):
        my_first_text = TextMobject("室温下，向下列溶液中通入相应的气体").to_edge(UP)
        second_line = TextMobject('至溶液 pH＝7(通入气体对溶液体积的影响可忽略)')
        second_line.next_to(my_first_text, DOWN)
        third_line = TextMobject("溶液中部分微粒的物质的量浓度关系正确的是")
        third_line.next_to(second_line,DOWN)

        fourth_line= TextMobject('室温下                             ').set_color(RED)
        fourth_line.next_to(second_line, UP)

        fifth_line = TextMobject('pH＝7                               ').set_color(RED)
        fifth_line.next_to(fourth_line,DOWN)

        sixth_line = TextMobject('正确                                ').set_color(RED)
        sixth_line.next_to(fifth_line,DOWN)

        self.play(ShowCreation(my_first_text))
        self.play(ShowCreation(second_line))
        self.wait(1)
        self.play(ShowCreation(third_line))
        self.wait(1)
        self.play(Transform(my_first_text,fourth_line))
        self.wait(1)
        self.play(Transform(second_line, fifth_line))
        self.wait(1)
        self.play(Transform(third_line,sixth_line))
        fourth_line.shift(6*LEFT)
        fifth_line.shift(6*LEFT+4*DOWN)
        self.wait(2)
```

```python
>>> from chempy import Equilibrium
>>> from sympy import *
init_session()
>>> K1, K2, Kw = symbols('K1 K2 Kw')
>>> e1 = Equilibrium({'MnO4-': 1, 'H+': 8, 'e-': 5}, {'Mn+2': 1, 'H2O': 4}, K1)
>>> e2 = Equilibrium({'O2': 1, 'H2O': 2, 'e-': 4}, {'OH-': 4}, K2)
>>> coeff = Equilibrium.eliminate([e1, e2], 'e-')
>>> coeff
>>> redox = e1*coeff[0] + e2*coeff[1]
>>> pprint(redox)
>>> autoprot = Equilibrium({'H2O': 1}, {'H+': 1, 'OH-': 1}, Kw)
>>> n = redox.cancel(autoprot)
>>> n
>>> redox2 = redox + n*autoprot
>>> pprint(redox2)
```

    IPython console for SymPy 1.4 (Python 3.7.4-64-bit) (ground types: python)

    These commands were executed:
    >>> from __future__ import division
    >>> from sympy import *
    >>> x, y, z, t = symbols('x y z t')
    >>> k, m, n = symbols('k m n', integer=True)
    >>> f, g, h = symbols('f g h', cls=Function)
    >>> init_printing()

    Documentation can be found at https://docs.sympy.org/1.4/

    32 H+ + 4 MnO4- + 20 OH- = 26 H2O + 4 Mn+2 + 5 O2; K1**4/K2**5
    12 H+ + 4 MnO4- = 6 H2O + 4 Mn+2 + 5 O2; K1**4*Kw**20/K2**5

```python
e1 = Equilibrium({'MnO4-': 1, 'H+': 8, 'e-': 5}, {'Mn+2': 1, 'H2O': 4}, K1)
```

```python
e1
```

8 H+ + MnO4- + 5 e- ↔ 4 H2O + Mn+2

```python
e2 = Equilibrium({'O2': 1, 'H2O': 2, 'e-': 4}, {'OH-': 4}, K2)
```

```python
e2
```

2 H2O + O2 + 4 e- ↔ 4 OH-

```python
coeff = Equilibrium.eliminate([e1, e2], 'e-')
```

```python
coeff
```

```python
redox
```

32 H+ + 4 MnO4- + 20 OH- ↔ 26 H2O + 4 Mn+2 + 5 O2

```python
autoprot
```

H2O ↔ H+ + OH-

```python
n
```

```python
from chempy import balance_stoichiometry
```

```python
reac, prod = balance_stoichiometry({'NaBO2', 'SiO2',"Na","H2"}, {'NaBH4', 'Na2SiO3'})
```

```python
>>> from pprint import pprint
>>> pprint(dict(reac))
>>> pprint(dict(prod))
```

    {'H2': 2, 'Na': 4, 'NaBO2': 1, 'SiO2': 2}
    {'Na2SiO3': 2, 'NaBH4': 1}

```python
reac, prod = balance_stoichiometry({"As2O3","Zn","HCl"},{"As", "H2", "ZnCl2","H2O"})
```

```python
>>> from pprint import pprint
>>> pprint(dict(reac))
>>> pprint(dict(prod))
```

    {'As2O3': 1/3, 'HCl': 2*x1, 'Zn': x1}
    {'As': 2/3, 'H2': x1 - 1, 'H2O': 1, 'ZnCl2': x1}

```python

```

Chapter 14 Iterations and Comprehensions.ipynb


# Solving a one-asset HANK model in sequence space
In this notebook, we show how to

1. Calculate the GE of a HANK model and calibrate its steady state
2. Obtain transitional dynamics from MIT shocks using the sequence space Jacobian.
3. Simulate an economy hit by aggregate shocks using the BKM (2018) algorithm.

The model is a HA version of the textbook New Keynesian model. Technology is linear in labor, prices are sticky á la Rotemberg, and monetary policy follows a Taylor rule. For a detailed description of the model, please see Auclert et al. (2020): "Using the Sequence-Space Jacobian to Solve and Estimate Heterogeneous Agent Models". The basic building blokcs of the model are as follows:

$$
\textbf{H}_t(\textbf{Y}, Z) \equiv
\begin{pmatrix}
Y_t - Z_t L_t
\\
Y_t \left[1 - \frac{\mu}{\mu-1}\frac{1}{2\kappa} \log(1 + \pi_t)^2\right] - w_t L_t - d_t
\\
r_t B - \tau_t
\\
r^*_t + \phi \pi_t - i_t
\\
1 + r_t - \frac{1+i_{t-1}}{1+\pi_t}
\\
\kappa \left(\frac{w_t}{Z_t} - \frac{1}{\mu} \right)  + \frac{1}{1+r_{t+1}} \frac{Y_{t+1}}{Y_t} \log(1+\pi_{t+1}) - \log(1+\pi_t)
\\
\mathcal{A}_t(\{r_s, w_s, \tau_s, d_s\})  - B
\\
\mathcal{N}_t(\{r_s, w_s, \tau_s, d_s\}) - L_t
\end{pmatrix}
= \begin{pmatrix} 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0\end{pmatrix},
\qquad t = 0, 1, \dots
$$

where the endogenous variables are $\textbf{Y} = (Y, L, r, w, d, \pi, \tau, i)$ and the exogenous variables are $\textbf{Z}=(r^*, Z)$.

The asset demand and labor supply functions $\{\mathcal{A}, \mathcal{L}\}$ follow from the household block with Bellman equation

$$
\begin{align} \tag{HH}
V_t(e, a_{-}) = \max_{c, n, a} &\left\{\frac{c^{1-\sigma}}{1-\sigma} - \varphi \frac{n^{1+\nu}}{1+\nu} + \beta \sum_{e'}V_{t+1}(e', a) \mathcal{P}(e,e') \right\}
\\
c + a &= (1 + r_t)a_{-} + w_t e n - \tau_t \bar{\tau}(e) + d_t \bar{d}(e)
\\
a &\geq 0
\end{align}
$$

where $\bar\tau(e)$ and $\bar d(e)$ are skill-specific incidence rules for taxes and dividends.

To see the directed acyclic graph (DAG) that accompanies sequence-space models, please refer to the paper.

## Step 1: Solving for the steady-state using EGM

The main function "egm" will complete all the backward iterations we need when solving for the jacobian in the household block.

```julia
include("rowenhorst_tauchen.jl") # include discretization functions (make sure it is in your working directory)

using Parameters, Plots, LinearAlgebra, Interpolations, BenchmarkTools, Roots, QuantEcon

Household = @with_kw (apoints = 500, #asset grid
    amax = 150,  # asset max
    beta = 0.986, # discount factor
    alpha = 0.11, # capital share
    deprec = 0.025, # depreciation rate
    gamma = 2.0, # inverse elasticity of substitution
    bc = 0, # borrowing constraint (must be weakly negative)
    rho = 0.966,  # autocorr of income process
    uncond_sd = 0.5, # unconditional sd
    num_states = 7, # number of states for income process
    sd = sqrt(1-rho^2)*uncond_sd, # stand. dev. of deviation process
    mean = 0, # mean of income process
    transition_matrix = rowenhorst(mean, uncond_sd, rho, num_states)[1], # transition matrix
    stationary_dis = stationary_distributions(MarkovChain(transition_matrix))[1], # stationary dis of income process
    ygrid = rowenhorst(mean, uncond_sd, rho, num_states)[2], # grid for income process
    Amat = setgrids(bc, apoints, amax, num_states, ygrid)[1], # asset grid
    Ymat = setgrids(bc, apoints, amax, num_states, ygrid)[2], # income grid
    phi = 0.8, # disutility factor
    frisch = 2.0, # inverse frisch elasticity for labor supply
    mu = 1.2, # markup
    B_Y = 5.6, # liquid assets
    r = 0.005) # steady state interest rate)

function setgrids(bc, apoints, amax, num_states, ygrid)
    Amat = [i for i in range(bc, length = apoints, stop= amax), j in 1:num_states]
    Ymat = [j for i = 1:apoints, j in ygrid]
    return Amat, Ymat
end

function setunevengrids(bc, apoints, amax, num_states, ygrid; curve = 2)
    unevengrid = range(bc^(1/curve), stop = amax^(1/curve), length = apoints).^curve
    Amat = [i for i in unevengrid, j in 1:num_states]
    Ymat = [j for i = 1:apoints, j in ygrid]
    return Amat, Ymat
end

hh = Household()
```

    WARNING: using QuantEcon.tauchen in module Main conflicts with an existing identifier.

    (apoints = 500, amax = 150, beta = 0.986, alpha = 0.11, deprec = 0.025, gamma = 2.0, bc = 0, rho = 0.966, uncond_sd = 0.5, num_states = 7, sd = 0.12927103310486848, mean = 0, transition_matrix = [0.9022379843199956 0.09361981119088468 … 8.374316586000039e-9 2.4137569000000128e-11; 0.015603301865147443 0.9035872016735433 … 4.0355125541400147e-7 1.3957194310000061e-9; … ; 1.3957194310000061e-9 4.0355125541400147e-7 … 0.9035872016735433 0.015603301865147443; 2.4137569000000125e-11 8.374316586000037e-9 … 0.09361981119088467 0.9022379843199955], stationary_dis = [0.015624999999999997, 0.09375, 0.234375, 0.3125, 0.234375, 0.09375000000000001, 0.015625000000000003], ygrid = [0.2595291268380845, 0.390378674741505, 0.5872000247124883, 0.8832548787421952, 1.3285748433063689, 1.998416489677544, 3.005979291521312], Amat = [0.0 0.0 … 0.0 0.0; 0.30060120240480964 0.30060120240480964 … 0.30060120240480964 0.30060120240480964; … ; 149.6993987975952 149.6993987975952 … 149.6993987975952 149.6993987975952; 150.0 150.0 … 150.0 150.0], Ymat = [0.2595291268380845 0.390378674741505 … 1.998416489677544 3.005979291521312; 0.2595291268380845 0.390378674741505 … 1.998416489677544 3.005979291521312; … ; 0.2595291268380845 0.390378674741505 … 1.998416489677544 3.005979291521312; 0.2595291268380845 0.390378674741505 … 1.998416489677544 3.005979291521312], phi = 0.8, frisch = 2.0, mu = 1.2, B_Y = 5.6, r = 0.005)

```julia
function transfers(stationary_dis; div_rule, tax_rule, Div, Tax)
    div = Div / sum(stationary_dis .* div_rule) .* div_rule
    tax = Tax / sum(stationary_dis .* tax_rule) .* tax_rule
    T = div .- tax
    return T
end

```

    transfers (generic function with 1 method)

```julia
up(c,gamma) = c.^(-gamma)
invup(x,gamma) = x.^(-1/gamma)
vp(l, phi, frisch) = phi.*l.^frisch
invvp(x, phi, frisch) = (x./phi).^(1/frisch)

# euler equation to get current consumption given future interest rate and future consumption grid

function getc(gamma,beta,transition_matrix; rnext,cnext)
    upnext = beta.*(1+rnext).*up(cnext,gamma)*transition_matrix' # future marginal utility
    c = invup(upnext,gamma) # current consumption
    return c
end

# intratemporal foc to get labor given current consumption

function getl(c, y, gamma, phi, frisch, w)
    labor = invvp(w.*y.*(up(c, gamma)), phi, frisch)
    return labor
end

# obtain current assets given consumption today defined on asset grid tomorrow

function geta(Amat, Ymat, gamma, phi, frisch, T; r, w, c)
    return 1/(1+r).*(c.+Amat.-w.*Ymat.*getl(c, Ymat, gamma, phi, frisch, w) .- T)
end

# obtain aggregates

function getagg(; policyfun, dist)
    agg = reshape(policyfun, (length(dist),1))
    agg = sum(agg.*dist)
    return agg
end

```

    getagg (generic function with 1 method)

```julia
# Note: function takes both current and future interest rates as arguments.

function egm(hh; w, cnext, cbinding, r, rnext, T)
 """
    use endogenous grid method to obtain c_{t} and a_{t} given c_{t+1} 'cnext'

    #### Fields

    - 'hh': household tuple
    - 'w': wage rate
    - 'cnext': time t+1 consumption grid
    - 'cbinding': consumption grid when borrowing constraint binds
    - 'r': interest rate at time t
    - 'rnext': interest rate at time t+1

    #### Returns

    - 'c': time t consumption grid
    - 'anext': time t policy function
    - 'l': time t labor function
"""

@unpack gamma, beta, transition_matrix, stationary_dis, Amat, Ymat, num_states, phi, frisch, bc = hh

# current policy functions on future grid
c = getc(gamma, beta, transition_matrix; rnext=rnext, cnext=cnext)
a = geta(Amat, Ymat, gamma, phi, frisch, T; r=r, w=w, c=c)

cnonbinding = similar(Amat)

# get consumption policy function for current grid
for i = 1:num_states
    cnonbinding[:,i] = LinearInterpolation(a[:,i], c[:,i], extrapolation_bc = Line()).(Amat[:,i])
end

# update elements of consumption policy when borrowing constraint binds
# a[1,j] is the level of current assets that induces the borrowing constraint to bind exactly.
# Therefore, whenever current assets are below a[1,j], the borrowing constraint will be STRICTLY binding.
# Note that this uses the monotonicity of the policy rule.

for j = 1:num_states
   c[:,j] = (Amat[:,j] .> a[1,j]) .*cnonbinding[:,j] .+ (Amat[:,j] .<= a[1,j]).*cbinding[:,j]
end

l = getl(c, Ymat, gamma, phi, frisch, w)

# update saving policy function with new consumption function
anext = @. (1+r)*Amat + w*Ymat*l - c + T

return c, anext, l
end
```

    egm (generic function with 1 method)

```julia
function egm_iterate(hh; r, w, T, rnext, cnext)
    @unpack Amat, Ymat, bc, gamma, phi, frisch, num_states, apoints = hh

    function getcbinding(a, c, y, t)
        @. (1+r)*a + w*y*getl(c, y, gamma, phi, frisch, w) + t - bc - c
    end

    cbinding = similar(Amat)

    for j = 1:num_states
        for i = 1:apoints
            cbinding[i,j] = find_zero(c -> getcbinding(Amat[i,j], c, Ymat[i,j], T[1,j]), 1.0)
        end
    end

    c, anext, l = egm(hh; w=w, rnext=rnext, r=r, T = T, cnext=cnext, cbinding=cbinding)

    return c, anext, l
end

function hh_ss(hh; r, w, T, tol=1e-8, maxiter=1000)
    @unpack Amat, Ymat, bc, gamma, phi, frisch, num_states, apoints = hh

    cnext = @. (max(r,0))*Amat+Ymat*w + T # initial guess for policy function iteration

    # get consumption when borrowing constraint binds

    function getcbinding(a, c, y, t)
        @. (1+r)*a + w*y*getl(c, y, gamma, phi, frisch, w) + t - bc - c
    end

    cbinding = similar(Amat)

    for j = 1:num_states
        for i = 1:apoints
            cbinding[i,j] = find_zero(c -> getcbinding(Amat[i,j], c, Ymat[i,j], T[1,j]), 1.0)
        end
    end

    dist = 1
    counter = 0

    for i=1:maxiter
        c = egm(hh; w=w, rnext=r, r=r, T = T, cnext=cnext, cbinding=cbinding)[1]
        if norm(c-cnext,Inf)<tol
            println("policy function iteration successful!")
            return egm(hh; w=w, rnext=r, r=r, T = T, cnext=c, cbinding=cbinding)
        else
            cnext = c
        end
    end

    error("no policy function convergence!")

end
```

    hh_ss (generic function with 1 method)

```julia
function get_kernel(hh; policyfun)

"""
    get transition kernel for asset-income distribution using Young's method

    #### Fields

    - 'hh': household tuple
    - 'policyfun': savings function, array na x ny

    #### Returns

    - 'kernel': na*ny x na*ny array row-stochastic transition kernel

"""

@unpack apoints, Amat, num_states, Ymat, transition_matrix = hh

# construct transition matrix without labour stochasticity
Q = zeros(apoints, apoints, num_states)

# find which element to interpolate to
findnearest(A,t) = findmin(abs.(A.-t))[2]

# construct matrices to get neighboring indices
next = similar(Amat)
previous = similar(Amat)

for j = 1:num_states
    for k = 1:apoints
        ind = findnearest(Amat[:,j],policyfun[k,j])
            if policyfun[k,j] - Amat[ind,j] > 0
                previous[k,j] = Amat[ind,j]
                if ind == apoints
                    next[k,j] = Amat[ind,j]
                else
                next[k,j] = Amat[ind+1,j]
                end
            elseif policyfun[k,j] == Amat[ind,j]
                previous[k,j] = policyfun[k,j]
                next[k,j] = policyfun[k,]
            else
                next[k,j] = Amat[ind,j]
                if ind == 1
                    previous[k,j] = Amat[ind,j]
                else
                    previous[k,j] = Amat[ind-1,j]
                end
            end
    end
end

# construct transition matrix for assets.
# Q[i,j,k] is the probability of going to agrid[i] when current assets are agrid[j] and income is ygrid[k]
for k = 1:apoints
    for j = 1:num_states
        if next[k,j] == previous[k,j]
            Q[Amat[:,1].==previous[k,j],k,j] .= 1
        else
            Q[Amat[:,1].==previous[k,j],k,j] .= (next[k,j]-policyfun[k,j])./(next[k,j]-previous[k,j])
            Q[Amat[:,1].==next[k,j],k,j] .= 1 - (next[k,j]-policyfun[k,j])./(next[k,j]-previous[k,j])
        end
    end
end

# construct transition kernel by taking the kronecker product of assets and transition_matrix for income
kernel = zeros(apoints*num_states,apoints*num_states)

for j=1:num_states
    for i=1:num_states
        kernel[(i-1)*apoints+1:i*apoints,(j-1)*apoints+1:j*apoints]=Q[:,:,j].*transition_matrix[j,i];
    end
end

kernel = kernel'

return kernel
end
```

    get_kernel (generic function with 1 method)

```julia
function histogram_method(hh; kernel, tol=1e-8, maxiter=10000)
    #needs Markov transition kernel
    @unpack apoints, num_states = hh

    #initial guess for invariant distribution
    init = ones(apoints*num_states)
    init = init./sum(init)

    dist = 1
    counter = 0

    for i=1:maxiter
        initnext = (init'*kernel)'
        if norm(init-initnext,Inf) < tol
            println("distribution iteration successful!")
            return initnext
        else
            init = initnext
        end
    end

    error("distribution did not convergence!")
end
```

    histogram_method (generic function with 1 method)

```julia
function get_hh_agg(hh, r, w, T)
    @unpack beta, Ymat = hh

    c, anext, l = hh_ss(hh; r = r, w = w, T = T)

    kernel = get_kernel(hh; policyfun = anext) # get kernel
    invariant_distribution = histogram_method(hh; kernel = kernel) # get invariant distribution

    K = getagg(; policyfun = anext, dist = invariant_distribution) # get aggregate capital
    L = getagg(; policyfun = l.*Ymat, dist = invariant_distribution) # get aggregate labor
    return K, L
end

function get_hh_agg(hh; c, anext, l, dist)
    @unpack Ymat = hh

    K = getagg(; policyfun = anext, dist = dist) # get aggregate capital
    L = getagg(; policyfun = l.*Ymat, dist = dist) # get aggregate labor
    C = getagg(; policyfun = c, dist = dist)
    return C, K, L
end
```

    get_hh_agg (generic function with 2 methods)

```julia
function obtain_J(f, x, y; h = 1e-5)
    """Finds Jacobian f'(x) around y=f(x)"""

    nx = size(x)[1]
    ny = size(y)[1]
    J = zeros(ny, nx)

    for i = 1:nx
        dx = h * (1:nx .== i)
        J[i, :] = (f(x .+ dx) .- y) ./ h
    end
    return J
end

function newton_solver(f, x, y; tol = 1e-6, maxcount = 100)
    for count=1:maxcount
        J = obtain_J(f, x, y)

        if maximum(abs.(y)) < tol
            return x, y
        end

        dx = J\(-y)
        print(dx)
        y = f(x + dx)
        x = x + dx
        print(y)
    end
    error("no convergence in newton solver")
end
```

    newton_solver (generic function with 1 method)

## Step 2: Calibrating the Steady-State

We use a Newton method to calibrate the equilibrium bond holdings and equilibrium output in steady-state. This will generally be faster than ad hoc methods that use a variant of the bisection method.

```julia
function calibrate_ss!(hh; mu = 1.2, r = 0.005, B_Y = 5.6)
    div_rule = hh.ygrid
    tax_rule = hh.ygrid

    # solve analytically what we can
    B = B_Y
    w = 1 / mu
    Div = (1 - w)
    Tax = r * B
    T = transfers(hh.stationary_dis; div_rule, tax_rule, Div, Tax)'

    x = [0.982041, 0.786046] # guess for beta and phi
    temp_hh = merge(hh, (beta = x[1], phi = x[2]))
    y = [get_hh_agg(temp_hh, r, w, T)[1] - B; get_hh_agg(temp_hh, r, w, T)[2] - 1]

    function residual(x)
       temp_hh = merge(hh, (beta = x[1], phi = x[2]))
       return [get_hh_agg(temp_hh, r, w, T)[1] - B; get_hh_agg(temp_hh, r, w, T)[2] - 1]
    end

    result = newton_solver(residual, x, y)[1]

    hh = merge(hh, (beta = result[1], phi = result[2]))

    print(get_hh_agg(hh, r, w, T)[1])

    return hh
end

hh = calibrate_ss!(hh)

```

    policy function iteration successful!
    distribution iteration successful!
    policy function iteration successful!
    distribution iteration successful!
    policy function iteration successful!
    distribution iteration successful!
    policy function iteration successful!
    distribution iteration successful!
    policy function iteration successful!
    distribution iteration successful!
    policy function iteration successful!
    distribution iteration successful!
    [5.3694764568422214e-8, 3.805314917027781e-7]policy function iteration successful!
    distribution iteration successful!
    policy function iteration successful!
    distribution iteration successful!
    [-3.194463200628661e-7, 4.122591401589659e-8]policy function iteration successful!
    distribution iteration successful!
    policy function iteration successful!
    distribution iteration successful!
    policy function iteration successful!
    distribution iteration successful!
    policy function iteration successful!
    distribution iteration successful!
    policy function iteration successful!
    distribution iteration successful!
    5.59999968055368

    (apoints = 500, amax = 150, beta = 0.9820410536947646, alpha = 0.11, deprec = 0.025, gamma = 2.0, bc = 0, rho = 0.966, uncond_sd = 0.5, num_states = 7, sd = 0.12927103310486848, mean = 0, transition_matrix = [0.9022379843199956 0.09361981119088468 … 8.374316586000039e-9 2.4137569000000128e-11; 0.015603301865147443 0.9035872016735433 … 4.0355125541400147e-7 1.3957194310000061e-9; … ; 1.3957194310000061e-9 4.0355125541400147e-7 … 0.9035872016735433 0.015603301865147443; 2.4137569000000125e-11 8.374316586000037e-9 … 0.09361981119088467 0.9022379843199955], stationary_dis = [0.015624999999999997, 0.09375, 0.234375, 0.3125, 0.234375, 0.09375000000000001, 0.015625000000000003], ygrid = [0.2595291268380845, 0.390378674741505, 0.5872000247124883, 0.8832548787421952, 1.3285748433063689, 1.998416489677544, 3.005979291521312], Amat = [0.0 0.0 … 0.0 0.0; 0.30060120240480964 0.30060120240480964 … 0.30060120240480964 0.30060120240480964; … ; 149.6993987975952 149.6993987975952 … 149.6993987975952 149.6993987975952; 150.0 150.0 … 150.0 150.0], Ymat = [0.2595291268380845 0.390378674741505 … 1.998416489677544 3.005979291521312; 0.2595291268380845 0.390378674741505 … 1.998416489677544 3.005979291521312; … ; 0.2595291268380845 0.390378674741505 … 1.998416489677544 3.005979291521312; 0.2595291268380845 0.390378674741505 … 1.998416489677544 3.005979291521312], phi = 0.7860463805314917, frisch = 2.0, mu = 1.2, B_Y = 5.6, r = 0.005)

## Step 3: Getting the household block jacobian.

The following set of functions calculate the jacobians of the "outputs" of the household block with respect to certain inputs. This is the most time consuming part of the sequence-space jacobian approach. The code utilizes the **fake news** algorithm, which significantly speeds up the calculation of the jacobians. Please read the paper to obtain familiarity with some of the terminology used in the code.

```julia
#getting jacobian with respect to r

function get_dYr(hh; horizon, diff, css, dist)

    @unpack B_Y, mu, r, Amat = hh

    div_rule = hh.ygrid
    tax_rule = hh.ygrid

    # solve analytically what we can
    B = B_Y
    w = 1 / mu
    Div = (1 - w)
    Tax = r * B
    T = transfers(hh.stationary_dis; div_rule, tax_rule, Div, Tax)'

    r_up = r + diff
    r_down = r - diff

#vector that holds aggregate differences

dK = zeros(horizon)
dL = zeros(horizon)
dC = zeros(horizon)

# vector of one-dimensional vectors (must be column vectors!) to hold change in distributions

dD = zeros(length(Amat),horizon)

#first upward iteration
cup, aup, lup = egm_iterate(hh; r = r_up, w = w, T = T, rnext = r, cnext = css)

Λ_up = get_kernel(hh; policyfun = aup) #get transition function (up)

#first downward iteration
cdown, adown, ldown = egm_iterate(hh; r = r_down, w = w, T = T, rnext = r , cnext = css)

Λ_down = get_kernel(hh, policyfun = adown) #get transition function (down)

#get capital and consumption

dC[1], dK[1], dL[1] = get_hh_agg(hh; c = (cup.-cdown)./2, anext = (aup.-adown)./2, l = (lup.-ldown)./2, dist = dist)

#get change in distribution
dD[:,1] = (dist'*((Λ_up .- Λ_down)./2))'

#second upward iteration
cup, aup, lup = egm_iterate(hh; r = r, w = w, T = T, rnext = r_up, cnext = cup)

Λ_up = get_kernel(hh; policyfun = aup) #get transition function (up)

#second downward iteration
cdown, adown, ldown = egm_iterate(hh; r = r, w = w, T = T, rnext = r_down, cnext = cdown)

Λ_down = get_kernel(hh; policyfun = adown) #get transition function (down)

#get capital and consumption
dC[2], dK[2], dL[2] = get_hh_agg(hh; c = (cup.-cdown)./2, anext = (aup.-adown)./2, l = (lup.-ldown)./2, dist = dist)

#change in distribution
dD[:,2] = (dist'*((Λ_up .- Λ_down)./2))'

for i=1:horizon-2
    #upward iteration
    cup, aup, lup = egm_iterate(hh; r = r, w = w, T = T, rnext = r, cnext = cup)
    Λ_up = get_kernel(hh; policyfun = aup)

    #downward iteration
    cdown, adown, ldown = egm_iterate(hh; r = r, w = w, T = T, rnext = r, cnext = cdown)
    Λ_down = get_kernel(hh; policyfun = adown) #get transition function (down)

    #get capital, consumption, and distribution
    dC[i+2], dK[i+2], dL[i+2] = get_hh_agg(hh; c = (cup.-cdown)./2, anext = (aup.-adown)./2, l = (lup.-ldown)./2, dist = dist)

    dD[:,i+2] = (dist'*((Λ_up .- Λ_down)./2))'
end

    return dK./diff, dC./diff, dL./diff, dD./diff

end

```

    get_dYr (generic function with 1 method)

```julia
# getting jacobian with respect to w

function get_dYw(hh; horizon, diff, css, dist)

    @unpack B_Y, mu, r, Amat = hh

    div_rule = hh.ygrid
    tax_rule = hh.ygrid

    # solve analytically what we can
    B = B_Y
    w = 1 / mu
    Div = (1 - w)
    Tax = r * B
    T = transfers(hh.stationary_dis; div_rule, tax_rule, Div, Tax)'

    w_up = w + diff
    w_down = w - diff

#vector that holds aggregate differences

dK = zeros(horizon)
dL = zeros(horizon)
dC = zeros(horizon)

# vector of one-dimensional vectors (must be column vectors!) to hold change in distributions

dD = zeros(length(Amat),horizon)

#first upward iteration
cup, aup, lup = egm_iterate(hh; r = r, w = w_up, T = T, rnext = r, cnext = css)

Λ_up = get_kernel(hh; policyfun = aup) #get transition function (up)

#first downward iteration
cdown, adown, ldown = egm_iterate(hh; r = r, w = w_down, T = T, rnext = r , cnext = css)

Λ_down = get_kernel(hh, policyfun = adown) #get transition function (down)

#get capital and consumption

dC[1], dK[1], dL[1] = get_hh_agg(hh; c = (cup.-cdown)./2, anext = (aup.-adown)./2, l = (lup.-ldown)./2, dist = dist)

#get change in distribution
dD[:,1] = (dist'*((Λ_up .- Λ_down)./2))'

for i=1:horizon-1
    #upward iteration
    cup, aup, lup = egm_iterate(hh; r = r, w = w, T = T, rnext = r, cnext = cup)
    Λ_up = get_kernel(hh; policyfun = aup)

    #downward iteration
    cdown, adown, ldown = egm_iterate(hh; r = r, w = w, T = T, rnext = r, cnext = cdown)
    Λ_down = get_kernel(hh; policyfun = adown) #get transition function (down)

    #get capital, consumption, and distribution
    dC[i+1], dK[i+1], dL[i+1] = get_hh_agg(hh; c = (cup.-cdown)./2, anext = (aup.-adown)./2, l = (lup.-ldown)./2, dist = dist)

    dD[:,i+1] = (dist'*((Λ_up .- Λ_down)./2))'
end

    return dK./diff, dC./diff, dL./diff, dD./diff

end

```

    get_dYw (generic function with 1 method)

```julia
# getting jacobian with respect to T

function get_dYT(hh; horizon, diff, css, dist)

    @unpack B_Y, mu, r, Amat = hh

    div_rule = hh.ygrid
    tax_rule = hh.ygrid

    # solve analytically what we can
    B = B_Y
    w = 1 / mu
    Div = (1 - w)
    Tax = r * B
    T = transfers(hh.stationary_dis; div_rule, tax_rule, Div, Tax)'

    T_up = T .+ diff
    T_down = T .- diff

#vector that holds aggregate differences

dK = zeros(horizon)
dL = zeros(horizon)
dC = zeros(horizon)

# vector of one-dimensional vectors (must be column vectors!) to hold change in distributions

dD = zeros(length(Amat),horizon)

#first upward iteration
cup, aup, lup = egm_iterate(hh; r = r, w = w, T = T_up, rnext = r, cnext = css)

Λ_up = get_kernel(hh; policyfun = aup) #get transition function (up)

#first downward iteration
cdown, adown, ldown = egm_iterate(hh; r = r, w = w, T = T_down, rnext = r , cnext = css)

Λ_down = get_kernel(hh, policyfun = adown) #get transition function (down)

#get capital and consumption

dC[1], dK[1], dL[1] = get_hh_agg(hh; c = (cup.-cdown)./2, anext = (aup.-adown)./2, l = (lup.-ldown)./2, dist = dist)

#get change in distribution
dD[:,1] = (dist'*((Λ_up .- Λ_down)./2))'

for i=1:horizon-1
    #upward iteration
    cup, aup, lup = egm_iterate(hh; r = r, w = w, T = T, rnext = r, cnext = cup)
    Λ_up = get_kernel(hh; policyfun = aup)

    #downward iteration
    cdown, adown, ldown = egm_iterate(hh; r = r, w = w, T = T, rnext = r, cnext = cdown)
    Λ_down = get_kernel(hh; policyfun = adown) #get transition function (down)

    #get capital, consumption, and distribution
    dC[i+1], dK[i+1], dL[i+1] = get_hh_agg(hh; c = (cup.-cdown)./2, anext = (aup.-adown)./2, l = (lup.-ldown)./2, dist = dist)

    dD[:,i+1] = (dist'*((Λ_up .- Λ_down)./2))'
end

    return dK./diff, dC./diff, dL./diff, dD./diff

end

```

    get_dYT (generic function with 1 method)

```julia
# getting jacobian with respect to w

function get_dYbeta(hh; horizon, diff, css, dist)

    @unpack B_Y, mu, r, Amat, beta = hh

    div_rule = hh.ygrid
    tax_rule = hh.ygrid

    # solve analytically what we can
    B = B_Y
    w = 1 / mu
    Div = (1 - w)
    Tax = r * B
    T = transfers(hh.stationary_dis; div_rule, tax_rule, Div, Tax)'

    beta_up = beta + diff
    beta_down = beta - diff

hh_temp = merge(hh, (beta = beta_up,))

#vector that holds aggregate differences

dK = zeros(horizon)
dL = zeros(horizon)
dC = zeros(horizon)

# vector of one-dimensional vectors (must be column vectors!) to hold change in distributions

dD = zeros(length(Amat),horizon)

#first upward iteration
cup, aup, lup = egm_iterate(hh_temp; r = r, w = w, T = T, rnext = r, cnext = css)

Λ_up = get_kernel(hh_temp; policyfun = aup) #get transition function (up)

#first downward iteration
hh_temp = merge(hh, (beta = beta_down,))
cdown, adown, ldown = egm_iterate(hh_temp; r = r, w = w, T = T, rnext = r , cnext = css)

Λ_down = get_kernel(hh_temp, policyfun = adown) #get transition function (down)

#get capital and consumption

dC[1], dK[1], dL[1] = get_hh_agg(hh; c = (cup.-cdown)./2, anext = (aup.-adown)./2, l = (lup.-ldown)./2, dist = dist)

#get change in distribution
dD[:,1] = (dist'*((Λ_up .- Λ_down)./2))'

for i=1:horizon-1
    #upward iteration
    cup, aup, lup = egm_iterate(hh; r = r, w = w, T = T, rnext = r, cnext = cup)
    Λ_up = get_kernel(hh; policyfun = aup)

    #downward iteration
    cdown, adown, ldown = egm_iterate(hh; r = r, w = w, T = T, rnext = r, cnext = cdown)
    Λ_down = get_kernel(hh; policyfun = adown) #get transition function (down)

    #get capital, consumption, and distribution
    dC[i+1], dK[i+1], dL[i+1] = get_hh_agg(hh; c = (cup.-cdown)./2, anext = (aup.-adown)./2, l = (lup.-ldown)./2, dist = dist)

    dD[:,i+1] = (dist'*((Λ_up .- Λ_down)./2))'
end

    return dK./diff, dC./diff, dL./diff, dD./diff

end

```

    get_dYbeta (generic function with 1 method)

### Expectation Vectors

```julia
function expect_vec(hh; policyfun, horizon, output)

    @unpack Amat = hh

    expv = zeros(length(Amat),horizon)

    trans= get_kernel(hh; policyfun = policyfun)
    vec = reshape(output, length(trans[:,1]))

    expv[:,1] = vec

    for i=2:horizon-1
       expv[:,i] = (trans)*expv[:,i-1]
    end

    return expv
end

function fake_news(;horizon, expv, dD, dY)
    #constructs fake news matrix
    #inputs
#         expv: vector of expectation vectors
#         dD: vector of change in distribution (vector of vectors again)
#         dY: changes in outputs, vector of floats

    F = zeros(horizon,horizon)

    for j=1:horizon
        for i=1:horizon
            if i == 1
                F[i,j] = dY[j]
            else
                F[i,j] = expv[:,i-1]'*dD[:,j]
            end
        end
    end

    return F
end

function get_jac(F)
    #constructs Jacobian
   J = copy(F)
    for j = 2:length(F[:,1])
        for i = 2:length(F[1,:])
            J[i,j] = J[i-1,j-1] + F[i,j]
        end
    end

    return J
end

function GET_JAC(hh; policyfun, output, horizon, dD, dY)
    expv = expect_vec(hh; policyfun = policyfun, horizon = horizon, output = output)
    F = fake_news(horizon = horizon, expv = expv, dD = dD, dY = dY)
    J = get_jac(F)
    return J
end
```

    GET_JAC (generic function with 1 method)

```julia
# steady-state objects

@unpack B_Y, mu, r, Amat = hh

div_rule = hh.ygrid
tax_rule = hh.ygrid

B = B_Y
w = 1 / mu
Div = (1 - w)
Tax = r * B
T = transfers(hh.stationary_dis; div_rule, tax_rule, Div, Tax)'

css, ass, lss = hh_ss(hh; r = r, w = w, T = T)

kernel = get_kernel(hh; policyfun = ass) # get kernel
dist = histogram_method(hh; kernel = kernel) # get invariant distribution

get_hh_agg(hh, c = css, anext = ass, l = lss, dist = dist)

```

    policy function iteration successful!
    distribution iteration successful!

    (1.000000580227425, 5.59999968055368, 1.000000041225914)

```julia
horizon = 200

# with respect to r

Kr, Cr, Lr, Dr = get_dYr(hh; horizon = horizon, diff = 1e-5, css = css, dist = dist)

JCR = GET_JAC(hh; policyfun = ass, output = css, horizon = horizon, dD = Dr, dY = Cr)
JKR = GET_JAC(hh; policyfun = ass, output = ass, horizon = horizon, dD = Dr, dY = Kr)
JLR = GET_JAC(hh; policyfun = ass, output = lss, horizon = horizon, dD = Dr, dY = Lr)

JCR
```

    200×200 Array{Float64,2}:
     0.0905729    -0.336314     -0.317593     …  -3.79598e-5  -3.61815e-5
     0.0889616     0.106135     -0.322076        -3.88087e-5  -3.69906e-5
     0.0872427     0.10372       0.119705        -3.97175e-5  -3.78569e-5
     0.0855583     0.101254      0.116661        -4.06884e-5  -3.87824e-5
     0.0839058     0.0988754     0.113602        -4.1724e-5   -3.97695e-5
     0.0822825     0.0965753     0.110662     …  -4.28268e-5  -4.08207e-5
     0.0806867     0.0943469     0.107833        -4.39997e-5  -4.19388e-5
     0.0791168     0.0921845     0.105104        -4.52457e-5  -4.31266e-5
     0.0775717     0.0900833     0.102468        -4.65681e-5  -4.43871e-5
     0.0760505     0.0880397     0.0999196       -4.79701e-5  -4.57237e-5
     0.0745526     0.0860504     0.0974533    …  -4.94554e-5  -4.71396e-5
     0.073077      0.0841126     0.0950645       -5.10278e-5  -4.86384e-5
     0.0716232     0.0822235     0.0927492       -5.2691e-5   -5.0224e-5
     ⋮                                        ⋱
     0.000603436   0.000662502   0.000721603     -0.106821    -0.101857
     0.000585677   0.000643009   0.000700374     -0.112106    -0.106821
     0.00056844    0.000624088   0.000679769  …  -0.117739    -0.112106
     0.000551709   0.000605723   0.000659769     -0.123753    -0.117739
     0.000535471   0.000587898   0.000640357     -0.130182    -0.123753
     0.000519709   0.000570596   0.000621515     -0.13707     -0.130182
     0.000504411   0.000553804   0.000603226     -0.144467    -0.13707
     0.000489563   0.000537505   0.000585476  …  -0.152444    -0.144467
     0.000475152   0.000521685   0.000568246     -0.161096    -0.152444
     0.000461164   0.00050633    0.000551524     -0.170569    -0.161096
     0.000447588   0.000491427   0.000535293      0.266374    -0.170569
     0.000434412   0.000476962   0.000519539      0.258638     0.266374

```julia
# with respect to w

Kw, Cw, Lw, Dw = get_dYw(hh; horizon = horizon, diff = 1e-5, css = css, dist = dist)

JCW = GET_JAC(hh; policyfun = ass, output = css, horizon = horizon, dD = Dw, dY = Cw)
JKW = GET_JAC(hh; policyfun = ass, output = ass, horizon = horizon, dD = Dw, dY = Kw)
JLW = GET_JAC(hh; policyfun = ass, output = lss, horizon = horizon, dD = Dw, dY = Lw)

JLW
```

    200×200 Array{Float64,2}:
      0.473576    -0.0333122   -0.0307321   …  -3.99454e-6  -3.80749e-6
     -0.032455     0.476954    -0.0305028      -4.12696e-6  -3.93372e-6
     -0.0307726   -0.0294761    0.479488       -4.26706e-6  -4.06727e-6
     -0.029203    -0.0281331   -0.0271901      -4.41515e-6  -4.20845e-6
     -0.0277377   -0.0268526   -0.0260667      -4.57157e-6  -4.35757e-6
     -0.0263671   -0.0256346   -0.0249805   …  -4.73668e-6  -4.51498e-6
     -0.0250824   -0.0244764   -0.023934       -4.91086e-6  -4.68104e-6
     -0.0238763   -0.0233749   -0.0229271      -5.09452e-6  -4.85612e-6
     -0.0227433   -0.0223276   -0.0219594      -5.28806e-6  -5.04065e-6
     -0.0216785   -0.0213328   -0.0210306      -5.49196e-6  -5.23504e-6
     -0.020678    -0.0203888   -0.0201408   …  -5.70667e-6  -5.43974e-6
     -0.0197381   -0.0194945   -0.0192902      -5.93268e-6  -5.65524e-6
     -0.0188552   -0.0186482   -0.0184791      -6.17053e-6  -5.88201e-6
      ⋮                                     ⋱
     -9.45794e-5  -9.45947e-5  -9.47573e-5     -0.00856928  -0.00820278
     -9.18045e-5  -9.18196e-5  -9.19778e-5     -0.00895485  -0.00856928
     -8.91107e-5  -8.91257e-5  -8.92794e-5  …  -0.00935885  -0.00895485
     -8.64957e-5  -8.65104e-5  -8.66599e-5     -0.00978045  -0.00935885
     -8.39572e-5  -8.39716e-5  -8.4117e-5      -0.0102193   -0.00978045
     -8.14928e-5  -8.15071e-5  -8.16484e-5     -0.0106769   -0.0102193
     -7.91006e-5  -7.91146e-5  -7.92519e-5     -0.0111591   -0.0106769
     -7.67784e-5  -7.67921e-5  -7.69256e-5  …  -0.011681    -0.0111591
     -7.45241e-5  -7.45376e-5  -7.46673e-5     -0.0122752   -0.011681
     -7.23359e-5  -7.23491e-5  -7.24751e-5     -0.0130052   -0.0122752
     -7.02116e-5  -7.02246e-5  -7.03471e-5      0.496059    -0.0130052
     -6.81496e-5  -6.81623e-5  -6.82814e-5     -0.0115057    0.496059

```julia
# with respect to T and D

KD, CD, LD, DD = get_dYT(hh; horizon = horizon, diff = 1e-5, css = css, dist = dist)

JCD = GET_JAC(hh; policyfun = ass, output = css, horizon = horizon, dD = DD, dY = CD)
JKD = GET_JAC(hh; policyfun = ass, output = ass, horizon = horizon, dD = DD, dY = KD)
JLD = GET_JAC(hh; policyfun = ass, output = lss, horizon = horizon, dD = DD, dY = LD)

JCT = - JCD
JKT = - JKD
JLT = - JLD

JLD
```

    200×200 Array{Float64,2}:
     -0.124201    -0.0240272   -0.022453    …  -4.24248e-6  -4.04359e-6
     -0.0260373   -0.12087     -0.0212797      -4.38342e-6  -4.17793e-6
     -0.0244075   -0.0231502   -0.118425       -4.53257e-6  -4.32009e-6
     -0.0229035   -0.021893    -0.0209751      -4.69024e-6  -4.47039e-6
     -0.0215157   -0.0207024   -0.0199547      -4.8568e-6   -4.62915e-6
     -0.0202337   -0.0195792   -0.0189712   …  -5.03263e-6  -4.79675e-6
     -0.0190474   -0.0185213   -0.0180288      -5.21814e-6  -4.97359e-6
     -0.0179481   -0.0175257   -0.0171287      -5.41376e-6  -5.16006e-6
     -0.0169282   -0.0165894   -0.0162708      -5.61996e-6  -5.35661e-6
     -0.0159812   -0.0157095   -0.015455       -5.8372e-6   -5.56369e-6
     -0.0151014   -0.0148832   -0.0146805   …  -6.06599e-6  -5.7818e-6
     -0.0142832   -0.0141079   -0.0139469      -6.30687e-6  -6.01142e-6
     -0.0135218   -0.0133808   -0.0132532      -6.56039e-6  -6.2531e-6
      ⋮                                     ⋱
     -4.32467e-5  -4.30816e-5  -4.29346e-5     -0.005418    -0.0053616
     -4.19781e-5  -4.18178e-5  -4.16752e-5     -0.00545791  -0.005418
     -4.07466e-5  -4.0591e-5   -4.04526e-5  …  -0.00547555  -0.00545791
     -3.95511e-5  -3.94001e-5  -3.92658e-5     -0.00546404  -0.00547555
     -3.83907e-5  -3.82442e-5  -3.81138e-5     -0.00541593  -0.00546404
     -3.72643e-5  -3.71221e-5  -3.69955e-5     -0.00532433  -0.00541593
     -3.61709e-5  -3.60328e-5  -3.591e-5       -0.00518535  -0.00532433
     -3.51095e-5  -3.49755e-5  -3.48563e-5  …  -0.00500236  -0.00518534
     -3.40792e-5  -3.39491e-5  -3.38334e-5     -0.00479339  -0.00500236
     -3.30791e-5  -3.29529e-5  -3.28405e-5     -0.00460325  -0.00479339
     -3.21083e-5  -3.19858e-5  -3.18768e-5     -0.102697    -0.00460325
     -3.1166e-5   -3.1047e-5   -3.09412e-5     -0.00615388  -0.102697

```julia
# with respect to beta

KB, CB, LB, DB = get_dYbeta(hh; horizon = horizon, diff = 1e-5, css = css, dist = dist)

JCB = GET_JAC(hh; policyfun = ass, output = css, horizon = horizon, dD = DB, dY = CB)
JKB = GET_JAC(hh; policyfun = ass, output = ass, horizon = horizon, dD = DB, dY = KB)
JLB = GET_JAC(hh; policyfun = ass, output = lss, horizon = horizon, dD = DB, dY = LB)

JCB
```

    200×200 Array{Float64,2}:
     -0.43551     -0.41481      -0.395519     …  -5.15749e-5  -4.91575e-5
      0.0189147   -0.418056     -0.398623        -5.27295e-5  -5.02579e-5
      0.0180067    0.0356105    -0.402516        -5.39655e-5  -5.14361e-5
      0.0171606    0.0339847     0.0505317       -5.52862e-5  -5.26949e-5
      0.0163708    0.0324596     0.0483153       -5.66949e-5  -5.40375e-5
      0.0156318    0.0310268     0.0462258    …  -5.81951e-5  -5.54675e-5
      0.0149388    0.0296784     0.0442536       -5.97909e-5  -5.69886e-5
      0.0142878    0.0284076     0.0423897       -6.14864e-5  -5.86046e-5
      0.0136755    0.0272086     0.0406266       -6.32858e-5  -6.03197e-5
      0.0130989    0.0260765     0.0389576       -6.51938e-5  -6.21384e-5
      0.0125556    0.025007      0.0373773    …  -6.72153e-5  -6.40653e-5
      0.0120432    0.0239962     0.0358807       -6.93554e-5  -6.61052e-5
      0.0115597    0.0230405     0.0344629       -7.16196e-5  -6.82633e-5
      ⋮                                       ⋱
      5.71228e-5   0.000114239   0.000171415     -0.139583    -0.134085
      5.54452e-5   0.000110884   0.000166381     -0.145344    -0.139583
      5.38168e-5   0.000107628   0.000161494  …  -0.151383    -0.145344
      5.22361e-5   0.000104467   0.000156751     -0.15772     -0.151383
      5.07017e-5   0.000101398   0.000152147     -0.164375    -0.15772
      4.92124e-5   9.84197e-5    0.000147678     -0.171371    -0.164375
      4.77667e-5   9.55285e-5    0.00014334      -0.178733    -0.171371
      4.63634e-5   9.27221e-5    0.000139129  …  -0.186497    -0.178733
      4.50012e-5   8.99979e-5    0.000135041     -0.194711    -0.186497
      4.3679e-5    8.73537e-5    0.000131074     -0.203448    -0.194711
      4.23956e-5   8.47871e-5    0.000127223     -0.212829    -0.203448
      4.11499e-5   8.22957e-5    0.000123484      0.234873    -0.212829

## Step 4: Calculating the Jacobians with respect to all other blocks

In these relatively large models, it is very error-prone to calculate the Jacobians for each block by hand, "accumulate" them until the market clearing block, and then use the implicit function theorem. You'll be dealing with a lot of jacobians ($TxT$ matrices) -- one for each output and input for **every** block -- and you need to make sure to multiply them in the right order.

I suggest doing the computationally heavy parts in Julia (this will generally be calculating the jacobian of the household block) and then using Auclert et al.'s code to do the computationally simpler -- but tedious -- work of calculating the general equilibrium jacobians. This because they have automated the process of calculating jacobians for simple blocks, accumulating them, and then using the implicit function theorem.

To do this, save the dataframe from the household jacobian to a folder that has Auclert et al.'s code (i.e. fork https://github.com/shade-econ/sequence-jacobian). In HANK_supplement I demonstrate the steps you need to take to obtain the general equilibrium Jacobian. The dataframe df (from G.csv) contains this general equilibrium Jacobian matrix.

```julia
using DataFrames
using CSV

cd("C:\\Users\\gniko\\Documents\\GitHub\\sequence-jacobian2")

HH_J = DataFrame(CR = vec(JCR), CW = vec(JCW), CD = vec(JCD), CT = vec(JCT), CB = vec(JCB), AR = vec(JKR), AW = vec(JKW), AD = vec(JKD), AT = vec(JKT), AB = vec(JKB), NSR = vec(JLR), NSW = vec(JLW), NSD = vec(JLD), NST = vec(JLT), NSB = vec(JLB))

CSV.write("HH_J", HH_J)

```

    "HH_J"

```julia
cd("C:\\Users\\gniko\\Documents\\GitHub\\RA_HetAgents")

df = CSV.read("G.csv", DataFrame)

```

<table class="data-frame"><thead><tr><th></th><th>Column1</th><th>Yr</th><th>YZ</th><th>Ybeta</th><th>Cr</th><th>CZ</th><th>Cbeta</th></tr><tr><th></th><th>Int64</th><th>Float64</th><th>Float64</th><th>Float64</th><th>Float64</th><th>Float64</th><th>Float64</th></tr></thead><tbody><p>40,000 rows × 10 columns (omitted printing of 3 columns)</p><tr><th>1</th><td>0</td><td>-0.418298</td><td>0.115018</td><td>-0.435649</td><td>-0.418298</td><td>0.115018</td><td>-0.435649</td></tr><tr><th>2</th><td>1</td><td>-0.334406</td><td>0.13672</td><td>0.0937662</td><td>-0.334647</td><td>0.136836</td><td>0.0940777</td></tr><tr><th>3</th><td>2</td><td>0.0998297</td><td>-0.0385457</td><td>-0.0265739</td><td>0.0767919</td><td>-0.0293145</td><td>-0.0200105</td></tr><tr><th>4</th><td>3</td><td>0.00267746</td><td>0.000634841</td><td>0.00032494</td><td>-0.0136529</td><td>0.00710194</td><td>0.00498396</td></tr><tr><th>5</th><td>4</td><td>0.0224178</td><td>-0.00738307</td><td>-0.00518194</td><td>0.00624581</td><td>-0.00101411</td><td>-0.000596839</td></tr><tr><th>6</th><td>5</td><td>0.0165116</td><td>-0.0050646</td><td>-0.00359129</td><td>0.0018628</td><td>0.000674037</td><td>0.000554456</td></tr><tr><th>7</th><td>6</td><td>0.0163118</td><td>-0.00506011</td><td>-0.00358886</td><td>0.00280547</td><td>0.000217137</td><td>0.000233511</td></tr><tr><th>8</th><td>7</td><td>0.014929</td><td>-0.00458563</td><td>-0.00326323</td><td>0.00256674</td><td>0.000241781</td><td>0.000243722</td></tr><tr><th>9</th><td>8</td><td>0.0138811</td><td>-0.00425089</td><td>-0.00303308</td><td>0.00258021</td><td>0.000169378</td><td>0.000187802</td></tr><tr><th>10</th><td>9</td><td>0.012836</td><td>-0.00391931</td><td>-0.00280467</td><td>0.00253249</td><td>0.000126242</td><td>0.000152455</td></tr><tr><th>11</th><td>10</td><td>0.0118672</td><td>-0.00361848</td><td>-0.00259698</td><td>0.00249369</td><td>8.37756e-5</td><td>0.00011801</td></tr><tr><th>12</th><td>11</td><td>0.0109581</td><td>-0.00333996</td><td>-0.00240424</td><td>0.00244911</td><td>4.7459e-5</td><td>8.81925e-5</td></tr><tr><th>13</th><td>12</td><td>0.0101111</td><td>-0.00308331</td><td>-0.00222618</td><td>0.00240253</td><td>1.53081e-5</td><td>6.15994e-5</td></tr><tr><th>14</th><td>13</td><td>0.0093234</td><td>-0.00284658</td><td>-0.0020615</td><td>0.00235352</td><td>-1.28973e-5</td><td>3.80464e-5</td></tr><tr><th>15</th><td>14</td><td>0.00859298</td><td>-0.00262841</td><td>-0.00190931</td><td>0.00230246</td><td>-3.76168e-5</td><td>1.71916e-5</td></tr><tr><th>16</th><td>15</td><td>0.00791718</td><td>-0.00242753</td><td>-0.00176878</td><td>0.00224947</td><td>-5.91426e-5</td><td>-1.18661e-6</td></tr><tr><th>17</th><td>16</td><td>0.00729312</td><td>-0.00224272</td><td>-0.00163911</td><td>0.00219474</td><td>-7.77596e-5</td><td>-1.73052e-5</td></tr><tr><th>18</th><td>17</td><td>0.00671771</td><td>-0.00207276</td><td>-0.00151952</td><td>0.00213845</td><td>-9.37501e-5</td><td>-3.13803e-5</td></tr><tr><th>19</th><td>18</td><td>0.00618772</td><td>-0.00191648</td><td>-0.00140923</td><td>0.00208081</td><td>-0.00010739</td><td>-4.36227e-5</td></tr><tr><th>20</th><td>19</td><td>0.00569991</td><td>-0.00177278</td><td>-0.00130751</td><td>0.00202208</td><td>-0.000118935</td><td>-5.42263e-5</td></tr><tr><th>21</th><td>20</td><td>0.00525109</td><td>-0.00164062</td><td>-0.00121367</td><td>0.00196249</td><td>-0.000128609</td><td>-6.33621e-5</td></tr><tr><th>22</th><td>21</td><td>0.00483818</td><td>-0.00151906</td><td>-0.00112711</td><td>0.00190231</td><td>-0.000136612</td><td>-7.11788e-5</td></tr><tr><th>23</th><td>22</td><td>0.00445827</td><td>-0.00140722</td><td>-0.00104724</td><td>0.00184178</td><td>-0.000143114</td><td>-7.78055e-5</td></tr><tr><th>24</th><td>23</td><td>0.0041086</td><td>-0.00130429</td><td>-0.000973513</td><td>0.00178113</td><td>-0.00014827</td><td>-8.33564e-5</td></tr><tr><th>25</th><td>24</td><td>0.00378662</td><td>-0.00120951</td><td>-0.000905439</td><td>0.00172059</td><td>-0.000152216</td><td>-8.79338e-5</td></tr><tr><th>26</th><td>25</td><td>0.00348996</td><td>-0.00112218</td><td>-0.000842544</td><td>0.00166038</td><td>-0.000155077</td><td>-9.16312e-5</td></tr><tr><th>27</th><td>26</td><td>0.00321645</td><td>-0.00104167</td><td>-0.000784395</td><td>0.00160071</td><td>-0.00015697</td><td>-9.45348e-5</td></tr><tr><th>28</th><td>27</td><td>0.00296411</td><td>-0.00096737</td><td>-0.000730587</td><td>0.00154176</td><td>-0.000158</td><td>-9.67246e-5</td></tr><tr><th>29</th><td>28</td><td>0.00273114</td><td>-0.000898741</td><td>-0.000680752</td><td>0.0014837</td><td>-0.000158266</td><td>-9.82754e-5</td></tr><tr><th>30</th><td>29</td><td>0.00251591</td><td>-0.000835287</td><td>-0.00063455</td><td>0.00142667</td><td>-0.000157862</td><td>-9.92572e-5</td></tr><tr><th>⋮</th><td>⋮</td><td>⋮</td><td>⋮</td><td>⋮</td><td>⋮</td><td>⋮</td><td>⋮</td></tr></tbody></table>

## Step 5: Impulse Response Functions

```julia
pir = reshape(df[!,"pir"], (horizon, horizon))

rho = 0.7

drstar = -0.0025 * rho.^(0:horizon-1)

plot(10000 .* (pir*drstar)[1:20], legend = false)
title!("inflation response to 25 bp monetary policy shock")
xlabel!("quarters")
ylabel!("basis point (bp) deviation from ss")
```

```julia
Yr = reshape(df[!,"Yr"], (horizon, horizon))

rho = 0.7

drstar = -0.0025 * rho.^(0:horizon-1)

plot(10000 .* (Yr*drstar)[1:20], legend = false)
title!("output response to 25 bp monetary policy shock")
xlabel!("quarters")
ylabel!("basis point (bp) deviation from ss")
```

```julia
CZ = reshape(df[!,"CZ"], (horizon, horizon))

rho = 0.7

dZ = -0.01 * rho.^(0:horizon-1)

plot(100 .* (CZ*dZ)[1:20], legend = false)
title!("consumption response to 1pp productivity shock")
xlabel!("quarters")
ylabel!("pp deviation from ss")
```

```julia
Cbeta = reshape(df[!,"Cbeta"], (horizon, horizon))

rho = 0.8

dbeta = 0.01 * rho.^(0:horizon-1)

plot(100 .* (Cbeta*dbeta)[1:20], legend = false)
title!("consumption response to 1pp shock to discount factor")
xlabel!("quarters")
ylabel!("pp deviation from ss")
```

## Step 6: Simulating an economy with the BKM algorithm

Finally, we can use the BKM algorithm to simulate an economy hit by aggregate shocks. The simulation will be accurate as long as the aggregate shocks are small, or the model is "sufficiently" linear (not financial accelerator models, for example).

We can use these simulations to calculate standard deviations of various variables of interest, as well as cross-correlations. This is observable data that can be used to calibrate certain parameters (such as the standard deviations of the driving productivity process, or the persistence of the discount factor shock).

```julia
# BKM

using Distributions

YZ = reshape(df[!,"YZ"], (horizon, horizon))
rho = 0.7
dZ = rho.^(0:horizon-1)
Z_irf = YZ*dZ

Ybeta = reshape(df[!,"Ybeta"], (horizon, horizon))
rho = 0.7
dbeta = rho.^(0:horizon-1)
beta_irf = Ybeta*dbeta

sigma_z = 0.5
sigma_beta = 0.1

sz = Normal(0,sigma_z)
sb = Normal(0, sigma_beta)

t_shocks = horizon

z_shocks = zeros(t_shocks)
b_shocks = zeros(t_shocks)

z_shocks[1] = rand(sz)
b_shocks[1] = rand(sb)

for i = 2:t_shocks
    z_shocks[i] = rho*z_shocks[i-1] + rand(sz)
    b_shocks[i] = rho*b_shocks[i-1] + rand(sb)
end

output = zeros(t_shocks)

for i=1:t_shocks
    for k=1:i
        output[i]+=Z_irf[k]*z_shocks[i-k+1]
    end
    for k=1:i
        output[i]+=beta_irf[k]*b_shocks[i-k+1]
    end
end

plot(output)
title!("output with productivity and discount factor shocks (BKM)" , legend = false)
xlabel!("quarters")
ylabel!("pp deviation from steady state")

```


# Lineární advekce

Nechť $a \in \mathbb R$ a $u \in \mathbb C^1( \mathbb R^2 \to \mathbb R)$. Potom rovnici
\begin{equation}
  \frac{\partial u(x,t)}{\partial t} + a \frac{\partial u(x,t)}{\partial x} = 0
\end{equation}
nazveme **rovnicí lineární advekce**.

## Počáteční úloha pro rovnici lineární advekce

Nechť $a \in \mathbb R$ a $u_0 \in \mathbb C^1(\mathbb R \to \mathbb R)$. **Počáteční úlohou** pro rovnici advekce pak rozumíme nalézt funkci $u \in \mathbb C^1( \mathbb R\times [0,+\infty) \to \mathbb R)$ takovou, že $\forall x \in \mathbb R, \forall t>0$ je splněna rovnice
\begin{equation}
  \frac{\partial u(x,t)}{\partial t} + a \frac{\partial u(x,t)}{\partial x} = 0
\end{equation}
a navíc je $u(x,0)=u_0(x)$.

### Analytické řešení počáteční úlohy
Analytické řešení je možné získat například pomocí metody charakteristik. Uvažujme v rovině $x-t$ nějakou křivku $x = \xi(t)$. Potom
$$
\frac{d u(\xi(t),t)}{t} = \frac{\partial u}{\partial x} \frac{d\xi}{dt} + \frac{\partial u}{\partial t}
$$
a tedy pokud $d\xi/dt = a$, je $du(\xi(t),t)/dt=0$ a $u$ je na této křivce konstantní.
Křivky splňující rovnici $d\xi/dt=a$ nazýváme **charakteristikami rovnice advekce**.
Charakteristiky jsou polopřímky $x = x_0 + a t$ a analytické řešení počáteční úlohy je
$$
    u(x,t) = u_0(x-at).
$$

### Numerické řešení počáteční úlohy pro rovnici advekce metodou sítí

```julia
using PyPlot
```

```julia
Nx = 26;                   # Pocet bodu site na intervalu [0,1]

x = range(0, stop=1, length=Nx);      # Souradnice bodu site

function u0(x)             # Definice pocatecni podminky"""
    if x<0.25 || x>0.75
        return 0
    else
        return cos( 2*(2*x-1.0) * π ) + 1
    end
end;
```

```julia
plot(x,[u0(xi) for xi in x], label="u0");
ylim(-0.5,2.5); grid(true); xlabel("x"); ylabel("u");
legend(loc="upper left");
```

**Protiproudové (upwind) schéma**

```julia
a = 1;                  # Rychlost advekce

dx = 1.0 / (Nx-1);      # Velikost prostoroveho
dt = 0.5 * dx / abs(a)  # Velikost casoveho kroku

u    = [u0(xi) for xi in x]

uNew = copy(u)

t = 0

pocet_iteraci = round(Int, 0.2 / dt) # Vypocet provedeme do casu priblizne 0.2

for n = 1:pocet_iteraci
    global t += dt

    for i=2:Nx
        uNew[i] = u[i] - a * dt / dx * (u[i] - u[i-1])
    end

    for i=2:Nx
        u[i] = uNew[i]
    end
end

u_upwind = copy(u);
```

```julia
plot(x, [u0(xi) for xi in x], label="u0")
plot(x,u, "o", label="u[i]");
plot(x, [u0(xi-a*t) for xi in x], "-r", label="presne")
ylim(-0.5,2.5); grid(true); xlabel("x"); ylabel("u"); legend(loc="upper left");
```

**Laxovo-Friedrichsovo (Rusanovovo) schéma**

```julia
u    = [u0(xi) for xi in x]
uNew = copy(u)

t = 0

for n = 1:pocet_iteraci

    global t += dt

    for i = 2:Nx-1
        uNew[i] = (u[i+1]+u[i-1])/2.0  - a * dt / (2*dx) * (u[i+1] - u[i-1])
    end

    for i = 2:Nx-1
        u[i] = uNew[i]
    end
end

u_lf = copy(u);
```

```julia
plot(x, [u0(xi) for xi in x], label="u0")
plot(x,u_lf, "o", label="u[i]");
plot(x, [u0(xi-a*t) for xi in x], "-r", label="presne")
ylim(-0.5,2.5); grid(true); xlabel("x"); ylabel("u"); legend(loc="upper left");
```

**Laxovo-Wendroffovo schéma**

```julia
u    = [u0(xi) for xi in x]
uNew = copy(u)

t = 0

pocet_iteraci = round(Int, 0.2 / dt) # Vypocet provedeme do casu priblizne 0.2

for n = 1:pocet_iteraci

    global t += dt

    for i = 2:Nx-1
        uNew[i] = u[i] - a * dt / (2*dx) * (u[i+1] - u[i-1]) + (a*dt/dx)^2/2 * (u[i+1]-2*u[i]+u[i-1])
    end

    for i = 2:Nx-1
        u[i] = uNew[i]
    end

end

u_lw = copy(u);
```

```julia
plot(x, [u0(xi) for xi in x], label="u0")
plot(x,u, "o", label="u[i]");
plot(x, [u0(xi-a*t) for xi in x], "-r", label="presne")
ylim(-0.5,2.5); grid(true); xlabel("x"); ylabel("u"); legend(loc="upper left");
```

```julia

```