#!/usr/bin/env python3
"""
Markov Module
"""
import numpy as np

def viterbi(Observation, Emission, Transition, Initial):
    """
    Calculates the most likely sequence of hidden states for a hidden markov
    model:

    Observation is a numpy.ndarray of shape (T,) that contains the index of
    the observation
        T is the number of observations
    Emission is a numpy.ndarray of shape (N, M) containing the emission
    probability of a specific observation given a hidden state
        Emission[i, j] is the probability of observing j given the hidden
        state i
        N is the number of hidden states
        M is the number of all possible observations
    Transition is a 2D numpy.ndarray of shape (N, N) containing the transition
    probabilities
        Transition[i, j] is the probability of transitioning from the hidden
        state i to j
    Initial a numpy.ndarray of shape (N, 1) containing the probability of
    starting in a particular hidden state

    Returns: path, P, or None, None on failure
        path is the a list of length T containing the most likely sequence of
        hidden states
        P is the probability of obtaining the path sequence
    """
    if not isinstance(Observation, np.ndarray) or len(Observation.shape) != 1:
        return None, None
    if not isinstance(Emission, np.ndarray) or len(Emission.shape) != 2:
        return None, None
    if not isinstance(Transition, np.ndarray) or len(Transition.shape) != 2:
        return None, None
    if Transition.shape != (Emission.shape[0], Emission.shape[0]):
        return None, None
    if not isinstance(Initial, np.ndarray) or len(Initial.shape) != 2:
        return None, None
    if Initial.shape != (Emission.shape[0], 1):
        return None, None
    if not np.sum(Emission, axis=1).all():
        return None, None
    if not np.sum(Transition, axis=1).all():
        return None, None
    if not np.sum(Initial) == 1:
        return None, None

    F = np.zeros((Emission.shape[0], Observation.shape[0]))
    backpointer = np.zeros((Emission.shape[0], Observation.shape[0]))

    F[:, 0] = Initial.T * Emission[:, Observation[0]]
    backpointer[:, 0] = 0

    for t in range(1, Observation.shape[0]):
        for s in range(Emission.shape[0]):
            F[s, t] = np.max(F[:, t - 1] * Transition[:, s] *
                             Emission[s, Observation[t]])
            backpointer[s, t] = np.argmax(F[:, t - 1] * Transition[:, s] *
                                          Emission[s, Observation[t]])
    path = [0] * Observation.shape[0]
    path[-1] = np.argmax(F[:, Observation.shape[0] - 1])
    for t in range(Observation.shape[0] - 1, 0, -1):
        path[t - 1] = int(backpointer[path[t], t])
    P = np.max(F[:, -1])
    return path, P


import numpy as np
from timeit import default_timer as timer

def block(A, B, display = False):
    """
    Generates a block diagonal matrix of the form [[A,0], [0,B]] using
    vector/matrix functions and indexing.
    """

    # Create matrix according to sizes of A and B
    C = np.zeros((A.shape[0] + B.shape[0], A.shape[1] + B.shape[1]))

    # Put matrix A into upper left using slicing
    C[:A.shape[0], :A.shape[1]] = A

    # Put matrix B into the middle using slicing
    C[A.shape[0]:, A.shape[1]:] = B

    if display:
        print(C)

    return C

def block_loops(A, B, display = False):
    """
    Generates a block diagonal matrix of the form [[A,0], [0,B]] using loops.
    """

    # Create matrix according to sizes of A and B
    C = np.zeros((A.shape[0] + B.shape[0], A.shape[1] + B.shape[1]))

    # Put matrix A into upper left using loops
    for clm in range(A.shape[1]):
        for row in range(A.shape[0]):
            C[row, clm] = A[row, clm]

    # Put matrix B into the middle using loops
    for clm in range(B.shape[1]):
        for row in range(B.shape[0]):
            C[A.shape[0]+row, A.shape[1]+clm] = B[row,clm]

    if display:
        print(C)

    return C

def main():
    # Small Test: generate block matrices
    print("### Test block generation ###")
    A = np.array([[1,2], [3,4]])
    B = np.array([[1,2,3], [4,5,6]])
    print("Are equal?", np.array_equal(block(A, B, True), block_loops(A, B, True)))

    #---------------------------------------------------------
    print("### Test performance ###")
    # Generate large random matrices
    A = np.random.randint(low=0, high=100, size=(1000,2000))
    B = np.random.randint(low=0, high=100, size=(4400,3300))

    # Method 1: using slicing
    tic = timer()
    block(A, B)
    toc = timer()
    print("Method #1: ", toc - tic, "s")

    # Method 2: using loops
    tic = timer()
    block_loops(A, B)
    toc = timer()
    print("Method #2: ", toc - tic, "s")

    """ Result (on my machine)
    Method #1:   0.1364385 s
    Method #2:  13.6611307 s

    Interpretation:
    It gets more apparent that the larger the matrices are the more effcient slicing is
    compared to just using loops.
    """

if __name__ == "__main__":
    main()


import matplotlib.pyplot as plt #pip3 install matplotlib
import numpy as np #pip3 install numpy
import random

pmf_arr=[0.11, 0.12, 0.09, 0.08, 0.12, 0.10, 0.09, 0.09, 0.10, 0.10]

def gen_acc_rej(num,c): # A function for generating the random values as per the accept reject mechanism
    X_ran=[]
    itr_for_x=[]
    for i in range(0,num):
        count=1
        while(1):
            u=random.uniform(0,1) # represents U ~ U[0,1]
            x=1+int(random.uniform(0,1)*10) #represents the X generated from g
            fx=pmf_arr[x-1]*10 # since we are taking f(x)/g(x) and g(x)=0.1
            if(u<=(fx/c)):
                itr_for_x.append(count)
                X_ran.append(x)
                break
            else:
                count=count+1
    return X_ran, itr_for_x

num=100000 # the number of variables generated
c_values=[2,3] # this represents the values of c that were used. (minimum value was 1.2)

for i in range(0,2):
    X, counts_iter= gen_acc_rej(num,c_values[i])

    print('For the values of n='+str(num)+' and c='+str(c_values[i])+' \nWe have the mean='+str(np.mean(counts_iter)))
    #plotting the probability versus discrete values
    # getting the frequency array corresponding to each discrete value
    freq, _ = np.histogram(X)

    # scaling frequency array so as to compare with the discrete probability distribution
    freq = freq/num
    x_axis = np.arange(1,11,1)
    plt.plot(x_axis, pmf_arr, label = 'Actual probability')
    plt.plot(x_axis, freq, label = 'Scaled frequency')

    plt.title('Generating discrete variables with \nn = {} and c = {}'.format(num,c_values[i]))
    plt.xlabel('Permissible Discrete Values')
    plt.ylabel('Probability')
    plt.legend(frameon = 0)

    plt.scatter(x_axis, freq, color = 'orange')
    # plt.savefig('q3_{}.png'.format(c))
    plt.show()

Semester 5/MA 323 (Monte Carlo)/Lab Submissions/Lab 3/180123062_ABSatyaprakash_q3.py


#!/usr/bin/env python

import os.path
import argparse
import math
import random
import numpy as np
import sympy as sp
import matplotlib.pyplot as plt

plt.rc('text', usetex=True)
plt.rc('font', family='serif')

import stats.methods as methods
from stats.utils import *

################
# Declarations #
################

SYM_X, SYM_Y = SYM_VALUES = sp.symbols('x y')
SYM_A, SYM_ALPHA = SYM_PARAMS = sp.symbols('a alpha')

# SYM_EXPR = sp.sympify('a * exp(-alpha*x)')
# SYM_EXPR_DELTA = sp.sympify('y - a * exp(-alpha*x)')

SYM_EXPR = sp.sympify('a * exp(alpha*x)')
SYM_EXPR_DELTA = sp.sympify('y - a * exp(alpha*x)')

# linear function
# SYM_EXPR = sp.sympify('a + alpha*x')
# SYM_EXPR_DELTA = sp.sympify('y - a - alpha*x')

# quadratic function
# SYM_EXPR = sp.sympify('a*(x**2) + alpha*x')
# SYM_EXPR_DELTA = sp.sympify('y - a*(x**2) - alpha*x')

# logarithmic function
# SYM_EXPR = sp.sympify('a + alpha*log(x)')
# SYM_EXPR_DELTA = sp.sympify('y - a - alpha*log(x)')

# sinusoidal function
# SYM_EXPR = sp.sympify('a + alpha*sin(x)')
# SYM_EXPR_DELTA = sp.sympify('y - (a + alpha*sin(x))')

MIN_X = 0
MAX_X = 10
NUM_VALS = 20              # number of source values

REAL_A = 31                # real 'a' value of source distribution
REAL_ALPHA = 0.5           # real 'alpha' value of source distiribution

ERR_X_AVG = 0              # average of X error values
ERR_X_STD = 0.02              # std of X error values

ERR_Y_AVG = 0              # average of Y error values
ERR_Y_STD = 7              # std of Y error values

NUM_ITER = 10              # number of realizations

MNK_NUM_ITER = 1             # number of MNK iterations

################
# Program code #
################

DESCRIPTION = 'Use this script to determine estimates accuracy'
parser = argparse.ArgumentParser(description=DESCRIPTION)
parser.add_argument('-w', '--write-to', metavar='PATH',
                    type=str, help='file to write plot in')

# parse cli options
args = parser.parse_args()

# real X values without errors
real_x = np.linspace(MIN_X, MAX_X, NUM_VALS, dtype=np.float)

# real Y values without errors
real_y = np.vectorize(
    sp.lambdify(
        SYM_X,
        SYM_EXPR.subs({SYM_A: REAL_A, SYM_ALPHA: REAL_ALPHA}),
        'numpy'
    )
)(real_x)

print('Expression:    {}'.format(SYM_EXPR))
print('Real A:        {}'.format(REAL_A))
print('Real ALPHA:    {}'.format(REAL_ALPHA))
print('Error X std:   {}'.format(ERR_X_STD))
print('Error Y std:   {}'.format(ERR_Y_STD))
print('Number of iterations: {}'.format(NUM_ITER))
print('-' * 40, '\n')

# plot real parameters
plt.figure(0)
plt.plot(REAL_A, REAL_ALPHA,
         color='m', linestyle=' ',
         marker='x', markersize=10,
         mfc='r')

# current accuracies for this stds
cur_basic_acc = 0
cur_mnk_acc = 0
cur_mrt_acc = 0

# iterate by error standart derivation values
for iter_i in range(NUM_ITER):
    print('Iteration #{}:'.format(iter_i + 1))

    # add X errors with current normal distribution
    x = np.vectorize(
        lambda v: v + random.gauss(ERR_X_AVG, ERR_X_STD)
    )(real_x)

    half_len = len(x) / 2

    # add Y errors with current normal distribution
    y = np.vectorize(
        lambda v: v + random.gauss(ERR_Y_AVG, ERR_Y_STD)
    )(real_y)

    ################################
    # Base values for basic search #
    ################################

    # get base values as first pairs of values
    base_values_first = {
        SYM_X: [x[0], x[1]],
        SYM_Y: [y[0], y[1]]
    }

    # get base values as half-distant pairs of values
    base_values_half_dist = {
        SYM_X: [x[0], x[half_len]],
        SYM_Y: [y[0], y[half_len]]
    }

    # get base values as maximal distant pairs of values
    base_values_max_dist = {
        SYM_X: [x[0], x[-1]],
        SYM_Y: [y[0], y[-1]]
    }

    # get base values as averages of two half-length subgroups
    base_values_avg = {
        SYM_X: [avg(x[:half_len]), avg(x[half_len:])],
        SYM_Y: [avg(y[:half_len]), avg(y[half_len:])]
    }

    ################
    # Basic search #
    ################

    # find params with basic method
    basic_a, basic_alpha = methods.search_basic(
        delta_expression=SYM_EXPR_DELTA,
        parameters=(SYM_A, SYM_ALPHA),
        values=base_values_max_dist
    )

    print('Basic a:       {}'.format(basic_a))
    print('Basic alpha:   {}'.format(basic_alpha))

    # add distance between estimates and real values
    cur_basic_dst = (basic_a - REAL_A)**2 + (basic_alpha - REAL_ALPHA)**2
    cur_basic_acc += math.sqrt(cur_basic_dst)

    plt.figure(0)
    plt.plot(basic_a, basic_alpha,
             color='g', linestyle=' ',
             marker='.', markersize=10,
             mfc='g', label='values')

    ##############
    # MNK search #
    ##############

    # use basic estimates as init estimates for MNK
    for i, (mnk_a, mnk_alpha) in methods.search_mnk(
            expression=SYM_EXPR,
            parameters=(SYM_A, SYM_ALPHA),
            values={SYM_X: x},
            result_values={SYM_Y: y},
            init_estimates={SYM_A: basic_a, SYM_ALPHA: basic_alpha},
            num_iter=MNK_NUM_ITER
    ):
        mnk_y = np.vectorize(
            sp.lambdify(
                SYM_X,
                SYM_EXPR.subs({SYM_A: mnk_a,
                               SYM_ALPHA: mnk_alpha}),
                'numpy'
            )
        )(real_x)

        print('MNK({}) a:      {}'.format(i, mnk_a))
        print('MNK({}) alpha:  {}'.format(i, mnk_alpha))

    # add distance between estimates and real values
    cur_mnk_dst = (mnk_a - REAL_A)**2 + (mnk_alpha - REAL_ALPHA)**2
    cur_mnk_dst += math.sqrt(cur_mnk_dst)

    plt.figure(0)
    plt.plot(mnk_a, mnk_alpha,
             color='b', linestyle=' ',
             marker='.', markersize=10,
             mfc='b')

    #################
    # Mrt search #
    #################

    # find params with mrt method
    mrt_a, mrt_alpha = methods.search_mrt(
        delta_expression=SYM_EXPR_DELTA,
        parameters=(SYM_A, SYM_ALPHA),
        values={SYM_X: x, SYM_Y: y},
        err_stds={SYM_X: ERR_X_STD, SYM_Y: ERR_Y_STD}
    )

    print('MRT a:         {}'.format(mrt_a))
    print('MRT alpha:     {}'.format(mrt_alpha))

    # add distance between estimates and real values
    cur_mrt_dst = (mrt_a - REAL_A)**2 + (mrt_alpha - REAL_ALPHA)**2
    cur_mrt_acc += math.sqrt(cur_mrt_dst)

    plt.figure(0)
    plt.plot(mrt_a, mrt_alpha,
             color='r', linestyle=' ',
             marker='.', markersize=10,
             mfc='r')

    print('-' * 40, '\n')

print('Basic accuracy: {}'.format(cur_basic_acc))
print('MNK accuracy:   {}'.format(cur_mnk_acc))
print('MRT accuracy:   {}'.format(cur_mrt_acc))

plt.figure(0)
plt.xlabel('$ a $')
plt.ylabel('$ \\alpha $')
plt.grid(True)

if args.write_to:
    plt.savefig(args.write_to, dpi=100)

plt.show()


#Program to perform linear convolution
import numpy as np
import scipy as sy
from matplotlib import pyplot as plt
#impulse response
h = [1,2,3,3,2,1];
#input response
x = [1,2,3,4,5];
N1 = len(x)
N2 = len(h)
N = N1+N2-1
y = np.zeros(N)
#x = [[x],[np.zeros(N-N1)]]
#h = [h,np.zeros(N-N2)]
#Linear convolution using built-in function in NumPy
y1 = np.convolve(x,h)
m = N-N1
n = N-N2
#Padding zeros to x and h to make their length to N
x =np.pad(x,(0,m),'constant')
h =np.pad(h,(0,n),'constant')

#Linear convolution using convolution sum formula
for n in range (N):
    for k in range (N):
        if n >= k:
             y[n] = y[n]+x[n-k]*h[k]

print('Linear convolution using convolution sum formula output response y =\n',y)
print('Linear convolution using NumPy built-in function output response y=\n',y1)

#RESULT
#Linear convolution using convolution sum formula output response y =
#[ 1.  4. 10. 19. 30. 36. 35. 26. 14.  5.]
#Linear convolution using NumPy built-in function output response y=
#[ 1  4 10 19 30 36 35 26 14  5]


#!/usr/bin/env python
"""
(C) 2016 Nikolay Manchev, London Machine Learning Study Group

http://www.meetup.com/London-Machine-Learning-Study-Group/

This work is licensed under the Creative Commons Attribution 4.0 International
License. To view a copy of this license, visit
http://creativecommons.org/licenses/by/4.0/.
"""

import numpy as np
import math

def split(dataset, attribute, value):
    """
    Split a dataset in two by value of an attribute

    Parameters
    ----------
    dataset    : dataset for the split
    attribute  : attribute to split on
    value      : threshold value for the split

    Returns
    -------
    a tuple containing the two splits
    """
    set_one = dataset[dataset[:, attribute] > value]
    set_two = dataset[dataset[:, attribute] <= value]
    return (set_one, set_two)

def count_distinct(dataset):
    """
    Gets a list of unique values in a dataset and computes the
    frequency of occurrence for each unique value.

    Parameters
    ----------
    dataset    : a list of values

    Returns
    -------
    a dictionary of unique values and their respective frequency
    of occurrence
    """
    counts = {}

    # Loop over all elements of the dataset
    for item in dataset:
        if (item in counts):
            # This value is already in the dictionary.
            # Increase its count.
            counts[item] = counts[item] + 1
        else:
            # This is the first occurrence of the word.
            # Add it to the dictionary and set its count to 1
            counts[item] = 1
    return counts

def entropy(dataset):
    """
    Computes the entropy for a dataset. The entropy is computed as

      H = sum_{i} p(x_i) log_2 p(x_i)

    The sum is taken over all unique values in the set. The
    probability p(x_i) is computed as

    p(x_i) = (frequency of occurrence of x_i) / (size of the dataset)

    Parameters
    ----------
    dataset    : a list of values

    Returns
    -------
    the entropy of the set
    """
    H = 0

    for freq in count_distinct(dataset).values():
        H += (-freq/len(dataset)) * math.log(freq/len(dataset), 2)

    return H

def show_split_entropy(dataset, attr_index, split_value):
    """
    Splits a dataset on attribute and prints the frequency of occurrence
    and the entropy for each split.

    Parameters
    ----------
    dataset     : a list of values
    attr_index  : index of an attribute to split on
    split_value : threshold value for the split

    """
    # Split the dataset in two subsets
    (x1, x2) = split(dataset,attr_index,split_value)

    # Print the frequencies and entropy for the first subset
    print("First split")
    print("**************")
    print("Value counts: ", count_distinct(x1[:,attr_index]))
    print("Entropy: ", entropy(x1[:,attr_index]), "\n")

    # Print the frequencies and entropy for the second subset
    print("Second split")
    print("**************")
    print("Value counts: ", count_distinct(x2[:,attr_index]))
    print("Entropy: ", entropy(x2[:,attr_index]))

# Load the data set
# We use a modified version of the Auto MPG from UCI Machine Learning
# Repository where the continuous MPG attribute has been converted to
# categorical as follows:
#
# [9;19) - BAD
# (9;26] - OK
# (26;47] - GOOD
#
# The original dataset is available at
# https://archive.ics.uci.edu/ml/datasets/Auto+MPG

car_data = np.genfromtxt("auto-mpg-modified.data", usecols = range(8))
car_data = car_data[~np.isnan(car_data).any(axis = 1)]

# Assign MPG to y and all other attributes to x
data   = car_data[:,1:]
labels = car_data[:,0]

# Set attribute names
attributes =   ["CYLYNDERS", "DISPLACEMENT", "HORSEPOWER", "WEIGHT", "ACCELERATION", "MODEL_YEAR", "ORIGIN"]
class_labels = ["BAD", "OK", "GOOD"]

# Look at the unique values for the MODEL_YEAR attribute
print("Unique values for MODEL_YEAR: ", count_distinct(data[:,5]), "\n")

# Split the dataset at the value 75
show_split_entropy(data, 5, 75)


"""
# !/usr/bin/env python
# -*- coding: utf-8 -*-
@Time        : 2022/2/28 20:27
@Author      : shengdl999links@gmail.com
@ProjectName : udacity-program_self_driving_car_engineer_v1.0_source.0
@File        : sobel_operator.py
"""

import cv2
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

img = mpimg.imread('curved-lane.jpeg')
# Use cv2.COLOR_RGB2GRAY if you've read in an image using mpimg.imread().
# Use cv2.COLOR_BGR2GRAY if you've read in an image using cv2.imread().
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

# Calculate the derivative in the xx direction (the 1, 0 at the end denotes xx direction):
sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0)

# Calculate the derivative in the yy direction (the 0, 1 at the end denotes yy direction):
sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1)

# Calculate the absolute value of the xx derivative:
abs_sobelx = np.absolute(sobelx)
abs_sobely = np.absolute(sobely)

# Convert the absolute value image to 8-bit:
scaled_sobel = np.uint8(255 * abs_sobelx/np.max(abs_sobelx))
scaled_sobel = np.uint8(255 * abs_sobely/np.max(abs_sobely))

thresh_min = 20
thresh_max = 100
sxbinary = np.zeros_like(scaled_sobel)
sxbinary[(scaled_sobel >= thresh_min) & (scaled_sobel <= thresh_max)] = 1
plt.imshow(sxbinary, cmap='gray')
plt.show()

def abs_sobel_thresh(img, orient='x', thresh_min=0, thresh_max=255):
    # Grayscale
    # Apply cv2.Sobel()
    # Take the absolute value of the output from cv2.Sobel()
    # Scale the result to an 8-bit range (0-255)
    # Apply lower and upper thresholds
    # Create binary_output
    # return binary_output
    pass

udacity-program_self_driving_car_engineer_v1.0/part01-computer vision and deep learning/module04-computer vision/lesson02-gradients and color spaces/sobel/sobel_operator.py