# Python Basic Programs

### 1. Complex Numbers
Write a function `rand_complex(n)` that returns a list of `n` random complex numbers uniformly distributed in the unit circle (i.e., the magnitudes of the numbers are all between 0 and 1). Give the function a docstring. Demonstrate the function by making a list of 25 complex numbers. 


```python
import numpy as np
import random as random
import matplotlib.pyplot as plt
def rand_complex (n):
  """To get random complex numbers uniformly distribued in the unit circle.
     Unit circle= A circle of unit radius, i.e. a radius of 1.
     Condition for unit circle: If (x,y) is a point on the circumference of the circle.
                                Then, (x^2+y^2=1). 

    Parameter n: Required number of complex numbers, type int.

    Returns m: An array of complex numbers within the unit circle.
  """
  m = []                          #Initializing an empty array
  for i in range(n):
    a = np.random.uniform(-1 , 1) #Get a random number between -1 & 1
    b = np.sqrt(1-a**2)           #Get a number that fulfills (a^2+b^2=1 or b=square-root of(1-a^2))
    br = np.random.uniform(-b , b)#Get a random number between -b & b
    z = complex (a , br)          #Forms complex number of the form (a + br j)
    m.append(z)                   #Append the array with complex numbers generated 
    plt.scatter(a , br)           #Plot the complex numbers
    circle=plt.Circle((0,0),1, fill= False)
    plt.gca().add_patch(circle)
  return m

rand_complex(25)
```

### 2. Hashes
Write a function `to_hash(L) `that takes a list of complex numbers `L` and returns an array of hashes of equal length, where each hash is of the form `{ "re": a, "im": b }`. Give the function a docstring and test it by converting a list of 25 numbers generated by your `rand_complex` function. 


```python
def to_hash(L):
  """Returns the hash or dictionary values of a list of complex numbers.

     Parameter L: List of complex numbers.

     Returns a: An array of hashes of equal length in the form {"re": a, "im": b}  
  """
  a = []                            #Initializing an empty array
  b = len(L)                        #Get the length of array list
  for i in range(b):  
    x = L[i].real                   #Stores real values of complex numbers
    y = L[i].imag                   #Stores imaginary values of complex numbers
    a.append({ "re": x, "im": y })  #Add all the real and imaginary parts to the array in the form of hashes
  return a

to_hash(rand_complex(25)) 
```

### 3. Matrices

Write a function `lower_traingular(n)` that returns an $n \times n$ numpy matrix with zeros on the upper diagonal, and ones on the diagonal and lower diagonal. For example, `lower_triangular(3)` would return

```python
array([[1, 0, 0],
       [1, 1, 0],
       [1, 1, 1]])
```


```python
import numpy as np
def lower_traingular(n):
  """Forms an nxn lower triangular matrix, with zeros above diagonal
     and ones on diagonal and below diagonal
  
     Parameter n: Dimension of resultant nxn matrix, type int.  

     Returns x: Desired lower triangular nxn matrix.
  """
  x = np.zeros((n , n))   #Forms a matrix of zeros of desired dimension
  for i in np.arange(n): 
    for j in np.arange(n):
      if (i>=j):          #Selecting diagonal and lower diagonal places
        x[i][j]=1         #Inputs 1 wherever the condition applies
  return x  
    
lower_traingular(3)
```




    array([[1., 0., 0.],
           [1., 1., 0.],
           [1., 1., 1.]])



### 4. Numpy

Write a function `convolve(M,K)` that takes an $n \times m$ matrix $M$ and a $3 \times 3$ matrix $K$ (called the kernel) and returns their convolution as in [this diagram](https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTYo2_VuAlQhfeEGJHva3WUlnSJLeE0ApYyjw&usqp=CAU).


Please do not use any predefined convolution functions from numpy or scipy. Write your own. If the matrix $M$ is too small, your function should return a exception.

You can read more about convolution in [this post](https://setosa.io/ev/image-kernels/).

The matrix returned will have two fewer rows and two fewer columns than $M$. Test your function by making a $100 \times 100$ matrix of zeros and ones that as an image look like the letter X and convolve it with the kernel

$$
K = \frac{1}{16} \begin{pmatrix}
1 & 2 & 1 \\
2 & 4 & 2 \\
1 & 2 & 1
\end{pmatrix}
$$

Use `imshow` to display both images using subplots. 


```python
import numpy as np
import matplotlib.pyplot as plt

#Take user inputs for image dimensions 
n = int(input("Enter no of rows for image: "))
m = int(input("Enter no of columns for image: "))

#To form an image in the form of X of desired dimensions
img = np.zeros((n , m))  
for i in range(n):
  for j in range(m):
    if (i==j or i+j==m-1):
      img[i][j] = 1

#Kernel provided for convolution
ker = (1/16)*np.array([[1, 2, 1], [2, 4, 2], [1, 2, 1]])
k = ker.shape[0]

#Defining dimensions of resultant image
#Dimensions 2 rows and columns lesser than given image (as kernel is 3x3) 
res = np.zeros(((n-k+1) , (m-k+1)))

#Perfom Convolution
def convolve(M , K):
  """Performs the convolution of a nxm image by a kernel of 3x3 and provides a resultant image.

     Parameters:
     M= nxm image on which convolution is to be performed.
     K= 3x3 kernel.

     Raises: Exception as dimensions of input image can not be less than kernel dimensions.   
  """
  if (img.shape[0]<ker.shape[0] or img.shape[1]<ker.shape[1]):
    raise Exception("Image dimensions less than kernel dimensions")
  else:
    for i in range(n-k+1):
      for j in range(m-k+1):
        res[i][j] = np.sum(ker * img[i:i+k,j:j+k])

convolve(img , ker)

#Plot the given image and resultant image
fig = plt.figure(figsize = (10,10))
fig.add_subplot(1, 2, 1)
plt.title("Image")
plt.imshow(img)
fig.add_subplot(1, 2, 2)
plt.title("Result")
plt.imshow(res)
```

### 5. Symbolic Manipulation

Use sympy to specify and solve the following equations for $x$.

- $x^2 + 2x - 1 = 0$ 
- $a x^2 + bx + c = 0$

Also, evaluate the following integrals using sympy

- $\int x^2 dx$
- $\int x e^{6x} dx$
- $\int (3t+5)\cos(\frac{t}{4}) dt$


```python
import math
from sympy import *
init_printing(use_latex='mathjax')
x = Symbol("x")
solve((x**2) + (2*x) - 1)
```




$\displaystyle \left[ -1 + \sqrt{2}, \  - \sqrt{2} - 1\right]$




```python
x, a, b, c = symbols("x a b c")
solve(a*(x**2) + b*x + c)
```




$\displaystyle \left[ \left\{ a : - \frac{b x + c}{x^{2}}\right\}\right]$




```python
expr = (x**2)*diff(x)
integrate (expr, x)
```




$\displaystyle \frac{x^{3}}{3}$




```python
expr = x*(exp(6*x))*diff(x)
integrate (expr, x)
```




$\displaystyle \frac{\left(6 x - 1\right) e^{6 x}}{36}$




```python
t = Symbol("t")
expr = (3*t+5)*cos(t/4)*diff(t)
integrate (expr, t)
```




$\displaystyle 12 t \sin{\left(\frac{t}{4} \right)} + 20 \sin{\left(\frac{t}{4} \right)} + 48 \cos{\left(\frac{t}{4} \right)}$



### 6. Typesetting

Use LaTeX to typeset the following equations.




#$$17\:Equations\:That\:Changed\:the\:World$$
##$$by\:Ian\:Stewart$$

###$1.\:Pythagoras's\: Theorem\hspace{3.5cm}\ a^2+b^2=c^2\hspace{6cm}$ Pythagoras,530 BC

###$2.\:Logarithms\hspace{6.5cm}\ logxy=log x+log y\hspace{4cm}$ John Napier, 1610

###$3.\:Calculus\hspace{7.5cm}\frac{df}{dt}=lim_{h\to 0}\frac{f(t+h)-f(t)}{h}\hspace{3.5cm}$ Newton, 1668

###$4.\:Law\: of\: Gravity\hspace{5.5cm}\ F=G\frac{m1m2}{r^2}\hspace{6.5cm}$ Newton, 1687

###$5.\:The\: Square\: Root\: of\: Minus\: One\hspace{1cm}\ i^2=-1\hspace{7.5cm}$ Euler, 1750

###$6.\:Euler's\: Formula\ for\:Polyhedra\hspace{1cm}\ V-E+F=2\hspace{5.5cm}$  Euler, 1751

###$7.\:Normal\:Distribution\hspace{4cm}\Phi(x)=\frac{1}{\sqrt{2\pi\rho}}e^\frac{(x-\mu)^2}{2\rho^2}\hspace{4.5cm}$ C.F.Gauss, 1810

###$8.\:Wave\:Equation\hspace{5.5cm}\frac{\delta^2u}{\delta t^2}=c^2\frac{\delta^2u}{\delta x^2}\hspace{6.5cm} $ J.d'Almbert, 1746

###$9.\:Fourier\:Transform\hspace{4cm}\ f(\omega)=\int_{-\infty}^\infty\ f(x)e^{-2\pi ix\omega}dx\hspace{2.5cm}$ J. Fourier, 1822

###$10.\:Navier-Stokes\: Equation\hspace{2cm}\rho(\frac{\delta v}{\delta t}+v.\nabla v)=-\nabla p+\nabla .T+f\hspace{1cm}$ C.Navier, G.Stokes, 1845

###$11.\:Maxwell's\:Equations\hspace{3.5cm}\nabla.E=0,\hspace{2.5cm}\nabla.H=0,\hspace{10.5cm}\nabla XE=-\frac{1}{c}\frac{\delta H}{\delta t},\hspace{1cm}\nabla XH=\frac{1}{c}\frac{\delta E}{\delta t} \hspace{0.5cm}$ J.C. Maxwell, 1865

###$12.\:Second\:Law\:of\:Thermodynamics\hspace{0.5cm} \ dS\geq 0 \hspace{7.5cm}$ L. Boltzmann, 1874

###$13.\:Relativity\hspace{7cm}\ E=mc^2\hspace{7cm}$ Einstein, 1905

###$14.\:Schrodinger's\:Equation\hspace{3cm}\ ih\frac{\delta}{\delta t}\Psi=H\Psi\hspace{6cm} $ E. Schrodinger, 1927

###$15.\:Information\:Theory\hspace{4cm}\ H=-\sum p(x)logp(x)\hspace{3.5cm}$ C. Shannon, 1949

###$16.\:Chaos\:Theory\hspace{6cm}\ x_{t+1}=kx_{t}(1-xt)\hspace{4.5cm}$ Robert May, 1975

###$17.\:Black-Scholes\:Equation\hspace{1.5cm}\frac{1}{2}\sigma^2 S^2\frac{\delta^2V}{\delta S^2}+rS\frac{\delta V}{\delta S}+\frac{\delta V}{\delta t}-rV=0\hspace{0.5cm}$ F. Black, M.Scholes, 1990



b9afb5912c2dca3bb18ccf0f9b34114b479e8a38
ipynb
Jupyter Notebook
Basic Python Programs/Python Basic Programs.ipynb
joy6543/Mathematics-and-Analytical-Methods
eea45c7ffd98c308254142903ef661c792fa3503
MIT
Basic Python Programs/Python Basic Programs.ipynb
joy6543/Mathematics-and-Analytical-Methods
eea45c7ffd98c308254142903ef661c792fa3503
MIT
Basic Python Programs/Python Basic Programs.ipynb
joy6543/Mathematics-and-Analytical-Methods
eea45c7ffd98c308254142903ef661c792fa3503
MIT
Qwen/Qwen-72B
1. YES
2. YES