'''
Created on 20-Jan-2022

@author: bthakur
'''

import inspect
import traceback
import random
import numpy as np
from sympy import (latex, Symbol, symbols,
                   )

from xv.util import toIntOrFloat, listAttr
from xv.km.storeddata import BaseStoredQuestions

# _matrix_stored_questions
# MatrixStoredQuestions

class MatrixStoredQuestions(BaseStoredQuestions):
    _QUESTION_KEYWORDS = None
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        pass
    
    def get_question_matrix_notation(self):
        
        keywords = [
            'matrix',
            'notation',
            'matrix notation',
            ]
        
        prob_s = rf"""
        Define an ${{m \times n}}$  matrix  in $\mathbb{{R}}^{{m \times n}}$ vector space where $\mathbb{{R}}$ is the set of real numbers.
        
        """
        
        soln_s = rf"""
        An ${{m \times n}}$  matrix  in $\mathbb{{R}}^{{m \times n}}$ vector space where $\mathbb{{R}}$ is the set of real numbers.
        
        $$
        A \in \mathbb{{R}}^{{m \times n}} \quad \Longleftrightarrow \quad A=\left(a_{{i j}}\right)=\left[\begin{{array}}{{ccc}}
        a_{{11}} & \cdots & a_{{1 n}} \\
        \vdots & & \vdots \\
        a_{{m 1}} & \cdots & a_{{m n}}
        \end{{array}}\right], \quad a_{{i j}} \in \mathbb{{R}}
        $$
        
        The elements of a matrix with are expressed as $a_{{i j}}$, $[A]_{{i j}}$ or $A(i, j)$.
        """
        
        answer_s = soln_s

        result = {
            'keywords': keywords,
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass
    

    def get_question_vector_space_notation(self):
        
        keywords = [
            'matrix',
            'vector space',
            ]
        
        prob_s = rf"""
        Define an $\mathbb{{R}}^{{n}}$ vector space of real $n$-vectors.
        """
        
        soln_s = rf"""
        
        An $\mathbb{{R}}^{{n}}$ vector space of real $n$-vectors can be defined as:
        $$
        X \in \mathbb{{R}}^{{n}} \quad \Longleftrightarrow 
        \quad X = \left[\begin{{array}}{{c}}
        x_{{1}} \\
        \vdots \\
        x_{{n}}
        \end{{array}}\right] \qquad \forall  \quad x_{{i}} \in \mathbb{{R}} 
        $$
        This above matrix is a $\mathbb{{R}}^{{n \times 1}}$ matrix, which is a column vector.
        
        It can also expressed it as a $\mathbb{{R}}^{{1 \times n}}$ matrix, which is a row vector.
        $$
        Y \in \mathbb{{R}}^{{1 \times n}} \Longleftrightarrow 
        Y = \left[x_{{1}}, \ldots, x_{{n}}\right] .
        $$
        The relation between $X$ and $Y$ can be expressed as:
        $Y = X^{{T}}$
        """
        
        answer_s = soln_s

        result = {
            'keywords': keywords,
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass
    
    
    def get_question_matrix_operations_summary(self):
        
        keywords = [
            'matrix',
            'operation',
            'operations',
            'matrix operation',
            'matrix operations',
            ]
        
        prob_s = rf"""
        
        Write basic matrix operations.
        
        """
        
        soln_s = []

        soln_item = rf"""
        <b>matrix transposition $
        \left(\mathbb{{R}}^{{m \times n}} \rightarrow \mathbb{{R}}^{{n \times m}}\right)$</b> 
        $$
        C=A^{{T}} \quad \Longrightarrow \quad c_{{i j}}=a_{{j i}},
        $$
        """
        soln_s.append(soln_item.strip())
        

        soln_item = rf"""
        <b>matrix-matrix addition</b> $
        \left(\mathbb{{R}}^{{m \times n}} \times \mathbb{{R}}^{{m \times n}} \rightarrow \mathbb{{R}}^{{m \times n}}\right)$,
        $$
        C=A+B \quad \Longrightarrow \quad c_{{i j}}=a_{{i j}}+b_{{i j}},
        $$
        """
        soln_s.append(soln_item.strip())
        
        soln_item = rf"""
        <b>scalar-matrix multiplication</b>$
        \left(\mathbb{{R}} \times \mathbb{{R}}^{{m \times n}} \rightarrow \mathbb{{R}}^{{m \times n}}\right)$,
        $$
        C=\alpha A \quad \Longrightarrow \quad c_{{i j}}=\alpha a_{{i j}},
        $$
        """
        soln_s.append(soln_item.strip())
        
        soln_item = rf"""
        <b>matrix-matrix multiplication</b>$
        \left(\mathbb{{R}}^{{m \times p}} \times \mathbb{{R}}^{{p \times n}} \rightarrow \mathbb{{R}}^{{m \times n}}\right)$,
        $$
        C=A B \quad \Longrightarrow \quad c_{{i j}}=\sum^{{p}} a_{{i k}} b_{{k j}} .
        $$
        """
        soln_s.append(soln_item.strip())
        
        
        soln_item = rf"""
        <b>pointwise matrix operation</b>
        $$
        C=A . * B \quad \Longrightarrow \quad c_{{i j}}=a_{{i j}} b_{{i j}}
        $$
        """
        soln_s.append(soln_item.strip())
        
        soln_item = rf"""
        <b>pointwise matrix division</b>$
        \left(\mathbb{{R}}^{{m \times n}} \times \mathbb{{R}}^{{m \times n}} \rightarrow \mathbb{{R}}^{{i n \times n}}\right)$
        $$
        C=A . / B \quad \Longrightarrow \quad c_{{i j}}=a_{{i j}} / b_{{i j}} .
        $$
        
        """
        soln_s.append(soln_item.strip())
        
        
        soln_s = "\n\n".join(soln_s)
        
        answer_s = soln_s

        result = {
            'keywords': keywords,
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass
    
    
    def get_question_vector_operations_summary(self):
        
        keywords = [
            'matrix',
            'vector',
            'operation',
            'operations',
            'vector operation',
            'vector operations',
            ]
        
        prob_s = rf"""
        
        Write vector operations.
        
        """
        
        soln_s = []

        soln_item = rf"""
        <b>Assume that</b>
        $a \in \mathbb{{R}}$ 
        $X \in \mathbb{{R}}^{{n}}$
        $Y \in \mathbb{{R}}^{{n}}$
        <br/>
        """
        soln_s.append(soln_item.strip())
        
        soln_item = rf"""
        <b>scalar-vector multiplication</b>
        $$
        Z =a X \quad \Longrightarrow \quad Z_{{i}}=a X_{{i}}
        $$
        """
        soln_s.append(soln_item.strip())
        
        soln_item = rf"""
        <b>vector addition</b>
        $$
        Z = X + Y \quad \Longrightarrow \quad Z_{{i}} = X_{{i}} + Y_{{i}}
        $$
        """
        soln_s.append(soln_item.strip())
        
        soln_item = rf"""
        <b>inner product (or dot product)</b>
        $$
        C = X^{{T}} Y \quad \Longrightarrow \quad C =\sum_{{i=1}}^{{n}} X_{{i}} Y_{{i}} .
        $$
        """
        soln_s.append(soln_item.strip())
        
        soln_item = rf"""
        <b>saxpy</b>
        $$
        Y = a X + Y \quad \Longrightarrow \quad Y_{{i}}=a X_{{i}} + Y_{{i}}
        $$
        """
        soln_s.append(soln_item.strip())
        
        soln_item = rf"""
        <b>pointwise vector operation</b>
        $$
        Z = X . * Y \quad \Longrightarrow \quad Z_{{i}} = X_{{i}} Y_{{i}}
        $$
        """
        soln_s.append(soln_item.strip())
        
        soln_item = rf"""
        <b>pointwise vector division</b>
        $$
        Z = X \cdot / Y \quad \Longrightarrow \quad Z_{{i}} = X_{{i}} / Y_{{i}}
        $$
        """
        soln_s.append(soln_item.strip())
        
        soln_s = "\n".join(soln_s)

        answer_s = soln_s

        result = {
            'keywords': keywords,
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass
    

    def get_question_discrete_fast_fourier_transform(self):
        
        keywords = [
            'matrix',
            'fourier',
            'discrete',
            'fast',
            'transform',
            'discrete fast fourier transform',
            ]
        
        prob_s = rf"""
        Define discrete fast Fourier transform of a vector.
        """
        
        soln_s = rf"""

        The discrete fast Fourier transform of a vector $X \in \mathbb{{C}}^{{n}}$ is a matrix-vector product
        $$
        Y = F_{{n}} X
        $$
        where the discrete fast Fourier transform matrix $F_{{n}}=\left(f_{{k j}}\right) \in \mathbb{{C}}^{{n \times n}}$ is defined by
        $$
        f_{{k j}}=\omega_{{n}}^{{(k-1)(j-1)}}
        $$
        where 
        $$
        \omega_{{n}}=\exp (-2 \pi i / n)=\cos (2 \pi / n)-i \cdot \sin (2 \pi / n)
        $$
        
        """
        
        answer_s = soln_s

        result = {
            'keywords': keywords,
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass
    
    
    pass
#class MatrixStoredQuestions:
