'''
Created on 12-Jul-2021

@author: bthakur

TODO: implement proof of all identities

'''
import random
import inspect
import traceback
import re

from sympy.simplify.fu import TR10

from sympy import (Symbol, symbols, latex, simplify, Eq,
                   pi,
                   sin, cos, tan,
                   csc, sec, cot, 
                   UnevaluatedExpr as ueval,
                   )
from sympy.abc import theta
import sympy as sp

from xv.km.util import latex_fraction, latex_exponent, wrap_bracket

from xv.util import UtilClass


class TrigIdentityHelper(UtilClass):
    '''
    This class provides trigonometric identities and their proofs
    '''
    
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.verbose = kwargs.get('verbose', False)
        self.implies = symbols(u'\U000021D2')
        self.A, self.B, self.C = symbols('A B C')
        pass
    
    def get_problem_random_identities_set(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        random_choices = list(range(1, 9))

        identifier = f"{self.__class__.__name__}{id(self)}.{inspect.stack()[0][3]}.random_choices"
        random_choice = self.get_no_repeat_random_choice(identifier, random_choices)
        
        random_choice = 8
        
        if random_choice == 1:
            return self.get_problem_identities_set_one()
            
        if random_choice == 2:
            return self.get_problem_identities_set_two()
            
        if random_choice == 3:
            return self.get_problem_identities_set_three()
            
        if random_choice == 4:
            return self.get_problem_identities_set_four()
            
        if random_choice == 5:
            return self.get_problem_identities_set_five()
            
        if random_choice == 6:
            return self.get_problem_identities_set_six()
            
        if random_choice == 7:
            return self.get_problem_identities_set_seven()
            
        if random_choice == 8:
            return self.get_problem_identities_set_eight()
            
        
        pass
    
    def get_problem_identities_set_one(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        identities_set = self.get_identities_set_one()
        prob_s = f"""
        Prove the followings:
        {identities_set}
        """
        
        soln_stmts = []
        
        base, height, hypotenuse = symbols("base, height, hypotenuse")
        
        sin_expr = height / hypotenuse
        cos_expr = base / hypotenuse
        tan_expr =  height / base

        right_angled_eq = Eq(base ** 2 + height ** 2, hypotenuse **2)
        
        soln_stmt = f"""
        The entities can be proven for any right-angled triangle.
        
        $\\displaystyle 
        \\begin{{aligned}}
        
        \\sin \\alpha \\cdot \\operatorname{{cosec}} \\alpha
        
        & = {latex(sin_expr)} \\cdot {latex(1 / sin_expr)}
        \\qquad \\text{{ by definition }}
        \\\\ \\\\ 
        
        & = 1
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())
        
        soln_stmt = f"""
        $\\displaystyle 
        \\begin{{aligned}}
        
        \\cos \\alpha \\cdot \\sec \\alpha
        
        & = {latex(cos_expr)} \\cdot {latex(1 / cos_expr)}
        \\qquad \\text{{ by definition }}
        \\\\ \\\\ 
        
        & = 1
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())
        
        soln_stmt = f"""
        $\\displaystyle 
        \\begin{{aligned}}
        
        \\tan \\alpha \\cdot \\cot \\alpha
        
        & = {latex(tan_expr)} \\cdot {latex(1 / tan_expr)}
        \\qquad \\text{{ by definition }}
        \\\\ \\\\ 
        
        & = 1
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())
        
        soln_stmt = f"""
        $\\displaystyle 
        \\begin{{aligned}}
        
        \\sin ^{{2}} \\alpha+\\cos ^{{2}} \\alpha
        
        & = {latex(sin_expr ** 2)} + {latex(cos_expr ** 2)}
        \\qquad \\text{{ by definition }}
        \\\\ \\\\ 
        
        & = 1
        \\qquad \\text{{ as }} \\quad {latex(right_angled_eq)}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())
        
        soln_stmt = f"""
        $\\displaystyle 
        \\begin{{aligned}}
        
        \\sec ^{{2}} \\alpha - \\tan ^{{2}} \\alpha
        
        & = {latex((1/cos_expr) ** 2)} - {latex(tan_expr ** 2)}
        \\qquad \\text{{ by definition }}
        \\\\ \\\\ 
        
        & = 1
        \\qquad \\text{{ as }} \\quad {latex(right_angled_eq)}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())
        
        soln_stmt = f"""
        $\\displaystyle 
        \\begin{{aligned}}
        
        \\operatorname{{cosec}} ^{{2}} \\alpha - \\cot ^{{2}} \\alpha
        
        & = {latex((1/sin_expr) ** 2)} - {latex((1/tan_expr) ** 2)}
        \\qquad \\text{{ by definition }}
        \\\\ \\\\ 
        
        & = 1
        \\qquad \\text{{ as }} \\quad {latex(right_angled_eq)}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())
        
        
        answer_s = f"""
        """
        
        soln_s = "\n\n".join(soln_stmts)
        
        result = {
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass
    
    def get_identities_set_one(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        identities_set = f"""
        $\\displaystyle \\sin \\alpha \\cdot \\operatorname{{cosec}} \\alpha=1$ 
                
        $\\displaystyle \\cos \\alpha \\cdot \\sec \\alpha=1$ 
        
        $\\displaystyle \\tan \\alpha \\cdot \\cot \\alpha=1$ 
        
        $\\displaystyle \\sin ^{{2}} \\alpha+\\cos ^{{2}} \\alpha=1$ 
        
        $\\displaystyle \\sec ^{{2}} \\alpha-\\tan ^{{2}} \\alpha=1$ 
        
        $\\displaystyle \\operatorname{{cosec}}^{{2}} \\alpha-\\cot ^{{2}} \\alpha=1$ 
        """
        return identities_set
        pass

    def get_problem_identities_set_two(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        identities_set = self.get_identities_set_two()
        prob_s = f"""
        Prove the followings:
        {identities_set}
        """
        
        soln_stmts = []
        
        alpha = Symbol('alpha', real = True)
        beta = Symbol('beta', real = True)
        theta = Symbol('theta', real = True)
        
        e = sp.E
        eq_e_theta = Eq(e ** (sp.I * theta), cos(theta) + sp.I * sin(theta))
        eq_e_alpha = Eq(e ** (sp.I * alpha), cos(alpha) + sp.I * sin(alpha))
        eq_e_beta = Eq(e ** (sp.I * beta), cos(beta) + sp.I * sin(beta))
        eq_e_alpha_beta = Eq(e ** (sp.I * (alpha + beta)), cos(alpha + beta) + sp.I * sin(alpha + beta))
        
        rhs_expended = sp.expand(eq_e_alpha.rhs * eq_e_beta.rhs)
        
        soln_stmt = f"""
        Euler's identity:
        
        $\\displaystyle 
        \\begin{{aligned}}

        & {latex(eq_e_alpha_beta.lhs)}
        = {latex(eq_e_alpha.lhs)} \\cdot {latex(eq_e_beta.lhs)}
        \\\\ \\\\
        
        & 
        \\text{{We know }} \\quad {latex(eq_e_theta)}.
        \\\\ \\\\

        & \\text{{Substituting the value of ${latex(theta)}
        $ with ${latex(alpha)} + {latex(beta)}
        $ on the left side and, ${latex(alpha)}$ and ${latex(beta)}
        $ respectively on the right side, we get  
        }}
        \\\\ \\\\
        
        & \\implies 
        {latex(eq_e_alpha_beta.rhs)}
        = \\left( {latex(eq_e_alpha.rhs)} \\right) 
        \\cdot 
        \\left( {latex(eq_e_beta.rhs)} \\right)
        \\\\ \\\\
        
        & \\implies 
        {latex(eq_e_alpha_beta.rhs)}
        = {latex( rhs_expended )}
        \\\\ \\\\

        & \\text{{Separating real and imaginary parts, we get}} 
        \\\\ \\\\
        
        & 
        {latex(sp.re(eq_e_alpha_beta.rhs))}
        = {latex( sp.re(rhs_expended) )}
        \\qquad \\cdots \\text {{ (i) }}
        \\\\ \\\\
        
        &{latex(sp.im(eq_e_alpha_beta.rhs))}
        = {latex( sp.im(rhs_expended) )}
        \\qquad \\cdots \\text {{ (ii) }}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())
        
        
        soln_stmt = f"""
        As we know:
        
        $\\displaystyle 
        \\begin{{aligned}}

        & {latex(sin(ueval(-theta)))}
        = {latex(sin(theta))} 
        \\\\ \\\\
        
        & {latex(cos(ueval(-theta)))}
        = {latex(cos(theta))} 
        \\\\ \\\\
        
        
        & \\text{{Substitution ${latex(beta)} = {latex(-beta)}$ in (i), we get }} 
        \\\\ \\\\
        
        &{latex(sp.re(eq_e_alpha_beta.rhs).subs(beta, ueval(-beta)))}
        = {latex( sp.re(rhs_expended).subs(beta, -beta) )}
        \\\\ \\\\
        
        &\\implies {latex(sp.re(eq_e_alpha_beta.rhs).subs(beta, -beta))}
        = {latex( sp.re(rhs_expended).subs(beta, -beta) )}
        \\qquad \\cdots \\text {{ (iii) }}
        \\\\ \\\\
        
        & \\text{{Substitution ${latex(beta)} = {latex(-beta)}$ in (ii), we get }} 
        \\\\ \\\\
        
        &{latex(sp.im(eq_e_alpha_beta.rhs).subs(beta, ueval(-beta)))}
        = {latex( sp.im(rhs_expended).subs(beta, -beta) )}
        \\\\ \\\\
        
        &\\implies {latex(sp.im(eq_e_alpha_beta.rhs).subs(beta, -beta))}
        = {latex( sp.im(rhs_expended).subs(beta, -beta) )}
        \\qquad \\cdots \\text {{ (iv) }}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())
        
        
        soln_stmt = f"""
        Dividing (ii) by (i):
        
        $\\displaystyle 
        \\begin{{aligned}}

        & \\frac {{ {latex(sp.im(eq_e_alpha_beta.rhs))} }} 
               {{ {latex(sp.re(eq_e_alpha_beta.rhs))} }}
        =
        \\frac {{ {latex( sp.im(rhs_expended) )} }} 
               {{ {latex( sp.re(rhs_expended) )} }}
        \\\\ \\\\
        
        &\\text{{Dividing both numerator and denominator on RHS by }} 
        {latex(cos(alpha) * cos(beta))}
        \\\\ \\\\
        
        &\\implies {latex(tan(alpha + beta))}
        =
        \\frac {{ {latex( tan(alpha) + tan(beta) )} }} 
               {{ {latex( 1 - tan(alpha) * tan(beta) )} }}
        \\qquad \\cdots \\text {{ (v) }}

        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())
        
        
        soln_stmt = f"""
        Dividing (i) by (ii):
        
        $\\displaystyle 
        \\begin{{aligned}}

        & \\frac {{ {latex(sp.re(eq_e_alpha_beta.rhs))} }}
                 {{ {latex(sp.im(eq_e_alpha_beta.rhs))} }} 
        =
        \\frac {{ {latex( sp.re(rhs_expended) )} }}
               {{ {latex( sp.im(rhs_expended) )} }} 
        \\\\ \\\\
        
        &\\text{{Dividing both numerator and denominator on RHS by }} 
        {latex(sin(alpha) * sin(beta))}
        \\\\ \\\\
        
        &\\implies {latex(cot(alpha + beta))}
        =
        \\frac {{ {latex( -1 + cot(alpha) * cot(beta) )} }}
               {{ {latex( cot(alpha) + cot(beta) )} }} 
        \\qquad \\cdots \\text {{ (vi) }}

        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())
        
        soln_stmt = f"""
        As we know:
        
        $\\displaystyle 
        \\begin{{aligned}}

        & {latex(tan(ueval(-theta)))}
        = {latex(tan(theta))} 
        \\\\ \\\\
        
        & {latex(cot(ueval(-theta)))}
        = {latex(cot(theta))} 
        \\\\ \\\\
        
        
        & \\text{{Substitution ${latex(beta)} = {latex(-beta)}$ in (v), we get }} 
        \\\\ \\\\
        
        &{latex(tan(alpha - beta))}
        =
        \\frac {{ {latex( tan(alpha) + tan(ueval(-beta)) )} }} 
               {{ {latex( 1 - tan(alpha) * tan(ueval(-beta)) )} }}
        \\\\ \\\\
        
        &\\implies {latex(tan(alpha - beta))}
        =
        \\frac {{ {latex( tan(alpha) - tan(beta) )} }} 
               {{ {latex( 1 + tan(alpha) * tan(beta) )} }}
        \\qquad \\cdots \\text {{ (vii) }}
        \\\\ \\\\
        
        & \\text{{Substitution ${latex(beta)} = {latex(-beta)}$ in (vi), we get }} 
        \\\\ \\\\
        
        &{latex(cot(alpha - beta))}
        =
        \\frac {{ {latex( -1 + cot(alpha) * cot(ueval(beta)) )} }}
               {{ {latex( cot(alpha) + cot(ueval(beta)) )} }} 
        \\\\ \\\\
        
        &\\implies {latex(cot(alpha - beta))}
        =
        \\frac {{ {latex( -1 - cot(alpha) * cot(beta) )} }}
               {{ {latex( cot(alpha) - cot(beta) )} }} 
        \\qquad \\cdots \\text {{ (viii) }}
        \\\\ \\\\
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())
        
        
        
        answer_s = f"""
        See solution.
        """
        
        soln_s = "\n\n".join(soln_stmts)
        
        result = {
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass

    
    def get_identities_set_two(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        identities_set = f"""
        $\\displaystyle \\sin (\\alpha \\pm \\beta)=\\sin \\alpha \\cos \\beta \\pm \\cos \\alpha \\sin \\beta$ 
        
        $\\displaystyle \\cos (\\alpha \\pm \\beta)=\\cos \\alpha \\cos \\beta \\mp \\sin \\alpha \\sin \\beta$ 
        
        $\\displaystyle \\tan (\\alpha \\pm \\beta)=\\frac{{\\tan \\alpha \\pm \\tan \\beta}}{{1 \\mp \\tan \\alpha \\cdot \\tan \\beta}}$ 
        
        $\\displaystyle \\cot (\\alpha \\pm \\beta)=\\frac{{\\cot \\alpha \\cot \\beta \\mp 1}}{{\\cot \\beta \\pm \\cot \\alpha}}$ 
        """
        return identities_set
        pass
    

    def get_problem_identities_set_three(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        identities_set = self.get_identities_set_three()
        prob_s = f"""
        Prove the followings:
        {identities_set}
        """
        
        soln_stmts = []
        
        x, y = symbols('x, y', real = True)
        
        alpha = Symbol('alpha', real = True)
        #n = Symbol('n', real = True)
        n = 2
        n_alpha = Symbol(f'{latex(n)}{latex(alpha)}', real = True)
        
        comp_num = x + sp.I * y
        
        e = sp.E
        eq_e_alpha = Eq(e ** (sp.I * alpha), cos(alpha) + sp.I * sin(alpha))
        eq_e_n_alpha = Eq(e ** (sp.I * n_alpha), cos(n * alpha) + sp.I * sin(n * alpha))
        rhs_expended = sp.expand(comp_num ** n)
        rhs_expended = rhs_expended.subs({x: cos(alpha),
                                          y: sin(alpha),
                                         })
        
        soln_stmt = f"""
        Euler's identity:
        
        $\\displaystyle 
        \\begin{{aligned}}

        & {latex(eq_e_n_alpha.lhs)}
        = {latex(eq_e_alpha.lhs ** ueval(n))} 
        \\\\ \\\\
        
        &\\implies {latex(eq_e_n_alpha.rhs)}
        = {latex(eq_e_alpha.rhs ** ueval(n))} 
        \\\\ \\\\
        
        &\\implies {latex(eq_e_n_alpha.rhs)}
        = {latex(rhs_expended)} 
        \\\\ \\\\
        
        & \\text {{Real part of both sides: }}
        \\\\
        
        &{latex(sp.re(eq_e_n_alpha.rhs))}
        = {latex(sp.re(rhs_expended))} 
        \\qquad \\cdots \\text {{ (i) }}
        \\\\ \\\\
        
        & \\text {{Imaginary part of both sides: }}
        \\\\
        
        &{latex(sp.im(eq_e_n_alpha.rhs))}
        = {latex(sp.im(rhs_expended))} 
        \\qquad \\cdots \\text {{ (ii) }}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())

        
        soln_stmt = f"""
        Dividing (ii) by (i):
        
        $\\displaystyle 
        \\begin{{aligned}}

        & \\frac {{ {latex(sp.im(eq_e_n_alpha.rhs))} }} 
               {{ {latex(sp.re(eq_e_n_alpha.rhs))} }}
        =
        \\frac {{ {latex(sp.im(rhs_expended))}  }} 
               {{ {latex(sp.re(rhs_expended))}  }}
        \\\\ \\\\
        
        &\\text{{Dividing both numerator and denominator on RHS by }} 
        {latex(cos(alpha) ** 2)}
        \\\\ \\\\
        
        &\\implies {latex(tan(2 * alpha))}
        =
        \\frac {{ {latex( 2 * tan(alpha) )} }} 
               {{ {latex( 1 - tan(alpha) ** 2)} }}
        \\qquad \\cdots \\text {{ (iii) }}

        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())
        
        
        
        soln_stmt = f"""
        Dividing (i) by (ii):
        
        $\\displaystyle 
        \\begin{{aligned}}

        & \\frac {{ {latex(sp.re(eq_e_n_alpha.rhs))} }}
                 {{ {latex(sp.im(eq_e_n_alpha.rhs))} }} 
               
        =
        \\frac {{ {latex(sp.re(rhs_expended))}  }}
               {{ {latex(sp.im(rhs_expended))}  }} 
        \\\\ \\\\
        
        &\\text{{Dividing both numerator and denominator on RHS by }} 
        {latex(sin(alpha) ** 2)}
        \\\\ \\\\
        
        &\\implies {latex(cot(2 * alpha))}
        =
        \\frac {{ {latex( cot(alpha) ** 2 - 1)} }}
               {{ {latex( 2 * cot(alpha) )} }} 
               
        \\qquad \\cdots \\text {{ (iv) }}


        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())
        
        
        answer_s = f"""
        See solution.
        """
        
        soln_s = "\n\n".join(soln_stmts)
        
        result = {
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass

    
    def get_identities_set_three(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        identities_set = f"""
        $\\displaystyle \\sin 2 \\alpha =2 \\sin \\alpha \\cos \\alpha $
        
        $\\displaystyle  \\cos 2 \\alpha =\\cos ^{{2}} \\alpha-\\sin ^{{2}} \\alpha $ 
        
        $\\displaystyle \\tan 2 \\alpha =\\frac{{2 \\tan \\alpha}}{{1-\\tan ^{{2}} \\alpha}}$ 
        
        $\\displaystyle \\cot 2 \\alpha =\\frac{{\\cot ^{{2}} \\alpha-1}}{{2 \\cot \\alpha}}$
        """
        return identities_set
        pass
    
    
    def get_problem_identities_set_four(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        identities_set = self.get_identities_set_four()
        prob_s = f"""
        Prove the followings:
        {identities_set}
        """
        
        soln_stmts = []
        
        x, y = symbols('x, y', real = True)
        
        alpha = Symbol('alpha', real = True)
        #n = Symbol('n', real = True)
        n = 3
        n_alpha = Symbol(f'{latex(n)}{latex(alpha)}', real = True)
        
        comp_num = x + sp.I * y
        
        e = sp.E
        eq_e_alpha = Eq(e ** (sp.I * alpha), cos(alpha) + sp.I * sin(alpha))
        eq_e_n_alpha = Eq(e ** (sp.I * n_alpha), cos(n * alpha) + sp.I * sin(n * alpha))
        rhs_expended = sp.expand(comp_num ** n)
        rhs_expended = rhs_expended.subs({x: cos(alpha),
                                          y: sin(alpha),
                                         })
        
        rhs_expended_re_subs = sp.re(rhs_expended).subs(sin(alpha)**2, 1- cos(alpha) ** 2)
        rhs_expended_im_subs = sp.im(rhs_expended).subs(cos(alpha)**2, 1- sin(alpha) ** 2)
        
        soln_stmt = f"""
        Euler's identity:
        
        $\\displaystyle 
        \\begin{{aligned}}

        & {latex(eq_e_n_alpha.lhs)}
        = {latex(eq_e_alpha.lhs ** ueval(n))} 
        \\\\ \\\\
        
        &\\implies {latex(eq_e_n_alpha.rhs)}
        = {latex(eq_e_alpha.rhs ** ueval(n))} 
        \\\\ \\\\
        
        &\\implies {latex(eq_e_n_alpha.rhs)}
        = {latex(rhs_expended)} 
        \\qquad \\cdots \\text {{ (i) }}

        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())

        
        
        soln_stmt = f"""
        Real part of both sides of (i):
        
        $\\displaystyle 
        \\begin{{aligned}}

        {latex(sp.re(eq_e_n_alpha.rhs))}
        &= {latex(sp.re(rhs_expended))} 
        \\\\ \\\\
        
        &= {latex(rhs_expended_re_subs)} 
        \\qquad \\cdots \\text {{ substitute }} 
        {latex(sin(alpha) ** 2)} = 1 - {latex(cos(alpha) ** 2)}
        \\\\ \\\\
        
        &= {latex(sp.expand(rhs_expended_re_subs))} 
        \\qquad \\cdots \\text {{ (ii) }}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())

        
        soln_stmt = f"""
        Imaginary part of both sides of (i):
        
        $\\displaystyle 
        \\begin{{aligned}}

        {latex(sp.im(eq_e_n_alpha.rhs))}
        &= {latex(sp.im(rhs_expended))} 
        \\\\ \\\\
        
        &= {latex(rhs_expended_im_subs)} 
        \\qquad \\cdots \\text {{ substitute }} 
        {latex(cos(alpha) ** 2)} = 1 - {latex(sin(alpha) ** 2)}
        \\\\ \\\\
        
        &= {latex(sp.expand(rhs_expended_im_subs))} 
        \\qquad \\cdots \\text {{ (iii) }}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())


        tan_numr_step1 = 4 * tan(alpha) ** 3 - 3 * tan(alpha) * sec(alpha) ** 2
        tan_denm_step1 = 4 - 3 * sec(alpha) ** 2
        
        tan_numr_step2 = 4 * tan(alpha) ** 3 - 3 * tan(alpha) * ueval(1 + tan(alpha) ** 2)
        tan_denm_step2 = 4 - 3 * ueval(1 + tan(alpha) ** 2)
        
        tan3_numr = 3 * tan(alpha) - tan(alpha) ** 3
        tan3_denm = 1 - 3 * tan(alpha) ** 2
        
        soln_stmt = f"""
        Dividing (iii) by (ii):
        
        $\\displaystyle 
        \\begin{{aligned}}

        & \\frac {{ {latex(sp.im(eq_e_n_alpha.rhs))} }} 
               {{ {latex(sp.re(eq_e_n_alpha.rhs))} }}
        =
        \\frac {{ {latex(sp.expand(rhs_expended_im_subs))}  }} 
               {{ {latex(sp.expand(rhs_expended_re_subs))}   }}
        \\\\ \\\\
        
        &\\text{{Dividing both numerator and denominator on RHS by }} 
        {latex(cos(alpha) ** 3)}
        \\\\ \\\\
        
        &\\implies {latex(tan(3 * alpha))}
        =
        \\frac {{ {latex( tan_numr_step1 )} }} 
               {{ {latex( tan_denm_step1 )} }}
        \\\\ \\\\

        &\\implies {latex(tan(3 * alpha))}
        =
        \\frac {{ {latex( tan_numr_step1 )} }} 
               {{ {latex( tan_denm_step1 )} }}
        \\\\ \\\\

        
        &\\implies {latex(tan(3 * alpha))}
        =
        \\frac {{ {latex( tan_numr_step2 )} }} 
               {{ {latex( tan_denm_step2 )} }}
        \\\\ \\\\

        
        &\\implies {latex(tan(3 * alpha))}
        =
        \\frac {{ {latex( tan3_numr )} }} 
               {{ {latex( tan3_denm )} }}
        \\qquad \\cdots \\text {{ (iv) }}
        \\\\ \\\\

        

        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())
        
        
        
        
        answer_s = f"""
        See solution.
        """
        
        soln_s = "\n\n".join(soln_stmts)
        
        result = {
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass

    
    def get_identities_set_four(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        identities_set = f"""
        $\\displaystyle \\sin 3 x = 3 \\sin x-4 \\sin ^3 x$
        
        $\\displaystyle \\cos 3 x = 4 \\cos ^3 x-3 \\cos x$

        $\\displaystyle \\tan 3 x =
        \\frac {{ 3 \\tan \\alpha - \\tan ^3 \\alpha }} {{ 1 - 3 \\tan ^2 \\alpha }}
         $

        """
        return identities_set
        pass
    
    
    def get_problem_identities_set_five(self):
        identities_set = self.get_identities_set_five()
        prob_s = f"""
        Prove the followings:
        {identities_set}
        """
        
        soln_stmts = []
        
        x, y = symbols('x, y', real = True)
        
        alpha = Symbol('alpha', real = True)
        #n = Symbol('n', real = True)

        soln_stmt = f"""
        $\\displaystyle 
        \\begin{{aligned}}

        {latex(sin(alpha))}
        & = 2 \\cdot {latex(sin(alpha / 2))} \\cdot {latex(cos(alpha / 2) )} 
        \\\\ \\\\
        
        & = 2 \\cdot
        \\frac {{ {latex(sin(alpha / 2))} }} {{ {latex(cos(alpha / 2))}  }} 
        \\cdot
        \\frac {{ 1 }} {{ {latex(sec(alpha / 2) ** 2)}  }} 
        \\\\ \\\\
        
        & = \\frac {{ 2 {latex(tan(alpha / 2))} }} 
        {{ 1 + {latex(tan(alpha / 2) ** 2)}  }} 
        \\qquad \\cdots \\text {{ (i) }}

        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())


        soln_stmt = f"""
        $\\displaystyle 
        \\begin{{aligned}}

        {latex(cos(alpha))}
        & = {latex(cos(alpha / 2) ** 2)} - {latex(sin(alpha / 2) ** 2)} 
        \\\\ \\\\
        
        & = \\frac {{ {latex(cos(alpha / 2) ** 2)} - {latex(sin(alpha / 2) ** 2)} }} 
               {{ {latex(cos(alpha / 2) ** 2)} \\cdot {latex(sec(alpha / 2) ** 2)}  }} 
               
        \\qquad \\cdots \\text {{ as }}  
        {latex(cos(alpha / 2))} \\cdot {latex(sec(alpha / 2))} = 1 
        \\\\ \\\\
        
        & = \\frac {{ 1 - {latex(tan(alpha / 2) ** 2)} }} 
               {{ {latex(sec(alpha / 2) ** 2)}  }} 
        \\\\ \\\\
        
        & = \\frac {{ 1 - {latex(tan(alpha / 2) ** 2)} }} 
        {{ 1 + {latex(tan(alpha / 2) ** 2)}  }} 
        \\qquad \\cdots \\text {{ (ii) }}

        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())

                
                
        answer_s = f"""
        See solution.
        """
        
        soln_s = "\n\n".join(soln_stmts)
        
        result = {
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass

    
    def get_identities_set_five(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        identities_set = f"""
        $\\displaystyle \\sin \\alpha 
        = \\frac{{2 \\tan \\frac{{ \\alpha }}{{2}}}}{{1+\\tan ^2 \\frac{{ \\alpha }}{{2}}}} 
        $
        
        $\\displaystyle \\cos  \\alpha 
        =\\frac{{1-\\tan ^2 \\frac{{ \\alpha }}{{2}}}}{{1+\\tan ^2 \\frac{{ \\alpha }}{{2}}}} 
        $

        """
        return identities_set
        pass
    
    
    def get_problem_identities_set_six(self):
        identities_set = self.get_identities_set_six()
        prob_s = f"""
        Prove the followings:
        {identities_set}
        """
        
        soln_stmts = []
        
        x, y = symbols('x, y', real = True)
        
        alpha = Symbol('alpha', real = True)
        beta = Symbol('beta', real = True)
        
        x_fnct = (alpha + beta) / 2
        y_fnct = (alpha - beta) / 2

        soln_stmt = f"""
        $\\displaystyle 
        \\begin{{aligned}}
    
        \\text{{Let }}
        & {latex(x)} = {latex(x_fnct)}
        \\\\ \\\\
        
        & {latex(y)} = {latex(y_fnct)}
        \\\\ \\\\
        
        \\implies
        & {latex(x + y)} = {latex(x_fnct + y_fnct)}
        \\\\ \\\\

        & {latex(x - y)} = {latex(x_fnct - y_fnct)}
        \\\\ \\\\

        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())

        term1 = sin(x + y)
        term2 = sin(x - y)
        term_calc = TR10(term1) + TR10(term2)
        term_calc_subs = term_calc.subs({x: x_fnct, y: y_fnct})
                
        soln_stmt = f"""
        Now, 
        
        $\\displaystyle 
        \\begin{{aligned}}
    
        { latex( sin(alpha) + sin(beta) )} 
        & = { latex( term1 + term2 )} 
        \\\\ \\\\
        
        & = \\left [ { latex( TR10(term1) ) }  \\right ]
        \\\\  
        & + \\left [ { latex( TR10(term2) ) }  \\right ]
        \\\\ \\\\

        & = { latex( term_calc ) }
        \\\\ \\\\

        & = { latex( term_calc_subs ) }
        \\qquad \\cdots \\text {{ (i) }}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())

                
        term1 = sin(x + y)
        term2 = sin(x - y)
        term_calc = TR10(term1) - TR10(term2)
        term_calc_subs = term_calc.subs({x: x_fnct, y: y_fnct})
                
        soln_stmt = f"""
        $\\displaystyle 
        \\begin{{aligned}}
    
        { latex( sin(alpha) - sin(beta) )} 
        & = { latex( term1 - term2 )} 
        \\\\ \\\\
        
        & = \\left [ { latex( TR10(term1) ) }  \\right ]
        \\\\  
        & - \\left [ { latex( TR10(term2) ) }  \\right ]
        \\\\ \\\\

        & = { latex( term_calc ) }
        \\\\ \\\\

        & = { latex( term_calc_subs ) }
        \\qquad \\cdots \\text {{ (ii) }}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())

                
        term1 = cos(x + y)
        term2 = cos(x - y)
        term_calc = TR10(term1) + TR10(term2)
        term_calc_subs = term_calc.subs({x: x_fnct, y: y_fnct})
                
        soln_stmt = f"""
        $\\displaystyle 
        \\begin{{aligned}}
    
        { latex( cos(alpha) + cos(beta) )} 
        & = { latex( term1 + term2 )} 
        \\\\ \\\\
        
        & = \\left [ { latex( TR10(term1) ) }  \\right ]
        \\\\  
        & + \\left [ { latex( TR10(term2) ) }  \\right ]
        \\\\ \\\\

        & = { latex( term_calc ) }
        \\\\ \\\\

        & = { latex( term_calc_subs ) }
        \\qquad \\cdots \\text {{ (iii) }}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())

                

                
        term1 = cos(x + y)
        term2 = cos(x - y)
        term_calc = TR10(term1) - TR10(term2)
        term_calc_subs = term_calc.subs({x: x_fnct, y: y_fnct})
                
        soln_stmt = f"""
        $\\displaystyle 
        \\begin{{aligned}}
    
        { latex( cos(alpha) - cos(beta) )} 
        & = { latex( term1 - term2 )} 
        \\\\ \\\\
        
        & = \\left [ { latex( TR10(term1) ) }  \\right ]
        \\\\  
        & - \\left [ { latex( TR10(term2) ) }  \\right ]
        \\\\ \\\\

        & = { latex( term_calc ) }
        \\\\ \\\\

        & = { latex( term_calc_subs ) }
        \\qquad \\cdots \\text {{ (iv) }}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())

                
        soln_stmt = f"""
        $\\displaystyle 
        \\begin{{aligned}}
    
        { latex( tan(alpha) + tan(beta) )} 
        & = \\frac {{ {latex(sin(alpha))} }} {{ {latex(cos(alpha))} }}
          + \\frac {{ {latex(sin(beta))} }} {{ {latex(cos(beta))} }}
        \\\\ \\\\
        
        & = \\frac {{ {latex(sin(alpha))} {latex(cos(beta))} 
                     + {latex(cos(alpha))} {latex(sin(beta))} }} 
                   {{ {latex(cos(alpha))} {latex(cos(beta))} }}
        \\\\ \\\\

        & = \\frac {{ {latex(sin(alpha + beta))} }} 
                   {{ {latex(cos(alpha))} {latex(cos(beta))} }}
        \\qquad \\cdots \\text {{ (v) }}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())

                
        soln_stmt = f"""
        $\\displaystyle 
        \\begin{{aligned}}
    
        { latex( tan(alpha) - tan(beta) )} 
        & = \\frac {{ {latex(sin(alpha))} }} {{ {latex(cos(alpha))} }}
          - \\frac {{ {latex(sin(beta))} }} {{ {latex(cos(beta))} }}
        \\\\ \\\\
        
        & = \\frac {{ {latex(sin(alpha))} {latex(cos(beta))} 
                     - {latex(cos(alpha))} {latex(sin(beta))} }} 
                   {{ {latex(cos(alpha))} {latex(cos(beta))} }}
        \\\\ \\\\

        & = \\frac {{ {latex(sin(alpha - beta))} }} 
                   {{ {latex(cos(alpha))} {latex(cos(beta))} }}
        \\qquad \\cdots \\text {{ (vi) }}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())


        soln_stmt = f"""
        $\\displaystyle 
        \\begin{{aligned}}
    
        { latex( cot(alpha) + cot(beta) )} 
        & = \\frac {{ {latex(cos(alpha))} }} {{ {latex(sin(alpha))} }}
          + \\frac {{ {latex(cos(beta))} }} {{ {latex(sin(beta))} }}
        \\\\ \\\\
        
        & = \\frac {{ {latex(cos(alpha))} {latex(sin(beta))} 
                     + {latex(sin(alpha))} {latex(cos(beta))} }} 
                   {{ {latex(sin(alpha))} {latex(sin(beta))} }}
        \\\\ \\\\

        & = \\frac {{ {latex(sin(alpha + beta))} }} 
                   {{ {latex(sin(alpha))} {latex(sin(beta))} }}
        \\qquad \\cdots \\text {{ (vii) }}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())



        soln_stmt = f"""
        $\\displaystyle 
        \\begin{{aligned}}
    
        { latex( cot(alpha) - cot(beta) )} 
        & = \\frac {{ {latex(cos(alpha))} }} {{ {latex(sin(alpha))} }}
          - \\frac {{ {latex(cos(beta))} }} {{ {latex(sin(beta))} }}
        \\\\ \\\\
        
        & = \\frac {{ {latex(cos(alpha))} {latex(sin(beta))} 
                     - {latex(sin(alpha))} {latex(cos(beta))} }} 
                   {{ {latex(sin(alpha))} {latex(sin(beta))} }}
        \\\\ \\\\

        & = - \\frac {{ {latex(sin(alpha - beta))} }} 
                   {{ {latex(sin(alpha))} {latex(sin(beta))} }}
        \\qquad \\cdots \\text {{ (viii) }}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())



                
        answer_s = f"""
        See solution.
        """
        
        soln_s = "\n\n".join(soln_stmts)
        
        result = {
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass

    
    def get_identities_set_six(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        identities_set = f"""
        $\\displaystyle \\sin \\alpha+\\sin \\beta
        =2 \\sin \\frac{{\\alpha+\\beta}}{{2}} \\cos \\frac{{\\alpha-\\beta}}{{2}}$
        
        $\\displaystyle \\sin \\alpha-\\sin \\beta
        =2 \\cos \\frac{{\\alpha+\\beta}}{{2}} \\sin \\frac{{\\alpha-\\beta}}{{2}}$
        
        $\\displaystyle \\cos \\alpha+\\cos \\beta
        =2 \\cos \\frac{{\\alpha+\\beta}}{{2}} \\cos \\frac{{\\alpha-\\beta}}{{2}}$
        
        $\\displaystyle \\cos \\alpha-\\cos \\beta
        =-2 \\sin \\frac{{\\alpha+\\beta}}{{2}} \\sin \\frac{{\\alpha-\\beta}}{{2}}$
        
        $\\displaystyle \\tan \\alpha \\pm \\tan \\beta
        =\\frac{{\\sin (\\alpha \\pm \\beta)}}{{\\cos \\alpha \\cos \\beta}}$
        
        $\\displaystyle \\cot \\alpha \\pm \\cot \\beta
        =\\pm \\frac{{\\sin (\\alpha \\pm \\beta)}}{{\\sin \\alpha \\sin \\beta}}$
        

        """
        return identities_set
        pass
    

    def get_problem_identities_set_seven(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        identities_set = self.get_identities_set_seven()
        prob_s = f"""
        Prove the followings:
        {identities_set}
        """
        
        soln_stmts = []
        
        alpha = Symbol('alpha', real = True)
        beta = Symbol('beta', real = True)

        term1 = cos(alpha - beta)
        term2 = cos(alpha + beta)
        term_calc = TR10(term1) - TR10(term2)
                
        soln_stmt = f"""
        $\\displaystyle 
        \\begin{{aligned}}
    
        { latex( term1 - term2 )} 
        & = \\left [ { latex( TR10(term1) ) }  \\right ]
        \\\\  
        & - \\left [ { latex( TR10(term2) ) }  \\right ]
        \\\\ \\\\

        & = { latex( term_calc ) }
        \\qquad \\cdots \\text {{ (i) }}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())


        term1 = cos(alpha - beta)
        term2 = cos(alpha + beta)
        term_calc = TR10(term1) + TR10(term2)
                
        soln_stmt = f"""
        $\\displaystyle 
        \\begin{{aligned}}
    
        { latex( term1 + term2 )} 
        & = \\left [ { latex( TR10(term1) ) }  \\right ]
        \\\\  
        & + \\left [ { latex( TR10(term2) ) }  \\right ]
        \\\\ \\\\

        & = { latex( term_calc ) }
        \\qquad \\cdots \\text {{ (ii) }}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())


        term1 = sin(alpha - beta)
        term2 = sin(alpha + beta)
        term_calc = TR10(term1) + TR10(term2)
                
        soln_stmt = f"""
        $\\displaystyle 
        \\begin{{aligned}}
    
        { latex( term1 + term2 )} 
        & = \\left [ { latex( TR10(term1) ) }  \\right ]
        \\\\  
        & + \\left [ { latex( TR10(term2) ) }  \\right ]
        \\\\ \\\\

        & = { latex( term_calc ) }
        \\qquad \\cdots \\text {{ (iii) }}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())


                
        term1 = sin(alpha + beta)
        term2 = sin(alpha - beta)
        term_calc = TR10(term1) * TR10(term2)
        term_calc_simp = sp.expand(term_calc)
        term_calc_simp_sin_func = term_calc_simp.subs({ 
                            cos(beta) ** 2: 1 - sin(beta) ** 2, 
                            cos(alpha) ** 2: 1 - sin(alpha) ** 2, 
                            })
        
        term_sin_func_simp = sp.expand(term_calc_simp_sin_func)
                
        soln_stmt = f"""
        $\\displaystyle 
        \\begin{{aligned}}
    
        {latex(term1)} {latex(term2)}
        & = \\left [ { latex( TR10(term1) ) }  \\right ]
        \\\\  
        & \\cdot \\;\\; \\left [ { latex( TR10(term2) ) }  \\right ]
        \\\\ \\\\

        & = { latex( term_calc_simp ) }
        \\\\ \\\\

        & = { latex( term_calc_simp_sin_func ) }
        \\\\ \\\\

        & = { latex( term_sin_func_simp ) }
        \\qquad \\cdots \\text {{ (iv) }}
        
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())


                
        term1 = cos(alpha + beta)
        term2 = cos(alpha - beta)
        term_calc = TR10(term1) * TR10(term2)
        term_calc_simp = sp.expand(term_calc)
        term_calc_simp_sin_func = term_calc_simp.subs({ 
                            cos(beta) ** 2: 1 - sin(beta) ** 2, 
                            sin(alpha) ** 2: 1 - cos(alpha) ** 2, 
                            })
        
        term_sin_func_simp = sp.expand(term_calc_simp_sin_func)
                
        soln_stmt = f"""
        $\\displaystyle 
        \\begin{{aligned}}
    
        {latex(term1)} {latex(term2)}
        & = \\left [ { latex( TR10(term1) ) }  \\right ]
        \\\\  
        & \\cdot \\;\\; \\left [ { latex( TR10(term2) ) }  \\right ]
        \\\\ \\\\
        
        & = { latex( term_calc_simp ) }
        \\\\ \\\\

        & = { latex( term_calc_simp_sin_func ) }
        \\\\ \\\\

        & = { latex( term_sin_func_simp ) }
        \\qquad \\cdots \\text {{ (v) }}
        
        
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())


                
                
        answer_s = f"""
        See solution.
        """
        
        soln_s = "\n\n".join(soln_stmts)
        
        result = {
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass

    
    def get_identities_set_seven(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        identities_set = f"""
        $\\displaystyle 2 \\sin \\alpha \\sin \\beta
        =\\cos (\\alpha-\\beta)-\\cos (\\alpha+\\beta)$ 
        
        $2\\displaystyle  \\cos \\alpha \\cos \\beta
        =\\cos (\\alpha-\\beta)+\\cos (\\alpha+\\beta)$ 
        
        $\\displaystyle 2 \\sin \\alpha \\cos \\beta
        =\\sin (\\alpha-\\beta)+\\sin (\\alpha+\\beta)$
        
        
        $\\displaystyle \\sin (\\alpha + \\beta) \\sin (\\alpha - \\beta)
        =\\sin ^2 \\alpha -\\sin ^2 \\beta$
        
        $\\displaystyle \\cos (\\alpha + \\beta) \\cos (\\alpha - \\beta)
        =\\cos ^2 \\alpha -\\sin ^2 \\beta$

        """
        return identities_set
        pass
    
    
    def get_problem_identities_set_eight(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        identities_set = self.get_identities_set_eight()
        prob_s = f"""
        Prove the followings:
        {identities_set}
        """
        
        soln_stmts = []
        
        theta1 = Symbol('theta_1', real = True)
        theta2 = Symbol('theta_2', real = True)
        x = Symbol('x', real = True)
        
        theta2_minus = Symbol(f"{latex(sp.pi / 2)} - {latex(theta2)}")
                
        soln_stmt = f"""
        In a right-angled triangle:
        
        $\\displaystyle 
        \\begin{{aligned}}
        
        \\text {{Let }}
        & { latex( sp.asin(x) )} 
        = { latex(  theta1 )} 
        \\qquad \\cdots \\text {{ (i) }}
        \\\\ \\\\

        \\text {{and, }}
        & { latex( sp.acos(x) )} 
        = { latex(  theta2 )} 
        \\qquad \\cdots \\text {{ (ii) }}
        \\\\ \\\\

        \\implies
        & { latex( cos(theta2) )} 
        = { latex( x )} 
        \\\\ \\\\

        \\implies
        & { latex( sin(theta2_minus) )} 
        = { latex( x )} 
        \\\\ \\\\

        \\implies
        & { latex( theta2_minus )} 
        = { latex( sp.asin(x) )} 
        \\\\ \\\\

        \\implies
        & { latex( sp.asin(x) + sp.acos(x))} 
        = { latex( sp.pi /2 )} 
        \\qquad \\text {{ replacing value from (ii) }} \\cdots \\text {{ (iii) }}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())

                
        soln_stmt = f"""
        
        $\\displaystyle 
        \\begin{{aligned}}
        
        \\text {{Let }}
        & { latex( sp.atan(x) )} 
        = { latex(  theta1 )} 
        \\qquad \\cdots \\text {{ (iv) }}
        \\\\ \\\\

        \\text {{and, }}
        & { latex( sp.acot(x) )} 
        = { latex(  theta2 )} 
        \\qquad \\cdots \\text {{ (v) }}
        \\\\ \\\\

        \\implies
        & { latex( cot(theta2) )} 
        = { latex( x )} 
        \\\\ \\\\

        \\implies
        & { latex( tan(theta2_minus) )} 
        = { latex( x )} 
        \\\\ \\\\

        \\implies
        & { latex( theta2_minus )} 
        = { latex( sp.atan(x) )} 
        \\\\ \\\\

        \\implies
        & { latex( sp.acot(x) + sp.atan(x))} 
        = { latex( sp.pi /2 )} 
        \\qquad \\text {{ replacing value from (v) }} \\cdots \\text {{ (vi) }}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())

                
        soln_stmt = f"""
        
        $\\displaystyle 
        \\begin{{aligned}}
        
        \\text {{Let }}
        & { latex( sp.atan(x) )} 
        = { latex(  theta1 )} 
        \\qquad \\cdots \\text {{ (vii) }}
        \\\\ \\\\

        \\text {{and, }}
        & { latex( sp.atan(1 / x) )} 
        = { latex(  theta2 )} 
        \\qquad \\cdots \\text {{ (viii) }}
        \\\\ \\\\

        \\implies
        & { latex( tan(theta2) )} 
        = { latex( 1 / x )} 
        \\\\ \\\\

        \\implies
        & { latex( cot(theta2) )} 
        = { latex( x )} 
        \\\\ \\\\

        \\implies
        & { latex( tan(theta2_minus) )} 
        = { latex( x )} 
        \\\\ \\\\

        \\implies
        & { latex( theta2_minus )} 
        = { latex( sp.atan(x) )} 
        \\\\ \\\\

        \\implies
        & { latex( sp.atan(1 / x) + sp.atan(x))} 
        = { latex( sp.pi /2 )} 
        \\qquad \\text {{ replacing value from (viii) }} \\cdots \\text {{ (ix) }}
        
        \\end{{aligned}}
        $ 
        """
        soln_stmts.append(soln_stmt.strip())

                
        answer_s = f"""
        See solution.
        """
        
        soln_s = "\n\n".join(soln_stmts)
        
        result = {
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass

    
    def get_identities_set_eight(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        identities_set = f"""
        $\\displaystyle
        \\begin{{aligned}}
        & \\arcsin (x)+\\arccos (x)=\\pi / 2 \\\\
        & \\arctan (x)+\\operatorname{{arccot}}(x)=\\pi / 2 . \\\\
        & \\arctan (x)+\\arctan (1 / x)=\\left\\{{\\begin{{array}}{{cl}}
        \\pi / 2, & \\text {{ if }} x > 0 \\\\
        -\\pi / 2, & \\text {{ if }} x < 0
        \\end{{array}}\\right.
        \\end{{aligned}}
        $
        """
        return identities_set
        pass
    
    
    def get_trig_identities_summary(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        
        identities_summary_items = []
        
        identities_summary_items.append(self.get_identities_set_one())
        identities_summary_items.append(self.get_identities_set_two())
        identities_summary_items.append(self.get_identities_set_three())
        identities_summary_items.append(self.get_identities_set_four())
        identities_summary_items.append(self.get_identities_set_five())
        identities_summary_items.append(self.get_identities_set_six())
        identities_summary_items.append(self.get_identities_set_seven())
        identities_summary_items.append(self.get_identities_set_eight())
        
        identities_summary_item = f"""
        

        
        
        
        $\\displaystyle \\sin \\alpha =\\frac{{1}}{{\\sqrt{{1+\\cot ^{{2}} \\alpha}}}} $
        
        $\\displaystyle \\cos \\alpha =\\frac{{1}}{{\\sqrt{{1+\\tan ^{{2}} \\alpha}}}} $
        
        
        $\\displaystyle \\implies \\sin ^2 \\theta=\\frac{{1-\\cos 2 \\theta}}{{2}}$
        
        $\\displaystyle \\implies \\cos ^2 \\theta=\\frac{{1+\\cos 2 \\theta}}{{2}}$
        
        
        
        
        $\\displaystyle 4 \\cos ^2 \\theta-1
         = \\frac{{\\sin 3 \\theta}}{{\\sin \\theta}}
        $
        
        
        
        $\\displaystyle \\cos \\frac{{\\alpha}}{{2}}
        =\\sqrt{{\\frac{{1+\\cos \\alpha}}{{2}}}}$ 
        
        $\\displaystyle \\sin \\frac{{\\alpha}}{{2}}
        =\\sqrt{{\\frac{{1-\\cos \\alpha}}{{2}}}}$ 
        
        
        
        $\\displaystyle \\cosh \\alpha
        =\\frac{{e^{{\\alpha}}+e^{{-\\alpha}}}}{{2}}$
        
        $\\displaystyle \\sinh \\alpha
        =\\frac{{e^{{\\alpha}}-e^{{-\\alpha}}}}{{2}}$ 
        
        $\\displaystyle \\tanh \\alpha
        =\\frac{{e^{{\\alpha}}-e^{{-\\alpha}}}}{{e^{{\\alpha}}+e^{{-\\alpha}}}}$ 
        
        $\\displaystyle \\operatorname{{coth}} \\alpha
        =\\frac{{e^{{\\alpha}}+e^{{-\\alpha}}}}{{e^{{\\alpha}}-e^{{-\\alpha}}}}$ 
        
        Additional identities:
        
        $\\displaystyle \\cos (\\beta-\\gamma)+\\cos (\\gamma-\\alpha)+\\cos (\\alpha-\\beta)=-\\frac{{3}}{{2}}$
        $\\displaystyle \\implies[\\sin \\alpha+\\sin \\beta+\\sin \\gamma]^2+(\\cos \\alpha+\\cos \\beta+\\cos \\gamma)^2=0$
        
        
        $\\displaystyle 
        \\sin x+\\sin 2 x+\\cdots+\\sin n x
        =\\frac{{\\cos \\frac{{x}}{{2}}-\\cos \\left(n+\\frac{{1}}{{2}}\\right) x}}{{2 \\sin \\frac{{x}}{{2}}}}
        $
        
        $\\displaystyle 
        \\cos x+\\cos 2 x+\\cos 3 x+\\cos 4 x 
        = 4 \\cos x \\cos \\frac{{5 x}}{{2}} \\cos \\frac{{x}}{{2}}
        $
        
        
        $\\displaystyle 
        \\sin (x)+\\sin (3 x)+\\sin (5 x)+\\cdots+\\sin (2 n-1) x
        = \\frac{{\\sin ^2(n x)}}{{\\sin (x)}}
        $
        
        $\\displaystyle 
        \\frac{{1}}{{4}}\\left(\\sin ^4 x+\\cos ^4 x\\right)-\\frac{{1}}{{6}}\\left(\\sin ^6 x+\\cos ^6 x\\right)
        =\\frac{{1}}{{12}}
        $
        
        
        $\\displaystyle 
        \\cos \\theta \\cdot \\cos 2 \\theta \\ldots \\ldots \\cos 2^{{n-1}} \\theta
        =\\frac{{\\sin 2^n \\theta}}{{2^n \\sin \\theta}}
        $
        
        
        $\\displaystyle 
        2 \\sin \\left(\\frac{{\\pi}}{{22}}\\right) \\sin \\left(\\frac{{3 \\pi}}{{22}}\\right) 
        \\sin \\left(\\frac{{5 \\pi}}{{22}}\\right) \\sin \\left(\\frac{{7 \\pi}}{{22}}\\right)
         \\sin \\left(\\frac{{9 \\pi}}{{22}}\\right)
         = \\frac{{2 \\sin \\frac{{32 \\pi}}{{11}}}}{{2^5 \\sin \\frac{{\\pi}}{{11}}}}
         $
        
        
        $\\displaystyle 
        \\sin \\left(60^{{\\circ}}-A\\right) \\sin A \\sin \\left(60^{{\\circ}}+A\\right)
        =\\frac{{1}}{{4}} \\sin 3 A
        $
        
        $\\displaystyle 
        15 \\sin ^4 \\alpha+10 \\cos ^4 \\alpha - 6
        = 3 \\sin ^2 \\alpha-2 \\cos ^2 \\alpha$
        
        
        $\\displaystyle 
        \\arctan (1)+\\arctan (2)+\\arctan (3)=\\pi
        $
        
        $\\displaystyle 
        \\arcsin \\alpha \\pm \\arcsin \\beta
        =\\arcsin \\left(\\alpha \\sqrt{{1-\\beta^2}} \\pm \\beta \\sqrt{{1-\\alpha^2}}\\right)
        $
        
        $\\displaystyle 
        \\arccos \\alpha \\pm \\arccos \\beta
        =\\arccos \\left(\\alpha \\beta \\mp \\sqrt{{\\left(1-\\alpha^2\\right)\\left(1-\\beta^2\\right)}}\\right)
        $
        
        
        $\\displaystyle 
        \\arctan \\alpha \\pm \\arctan \\beta
        =\\arctan \\left(\\frac{{\\alpha \\pm \\beta}}{{1 \\mp \\alpha \\beta}}\\right)
        $
        
        
        $\\displaystyle 
        \\sin \\left(\\sum_{{i=1}}^{{\\infty}} \\theta_i\\right)
        =\\sum_{{\\text {{odd }} k \\geq 1}}(-1)^{{(k-1) / 2}} \\sum_{{\\substack{{A \\subseteq\\{{1,2,3, \\ldots\\}} \\\\|A|=k}}}}\\left(\\prod_{{i \\in A}} \\sin \\theta_i \\prod_{{i \\notin A}} \\cos \\theta_i\\right)
        $
        
        
        $\\displaystyle 
        \\cos \\left(\\sum_{{i=1}}^{{\\infty}} \\theta_i\\right)
        =\\sum_{{\\text {{even }} k \\geq 0}}(-1)^{{k / 2}} \\sum_{{\\substack{{A \\subseteq\\{{1,2,3, \\ldots\\}} \\\\|A|=k}}}}\\left(\\prod_{{i \\in A}} \\sin \\theta_i \\prod_{{i \\notin A}} \\cos \\theta_i\\right)
        $
        
        $\\displaystyle 
        \\sec (\\alpha+\\beta+\\gamma)
        =\\frac{{\\sec \\alpha \\sec \\beta \\sec \\gamma}}{{1-\\tan \\alpha \\tan \\beta-\\tan \\alpha \\tan \\gamma-\\tan \\beta \\tan \\gamma}}
        $
        
        $\\displaystyle 
        \\csc (\\alpha+\\beta+\\gamma)
        =\\frac{{\\sec \\alpha \\sec \\beta \\sec \\gamma}}{{\\tan \\alpha+\\tan \\beta+\\tan \\gamma-\\tan \\alpha \\tan \\beta \\tan \\gamma}}
        $
        
        $\\displaystyle 
        \\tan \\left(\\frac{{\\alpha+\\beta}}{{2}}\\right)
        =\\frac{{\\sin \\alpha+\\sin \\beta}}{{\\cos \\alpha+\\cos \\beta}}
        =-\\frac{{\\cos \\alpha-\\cos \\beta}}{{\\sin \\alpha-\\sin \\beta}}
        $
        
        
        $\\displaystyle 
        1+2 \\cos (x)+2 \\cos (2 x)+2 \\cos (3 x)+\\cdots+2 \\cos (n x)
        =\\frac{{\\sin \\left(\\left(n+\\frac{{1}}{{2}}\\right) x\\right)}}{{\\sin (x / 2)}}
        $
        
        
        $\\displaystyle 
        \\begin{{aligned}}
        & \\sin \\varphi+\\sin (\\varphi+\\alpha)+\\sin (\\varphi+2 \\alpha)+\\cdots +\\sin (\\varphi+n \\alpha)
        =\\frac{{\\sin \\left(\\frac{{(n+1) \\alpha}}{{2}}\\right) \\cdot \\sin \\left(\\varphi+\\frac{{n \\alpha}}{{2}}\\right)}}{{\\sin \\frac{{\\alpha}}{{2}}}}
        \\end{{aligned}}
        $
        
        
        $\\displaystyle 
        \\begin{{array}}{{r}}
        \\cos \\varphi+\\cos (\\varphi+\\alpha)+\\cos (\\varphi+2 \\alpha)+\\cdots +\\cos (\\varphi+n \\alpha)
        =\\frac{{\\sin \\left(\\frac{{(n+1) \\alpha}}{{2}}\\right) \\cdot \\cos \\left(\\varphi+\\frac{{n \\alpha}}{{2}}\\right)}}{{\\sin \\frac{{\\alpha}}{{2}}}}
        \\end{{array}}        
        $
        
        
        $\\displaystyle 
        \\tan (x)+\\sec (x)
        =\\tan \\left(\\frac{{x}}{{2}}+\\frac{{\\pi}}{{4}}\\right)
        $
        
        
        Ptolemy's theorem
        If $w+x+y+z=\\pi=$ half circle,
        $
        \\begin{{aligned}}
        & \\text {{ then }} \\sin (w+x) \\sin (x+y) \\\\
        & =\\sin (x+y) \\sin (y+z) \\\\
        & =\\sin (y+z) \\sin (z+w) \\\\
        & =\\sin (z+w) \\sin (w+x) \\\\
        & =\\sin (w) \\sin (y)+\\sin (x) \\sin (z) \\\\
        &
        \\end{{aligned}}
        $
        
        
        
        $\\displaystyle
        \\prod_{{j=0}}^{{k-1}} \\cos \\left(2^j x\\right)
        =\\frac{{\\sin \\left(2^k x\\right)}}{{2^k \\sin (x)}}
        $
        
        $\\displaystyle
        \\prod_{{k=1}}^{{n-1}} \\sin \\left(\\frac{{k \\pi}}{{n}}\\right)=\\frac{{n}}{{2^{{n-1}}}}
        $
        
        $\\displaystyle
        \\prod_{{k=1}}^{{n-1}} \\cos \\left(\\frac{{k \\pi}}{{n}}\\right)=\\frac{{\\sin (\\pi n / 2)}}{{2^{{n-1}}}}
        $
        
        $\\displaystyle
        \\prod_{{k=1}}^{{n-1}} \\tan \\left(\\frac{{k \\pi}}{{n}}\\right)=\\frac{{n}}{{\\sin (\\pi n / 2)}}
        $
        
        $\\displaystyle
        \\prod_{{k=1}}^m \\tan \\left(\\frac{{k \\pi}}{{2 m+1}}\\right)=\\sqrt{{2 m+1}}
        $
        
        $\\displaystyle
        \\sin ^2\\left(18^{{\\circ}}\\right)+\\sin ^2\\left(30^{{\\circ}}\\right)=\\sin ^2\\left(36^{{\\circ}}\\right)
        $

        """
        
        identities_summary_items.append(identities_summary_item)
        
        identities_summary = "\n\n".join(identities_summary_items)
        
        return identities_summary
        pass
    
    def get_triangle_identities_summary(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        # see source 
        # F:\books\maths-physics\maths\trigonometry
        # trig-identities.pdf
        # 65 PROPERTIES OF TRIANGLE PART 1of 2.pdf
        # 66 PROPERTIES OF TRIANGLE PART 2 of 2.pdf
        
        triangle_identities_summary = r"""
        
        $\displaystyle
        \sin A+\sin B+\sin C
        = 4 \cos \frac{A}{2} \cdot \cos \frac{B}{2} \cdot \cos \frac{C}{2}
        $
        
        $\displaystyle
        \sin 2 A+\sin 2 B+\sin 2 C
        = 4 \sin A \cdot \sin B \cdot \sin C
        $
        
        $\displaystyle
        \triangle A B C$ is right iff $\sin ^2 A+\sin ^2 B+\sin ^2 C=2
        $
        
        $\displaystyle
        \frac{a}{\operatorname{Sin} A}=\frac{b}{\operatorname{Sin} B}
        =\frac{c}{\operatorname{Sin} C}
        $
        
        $\displaystyle
        c^2
        =a^2+b^2-2 a b \cos C
        $
        
        $\displaystyle
        \cos C
        =\frac{a^2+b^2-c^2}{2 a b}
        $
        
        $\displaystyle
        \frac{a-b}{a+b}
        =\frac{\tan \left(\frac{A-B}{2}\right)}{\tan \left(\frac{A+B}{2}\right)}
        $
        
        $\displaystyle
        \tan (x)+\tan (y)+\tan (z)
        =\tan (x) \tan (y) \tan (z)
        $
        
        $\displaystyle
        \sin (2 x)+\sin (2 y)+\sin (2 z)
        =4 \sin (x) \sin (y) \sin (z)
        $

        
        $\displaystyle
        \cot (x) \cot (y)+\cot (y) \cot (z)+\cot (z) \cot (x)
        =1
        $

        
        $\displaystyle
        a=b \cos C+c \cos B
        $

        
        $\displaystyle
        a(b \cos C-c \cos B)=b^2-c^2
        $

        
        $\displaystyle
        \tan \frac{B-C}{2}=\frac{b-c}{b+c} \cot \frac{A}{2}
        $

        
        $\displaystyle
        \text { If } s=\frac{a+b+c}{2} \text { is semi perimetre of triangle }
        $

        
        $\displaystyle
        \sin \frac{A}{2}=\sqrt{\frac{(s-b)(s-c)}{b c}}
        $

        
        $\displaystyle
        \cos \frac{A}{2}=\sqrt{\frac{s(s-a)}{b c}}
        $

        
        $\displaystyle
        \Delta=\frac{1}{2} a b \sin C=\frac{1}{2} b c \sin A=\frac{1}{2} c a \sin B=\sqrt{s(s-a)(s-b)(s-c)}
        $

        
        $\displaystyle
        \begin{aligned}
        (\mathrm{m}+\mathrm{n}) \cot \theta & =\mathrm{m} \cot \alpha-\mathrm{n} \cot \beta \\
        & =\mathrm{n} \cot B-\mathrm{m} \cot C
        \end{aligned}
        $

        
        $\displaystyle
        \text { Radius of Circumcirlce }
        R=\frac{a}{2 \sin A}=\frac{b}{2 \sin B}=\frac{c}{2 \sin C}=\frac{a b c}{4 \Delta}
        $

        
        $\displaystyle
        \text { Radius of The Incircle }
        r=\frac{\Delta}{s}
        $

        
        $\displaystyle
        \begin{aligned}
        \text { Radius of The Ex-Circles }
        & r_1=\frac{\Delta}{s-a} \\\\
        & r_2=\frac{\Delta}{s-b} \\\\
        & r_3=\frac{\Delta}{s-c}
        \end{aligned}
        $
        
        
        """
        return triangle_identities_summary
        pass
    
    def get_angles(self):
        return (self.A, self.B, self.C)


    def get_random_identity(self, index = None): 
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        if index is None:
            indexes = list(range(0, 7))
            identifier = f"{self.__class__.__name__}{id(self)}.{inspect.stack()[0][3]}"
            index = self.get_no_repeat_random_choice(identifier, indexes)
        
        if index == 0:
            return self._init_identities_0()
        
        if index == 1:
            return self._init_identities_1()
        
        if index == 2:
            return self._init_identities_2()
        
        if index == 3:
            return self._init_identities_3()
        
        if index == 4:
            return self._init_identities_4()
        
        if index == 5:
            return self._init_identities_5()
        
        if index == 6:
            return self._init_identities_6()
        
        return None
        pass
    

    
    def get_identities(self, index = None):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        A, B, C = self.get_angles()
        identity_sets = [
            self._init_identities_0(),
            self._init_identities_1(),
            self._init_identities_2(),
            self._init_identities_3(),
            self._init_identities_4(),
            self._init_identities_5(),
            self._init_identities_6(),
            ]
        
        if index is None:
            return identity_sets
        
        return [identity_sets[index]]
        pass

    def get_advanced_random_identity(self, index = None): 
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        if index is None:
            indexes = list(range(0, 7))
            identifier = f"{self.__class__.__name__}{id(self)}.{inspect.stack()[0][3]}"
            index = self.get_no_repeat_random_choice(identifier, indexes)
        
        if index == 0:
            return self._init_advanced_identities_0()
        
        if index == 1:
            return self._init_advanced_identities_1()
        
        if index == 2:
            return self._init_advanced_identities_2()
        
        if index == 3:
            return self._init_advanced_identities_3()
        
        if index == 4:
            return self._init_advanced_identities_4()
        
        if index == 5:
            return self._init_advanced_identities_5()
        
        if index == 6:
            return self._init_advanced_identities_6()
        
        return None
        pass
    
        
    
    def get_advanced_identities(self, index = None):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        A, B, C = self.get_angles()
        advanced_identity_sets = [
            self._init_advanced_identities_0(),
            self._init_advanced_identities_1(),
            self._init_advanced_identities_2(),
            self._init_advanced_identities_3(),
            self._init_advanced_identities_4(),
            self._init_advanced_identities_5(),
            self._init_advanced_identities_6(),
            ]
        
        if index is None:
            return advanced_identity_sets
        
        return [advanced_identity_sets[index]]
        pass
    
    def _init_identities_0(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        A, B, C = self.get_angles()
        ABp = latex(A + B)
        ABm = latex(A - B)
        ABCp = latex(A + B + C)
        
        eq = Eq(sin(A + B), sin(C))

        proof = f"""
        ${ABCp} = {latex(pi)}$
        
        $\\implies {ABp} = {latex(pi - C)}$
        
        $\\implies sin({ABp}) = sin({latex(pi - C)})$
        
        $= sin({latex(pi)}) * cos({latex(C)}) - cos({latex(pi)}) * sin({latex(C)})$
        
        $= sin({latex(C)})$  \t\t As \t $\\left. {{ sin({latex(pi)}) = 0 
                                                    \\\\ cos({latex(pi)}) = -1
                                                    }}\\right. $
        """
        return {'eq': eq, 'proof': proof}
    
        pass
    
    def _init_identities_1(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        A, B, C = self.get_angles()
        ABp = latex(A + B)
        ABm = latex(A - B)
        ABCp = latex(A + B + C)
        
        eq = Eq(cos(A + B), -cos(C))
        
        proof = f"""
        ${ABCp} = {latex(pi)}$
        
        $\\implies {ABp} = {latex(pi - C)}$
        
        $\\implies cos({ABp}) = cos({latex(pi - C)})$
        
        $= cos({latex(pi)}) * cos({latex(C)}) + sin({latex(pi)}) * sin({latex(C)})$
        
        $= - cos({latex(C)})$  \t\t As \t $\\left. {{ sin({latex(pi)}) = 0 
                                                    \\\\ cos({latex(pi)}) = -1
                                                    }}\\right. $
        """
        return {'eq': eq, 'proof': proof}
    
        pass
    
    def _init_identities_2(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        A, B, C = self.get_angles()
        ABp = latex(A + B)
        ABm = latex(A - B)
        ABCp = latex(A + B + C)

        ABp_half = latex (A/2 + B/2)
        ABm_half = latex (A/2 - B/2)
        ABCp_half = latex (A/2 + B/2 + C/2)

        eq = Eq(sin(A/2 + B/2), cos(C/2))
        
        proof = f"""
        ${ABCp} = {latex(pi)}$
        
        $\\implies {ABCp_half} = {latex(pi/2)}$
        
        $\\implies {ABp_half} = {latex(pi/2)} - {latex(C/2)}$
        
        $\\implies sin({ABp_half}) = sin({latex(pi/2)} - {latex(C/2)})$
        
        
        $RHS $
        $= sin({latex(pi/2)}) * cos({latex(C/2)}) - cos({latex(pi/2)}) * sin({latex(C/2)})$
        
        $= 1 * cos({latex(C/2)}) - 0 * sin({latex(C/2)})$  \t\t As \t $\\left. {{ sin({latex(pi/2)}) = 1 
                                                    \\\\ cos({latex(pi/2)}) = 0
                                                    }}\\right. $
                                                    
        $= cos({latex(C/2)})$ 
                                                    
        $\\implies sin({ABp_half}) = cos({latex(C/2)})$
        """
        return {'eq': eq, 'proof': proof}
    
        pass
    
    def _init_identities_3(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        A, B, C = self.get_angles()
        ABp = latex(A + B)
        ABm = latex(A - B)
        ABCp = latex(A + B + C)

        ABp_half = latex (A/2 + B/2)
        ABm_half = latex (A/2 - B/2)
        ABCp_half = latex (A/2 + B/2 + C/2)

        eq = Eq(cos(A/2 + B/2), sin(C/2))
        
        proof = f"""
        ${ABCp} = {latex(pi)}$
        
        $\\implies {ABCp_half} = {latex(pi/2)}$
        
        $\\implies {ABp_half} = {latex(pi/2)} - {latex(C/2)}$
        
        $\\implies cos({ABp_half}) = cos({latex(pi/2)} - {latex(C/2)})$
        
        $RHS $
        $= cos({latex(pi/2)} - {latex(C/2)})$
        
        $= cos({latex(pi/2)}) * cos({latex(C/2)}) + sin({latex(pi/2)}) * sin({latex(C/2)})$
        
        $= 0 * cos({latex(C/2)}) + 1 * sin({latex(C/2)})$  \t\t As \t $\\left. {{ sin({latex(pi/2)}) = 1 
                                                    \\\\ cos({latex(pi/2)}) = 0
                                                    }}\\right. $
                                                    
        $= sin({latex(C/2)})$ 
        
        $\\implies cos({ABp_half}) = sin({latex(C/2)})$
        """
        return {'eq': eq, 'proof': proof}
    
        pass

    def _declare_half_as_xy(self, A, B, ABp_half, ABm_half):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        x, y = symbols('x y')
        xyp = f"{x} + {y}"
        xym = f"{x} - {y}"

        half_as_xy = f"""
        Let:
        
        ${x} = {wrap_bracket(ABp_half)}$ 
        
        ${y} = {wrap_bracket(ABm_half)}$
        
        Then:
        
        ${latex(A)} = {wrap_bracket(ABp_half)} 
        + {wrap_bracket(ABm_half)}
        = {xyp}
        $ \t\t\t $\\cdots$ (i)

        ${latex(B)} = {wrap_bracket(ABp_half)} 
        - {wrap_bracket(ABm_half)}
        = {xym}
        $ \t\t\t $\\cdots$ (ii)

        """
        return x, y, xyp, xym, half_as_xy.strip()


    def _init_identities_4(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        A, B, C = self.get_angles()
        ABp = latex(A + B)
        ABm = latex(A - B)
        ABCp = latex(A + B + C)

        ABp_half = latex (A/2 + B/2)
        ABm_half = latex (A/2 - B/2)
        ABCp_half = latex (A/2 + B/2 + C/2)

        ABp_half_brkt = f"\\left( {ABp_half} \\right)"
        ABm_half_brkt = f"\\left( {ABm_half} \\right)"
        ABCp_half_brkt = f"\\left( {ABCp_half} \\right)"


        (AB2p, AB2m, 
        ABp1_half, ABm1_half,
        AB2p_s_latex, AB2m_s_latex
        ) = self._get_AB_plus_minus(A, B, C)

        eq = Eq(sin(A) + sin(B), 2 * sin(AB2p) * cos(AB2m)  )
        
        x, y, xyp, xym, half_as_xy = self._declare_half_as_xy(
                        A, B, ABp_half, ABm_half)
       
        proof = f"""
        {half_as_xy}
        
        Now:
        $sin({latex(A)}) + sin({latex(B)})$
        
        $= sin\\left({xyp}\\right) 
        + sin\\left({xym}\\right)$ \t\t using (i) & (ii)
        
        $= sin{x}*cos{y} 
        + cos{x}*sin{y} 
        \\\\
        + sin{x}*cos{y} 
        - cos{x}*sin{y}$ 
        
        $= 2 * sin{x}*cos{y}$ 

        $= {latex(eq.rhs)}$
        """
        return {'eq': eq, 'proof': proof}
    
        pass
    
    def _init_identities_5(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        A, B, C = self.get_angles()
        ABp = latex(A + B)
        ABm = latex(A - B)
        ABCp = latex(A + B + C)

        ABp_half = latex (A/2 + B/2)
        ABm_half = latex (A/2 - B/2)
        ABCp_half = latex (A/2 + B/2 + C/2)

        ABp_half_brkt = f"\\left( {ABp_half} \\right)"
        ABm_half_brkt = f"\\left( {ABm_half} \\right)"
        ABCp_half_brkt = f"\\left( {ABCp_half} \\right)"

        (AB2p, AB2m, 
        AB2p_latex, AB2m_latex,
        AB2p_s_latex, AB2m_s_latex
        ) = self._get_AB_plus_minus(A, B, C)


        eq = Eq(-sin(A) + sin(B), -2 * cos(AB2p) * sin(AB2m)  )

        x, y, xyp, xym, half_as_xy = self._declare_half_as_xy(
                        A, B, ABp_half, ABm_half)
       
       
        proof = f"""
        {half_as_xy}
        
        Now:
        $-sin({latex(A)}) + sin({latex(B)})$
        
        $= -sin({xyp}) 
        + sin({xym})$ \t\t using (i) & (ii)
        
        $= -( sin{x}*cos{y} - cos{x}*sin{y} )
        \\\\
        \\space \\space + sin{x}*cos{y} - cos{x}*sin{y}$ 
        
        $= -2 * cos{x}*sin{y}$ 
        
        $= -2 * sin{y} * cos{x}$ 
        
        $= {latex(eq.rhs)}$
        """
        return {'eq': eq, 'proof': proof}
    
        pass

    def _init_identities_6(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        A, B, C = self.get_angles()
        ABp = latex(A + B)
        ABm = latex(A - B)
        ABCp = latex(A + B + C)

        ABp_half = latex (A/2 + B/2)
        ABm_half = latex (A/2 - B/2)
        ABCp_half = latex (A/2 + B/2 + C/2)

        ABp_half_brkt = f"\\left( {ABp_half} \\right)"
        ABm_half_brkt = f"\\left( {ABm_half} \\right)"
        ABCp_half_brkt = f"\\left( {ABCp_half} \\right)"

        (AB2p, AB2m, 
        ABp1_half, ABm1_half,
        AB2p_s_latex, AB2m_s_latex
        ) = self._get_AB_plus_minus(A, B, C)

        eq = Eq(cos(2*A), 2*cos(A)**2 - 1)
       
        proof = f"""
        $cos(2{latex(A)})$
        
        $= cos({latex(A)} + {latex(A)})$
        
        $= cos({latex(A)})*cos({latex(A)}) 
        - sin({latex(A)})*sin({latex(A)})$        
       
        $= cos({latex(A)})^2 
        - sin({latex(A)})^2$ \t\t $\\cdots$ (i)
        
        $= cos({latex(A)})^2 
        - (1 - cos({latex(A)})^2)$
        
        $= cos({latex(A)})^2 
        - 1 + cos({latex(A)})^2$ \t\t $\\cdots$ (ii)
        
        $= {latex(eq.rhs)}$ 
        
        also:
        $cos({latex(A)})^2 
        - sin({latex(A)})^2$
        
        $= (1 - sin({latex(A)})^2) 
        - sin({latex(A)})^2$
        
        $= 1 - 2sin({latex(A)})^2$
        
        """
        return {'eq': eq, 'proof': proof}
    
        pass
    
    def _init_advanced_identities_0(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        A, B, C = self.get_angles()
        ABp = latex(A + B)
        ABm = latex(A - B)
        ABCp = latex(A + B + C)

        ABp_half = latex (A/2 + B/2)
        ABm_half = latex (A/2 - B/2)
        ABCp_half = latex (A/2 + B/2 + C/2)

        ABp_half_brkt = f"\\left( {ABp_half} \\right)"
        ABm_half_brkt = f"\\left( {ABm_half} \\right)"
        ABCp_half_brkt = f"\\left( {ABCp_half} \\right)"

        
        (AB2p, AB2m, 
        AB2p_latex, AB2m_latex,
        AB2p_s_latex, AB2m_s_latex
        ) = self._get_AB_plus_minus(A, B, C)

        eq = Eq(sin(A) + sin(B) + sin(C), 4 * cos(A/2) * cos(B/2) * cos(C/2))
        
        proof = f"""
        Please note:
        
        $sin({latex(A)}) + sin({latex(B)}) = 2 * sin{ABp_half_brkt} * cos{ABm_half_brkt}$ \t\t $\\cdots$ (i)
        
        $sin({latex(pi)} - {latex(theta)}) = sin{latex(theta/2)}$  \t\t $\\cdots$ (ii)
        
        $sin({latex(theta)}) = 2 * sin{latex(theta/2)} * cos{latex(theta/2)}$  \t\t $\\cdots$ (iii)
        
        
        Now, $LHS$ 
        $= {latex(eq.lhs)}$
        
        $= \\left[sin({latex(A)}) + sin({latex(B)})\\right] 
        + sin({latex(pi)} - ({ABp}))$
        
        $= 2 * sin{ABp_half_brkt} * cos{ABm_half_brkt}  
         + sin({ABp})$ \t\t applying $\\cdots$ (i) & (ii)  
        
        $= 2 * sin{ABp_half_brkt} * cos{ABm_half_brkt} 
        + 2 * sin{ABp_half_brkt} * cos{ABp_half_brkt}
        $ \t\t applying $\\cdots$ (iii)
        
        $= 2 * sin{ABp_half_brkt} 
        * \\left[
        cos{ABm_half_brkt} 
        + cos{ABp_half_brkt}  
        \\right]
        $
        
        $= 2 * sin\\left( {latex(pi/2)} - {latex(C/2)}\\right) \\\\ 
        * \\left[
        cos({latex(A/2)}) * cos({latex(B/2)}) + sin({latex(A/2)}) * sin({latex(B/2)})  
         \\\\
        + cos({latex(A/2)}) * cos({latex(B/2)}) - sin({latex(A/2)}) * sin({latex(B/2)})  
        \\right]
        $
        
        $= 2 * cos({latex(C/2)}) \\\\
        * 2 * cos({latex(A/2)}) * cos({latex(B/2)})$
        
        $= {latex(eq.rhs)}$
        """
        return {'eq': eq, 'proof': proof}
    
        pass
    
    def _init_advanced_identities_1(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        A, B, C = self.get_angles()
        ABp = latex(A + B)
        ABm = latex(A - B)
        ABCp = latex(A + B + C)

        ABp_half = latex (A/2 + B/2)
        ABm_half = latex (A/2 - B/2)
        ABCp_half = latex (A/2 + B/2 + C/2)

        ABp_half_brkt = f"\\left( {ABp_half} \\right)"
        ABm_half_brkt = f"\\left( {ABm_half} \\right)"
        ABCp_half_brkt = f"\\left( {ABCp_half} \\right)"

        
        (AB2p, AB2m, 
        AB2p_latex, AB2m_latex,
        AB2p_s_latex, AB2m_s_latex
        ) = self._get_AB_plus_minus(A, B, C)

        eq = Eq(sin(2 * A) + sin(2 * B) + sin(2 * C), 
               4 * sin(A) * sin(B) * sin(C))
        
        proof = f"""
        ${latex(eq.lhs)}$
        
        $= \\left[sin({latex(2*A)}) + sin({latex(2*B)})\\right] 
        + sin({latex(2*pi)} - 2 * ({ABp}))$
        
        $= \\left[sin({latex(2*A)}) + sin({latex(2*B)})\\right] \\\\
        + sin(-2 * ({ABp}))$
        
        $= \\left[sin({latex(2*A)}) + sin({latex(2*B)})\\right] \\\\
        - sin(2 * ({ABp}))$
        
        $= 2 * sin\\left({ABp}\\right) 
        * cos\\left({latex(A - B)}\\right) \\\\
        - 2 * sin\\left({ABp}\\right) 
        * cos\\left({ABp}\\right)
        $
        
        $= 2 * sin\\left({ABp}\\right) \\\\ 
        * \\left[
        cos\\left({latex(A - B)}\\right)
        - cos\\left({ABp}\\right) 
        \\right]
        $
        
        $= 2 * sin\\left( {latex(pi)} - {latex(C)}\\right) \\\\ 
        * \\left[
        \\left\{{
        cos({latex(A)}) * cos({latex(B)}) + sin({latex(A)}) * sin({latex(B)})  
        \\right\}}
        \\\\ 
        - 
        \\left\{{
        cos({latex(A)}) * cos({latex(B)}) - sin({latex(A)}) * sin({latex(B)})  
        \\right\}}
        \\right]
        $
        
        $= 2 * sin({latex(C)}) \\\\
        * 2 * sin({latex(A)}) * cos({latex(B)})$
        
        $= {latex(eq.rhs)}$
        """
        return {'eq': eq, 'proof': proof}
    
        pass
    
    def _init_advanced_identities_2(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        A, B, C = self.get_angles()
        ABp = latex(A + B)
        ABm = latex(A - B)
        ABCp = latex(A + B + C)

        ABp_double = latex (2*A + 2*B)
        ABm_double = latex (2*A - 2*B)
        ABCp_double = latex (2*A + 2*B + 2*C)

        ABp_double_brkt = f"\\left( {ABp_double} \\right)"
        ABm_double_brkt = f"\\left( {ABm_double} \\right)"
        ABCp_double_brkt = f"\\left( {ABCp_double} \\right)"

        ABp_half = latex (A/2 + B/2)
        ABm_half = latex (A/2 - B/2)
        ABCp_half = latex (A/2 + B/2 + C/2)

        ABp_half_brkt = f"\\left( {ABp_half} \\right)"
        ABm_half_brkt = f"\\left( {ABm_half} \\right)"
        ABCp_half_brkt = f"\\left( {ABCp_half} \\right)"


        (AB2p, AB2m, 
        AB2p_latex, AB2m_latex,
        AB2p_s_latex, AB2m_s_latex
        ) = self._get_AB_plus_minus(A, B, C)

        eq = Eq(sin(4 * A) + sin(4 * B) + sin(4 * C), 
               -4 * sin(2 * A) * sin(2 * B) * sin(2 * C))
        
        proof = f"""
        ${latex(eq.lhs)}$
        
        $= \\left[sin({latex(4*A)}) + sin({latex(4*B)})\\right] 
        + sin({latex(4*pi)} - 4 * ({ABp}))$
        
        $= \\left[sin({latex(4*A)}) + sin({latex(4*B)})\\right] \\\\
        + sin(-4 * ({ABp}))$
        
        $= \\left[sin({latex(4*A)}) + sin({latex(4*B)})\\right] \\\\
        - sin(4 * ({ABp}))$
        
        $= 2 * sin{ABp_double_brkt} 
        * cos{ABm_double_brkt} \\\\
        - 2 * sin{ABp_double_brkt} 
        * cos{ABp_double_brkt}
        $
        
        $= 2 * sin{ABp_double_brkt} \\\\ 
        * \\left[
        cos{ABm_double_brkt}
        - cos{ABp_double_brkt} 
        \\right]
        $
        
        $= 2 * sin\\left( {latex(2*pi)} - {latex(2*C)}\\right) \\\\ 
        * \\left[
        \\left\{{
        cos({latex(2*A)}) * cos({latex(2*B)}) + sin({latex(2*A)}) * sin({latex(2*B)})  
        \\right\}}
        \\\\ 
        - 
        \\left\{{
        cos({latex(2*A)}) * cos({latex(2*B)}) - sin({latex(2*A)}) * sin({latex(2*B)})  
        \\right\}}
        \\right]
        $
        
        $= 2 * sin({latex(-2*C)}) \\\\
        * 2 * sin({latex(2*A)}) * cos({latex(2*B)})$
        
        $= 2 * (- sin({latex(2*C)})) \\\\
        * 2 * sin({latex(2*A)}) * cos({latex(2*B)})$
        
        $= {latex(eq.rhs)}$
        """
        return {'eq': eq, 'proof': proof}
    
        pass

    def _init_advanced_identities_3(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        A, B, C = self.get_angles()
        ABp = latex(A + B)
        ABm = latex(A - B)
        ABCp = latex(A + B + C)

        ABp_half = latex (A/2 + B/2)
        ABm_half = latex (A/2 - B/2)
        ABCp_half = latex (A/2 + B/2 + C/2)

        ABp_half_brkt = f"\\left( {ABp_half} \\right)"
        ABm_half_brkt = f"\\left( {ABm_half} \\right)"
        ABCp_half_brkt = f"\\left( {ABCp_half} \\right)"

        (AB2p, AB2m, 
        AB2p_latex, AB2m_latex,
        AB2p_s_latex, AB2m_s_latex
        ) = self._get_AB_plus_minus(A, B, C)

        eq =  Eq(-sin(A) + sin(B) + sin(C), -4 * sin(A/2) * cos(B/2) * sin(C/2))
        
        eq_formula1 = self._init_identities_5()['eq']

        proof = f"""
        $LHS = {latex(eq.lhs)}$
        
        $= \\left[-sin({latex(A)}) + sin({latex(B)})\\right] 
        + sin({latex(pi)} - ({ABp}))$
        
        $= \\left[-sin({latex(A)}) + sin({latex(B)})\\right] \\\\
        + sin({ABp})$
        
        Using ${latex(eq_formula1)}$
        
        $LHS $
        $= - 2 * sin{ABm_half_brkt} 
        * cos{ABp_half_brkt} \\\\
        + 2 * sin{ABp_half_brkt} 
        * cos{ABp_half_brkt}
        $
        
        $= -2 * cos{ABp_half_brkt} \\\\ 
        * \\left[
        - sin{ABm_half_brkt} 
        + sin{ABp_half_brkt}  
        \\right]
        $
        
        $= -2 * cos\\left( {latex(pi/2)} - {latex(C/2)}\\right) \\\\ 
        * \\left[
        - sin({latex(A/2)}) * cos({latex(B/2)}) + cos({latex(A/2)}) * sin({latex(B/2)})  
        \\\\ 
        + sin({latex(A/2)}) * cos({latex(B/2)}) + cos({latex(A/2)}) * sin({latex(B/2)})  
        \\right]
        $
        
        $= -2 * sin({latex(C/2)}) \\\\
        * 2 * cos({latex(A/2)}) * sin({latex(B/2)})$
        
        $= {latex(eq.rhs)}$
        """
        return {'eq': eq, 'proof': proof}
    
        pass

    def _init_advanced_identities_4(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        A, B, C = self.get_angles()
        ABp = latex(A + B)
        ABm = latex(A - B)
        ABCp = latex(A + B + C)

        ABp_half = latex (A/2 + B/2)
        ABm_half = latex (A/2 - B/2)
        ABCp_half = latex (A/2 + B/2 + C/2)

        ABp_half_brkt = f"\\left( {ABp_half} \\right)"
        ABm_half_brkt = f"\\left( {ABm_half} \\right)"
        ABCp_half_brkt = f"\\left( {ABCp_half} \\right)"

        
        (AB2p, AB2m, 
        AB2p_latex, AB2m_latex,
        AB2p_s_latex, AB2m_s_latex
        ) = self._get_AB_plus_minus(A, B, C)

        eq = Eq(cos(A) + cos(B) + cos(C), 1 + 4 * sin(A/2) * sin(B/2) * sin(C/2))
        
        proof = f"""
        ${latex(eq.lhs)}$
        
        $= \\left[cos({latex(A)}) + cos({latex(B)})\\right] 
        + cos({latex(pi)} - ({ABp}))$
        
        $= \\left[cos({latex(A)}) + cos({latex(B)})\\right] 
        - cos({ABp})$
        
        $= 2 * cos{ABp_half_brkt} 
        * cos{ABm_half_brkt} \\\\
        - \\left( 2cos^{{2}}{ABp_half_brkt} - 1\\right)$
        
        $= 2 * cos{ABp_half_brkt} 
        * cos{ABm_half_brkt} \\\\
        - 2cos^{{2}}{ABp_half_brkt} + 1$
        
        $= 2 * cos{ABp_half_brkt} 
        * \\left[
        cos{ABm_half_brkt} 
        - cos{ABp_half_brkt}  
        \\right] + 1
        $
        
        $= 2 * cos\\left( {latex(pi/2)} - {latex(C/2)}\\right) \\\\ 
        * \\left[
        cos({latex(A/2)}) * cos({latex(B/2)}) + sin({latex(A/2)}) * sin({latex(B/2)})  
        \\\\ 
        - cos({latex(A/2)}) * cos({latex(B/2)}) + sin({latex(A/2)}) * sin({latex(B/2)})  
        \\right] + 1
        $
        
        $= 2 * sin({latex(C/2)}) \\\\
        * 2 * sin({latex(A/2)}) * sin({latex(B/2)}) + 1$
        
        $= {latex(eq.rhs)}$
        """
        return {'eq': eq, 'proof': proof}
    
        pass
    
    def _init_advanced_identities_5(self):
        A, B, C = self.get_angles()
        ABp = latex(A + B)
        ABm = latex(A - B)
        ABCp = latex(A + B + C)

        ABp_brkt = f"\\left( {ABp} \\right)"
        ABm_brkt = f"\\left( {ABm} \\right)"
        ABCp_brkt = f"\\left( {ABCp} \\right)"

        ABp_half = latex (A/2 + B/2)
        ABm_half = latex (A/2 - B/2)
        ABCp_half = latex (A/2 + B/2 + C/2)

        ABp_half_brkt = f"\\left( {ABp_half} \\right)"
        ABm_half_brkt = f"\\left( {ABm_half} \\right)"
        ABCp_half_brkt = f"\\left( {ABCp_half} \\right)"

        
        AB2p_latex = latex(A+B)
        AB2m_latex = latex(A-B)

        eq = Eq(cos(2 * A) + cos(2 * B) + cos(2 * C), 
               -1 - 4 * cos(A) * cos(B) * cos(C))
        
        proof = f"""
        ${latex(eq.lhs)}$
        
        $= \\left[cos({latex(2*A)}) + cos({latex(2*B)})\\right] 
        + cos({latex(2*pi)} - 2*({ABp}))$
        
        $= \\left[cos({latex(2*A)}) + cos({latex(2*B)})\\right] 
        + cos(- 2*({ABp}))$
        
        $= \\left[cos({latex(2*A)}) + cos({latex(2*B)})\\right] 
        + cos(2*({ABp}))$
        
        $= 2 * cos{ABp_brkt} 
        * cos{ABm_brkt} \\\\
        + \\left( 2cos^{{2}}{ABp_brkt} - 1\\right)$
        
        $= 2 * cos{ABp_brkt} 
        * cos{ABm_brkt} \\\\
        + 2cos^{{2}}{ABp_brkt} - 1$
        
        $= 2 * cos{ABp_brkt} 
        * \\left[
        cos{ABm_brkt} 
        + cos{ABp_brkt}  
        \\right] - 1
        $
        
        $= 2 * cos\\left( {latex(pi)} - {latex(C)}\\right) \\\\ 
        * \\left[
        cos({latex(A)}) * cos({latex(B)}) + sin({latex(A)}) * sin({latex(B)})  
        \\\\ 
        + cos({latex(A)}) * cos({latex(B)}) - sin({latex(A)}) * sin({latex(B)})  
        \\right] - 1
        $
                
        $= 2 * (- cos({latex(C)})) \\\\
        * 2 * cos({latex(A)}) * cos({latex(B)}) - 1$
        
        $= {latex(eq.rhs)}$
        """
        return {'eq': eq, 'proof': proof}
    
        pass
    
    def _init_advanced_identities_6(self):
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        theta = Symbol('theta')


        A, B, C = self.get_angles()
        ABp = latex(A + B)
        ABm = latex(A - B)
        ABCp = latex(A + B + C)

        ABp_brkt = f"\\left( {ABp} \\right)"
        ABm_brkt = f"\\left( {ABm} \\right)"
        ABCp_brkt = f"\\left( {ABCp} \\right)"

        ABp_double = latex (2*A + 2*B)
        ABm_double = latex (2*A - 2*B)
        ABCp_double = latex (2*A + 2*B + 2*C)

        ABp_double_brkt = f"\\left( {ABp_double} \\right)"
        ABm_double_brkt = f"\\left( {ABm_double} \\right)"
        ABCp_double_brkt = f"\\left( {ABCp_double} \\right)"

        ABp_half = latex (A/2 + B/2)
        ABm_half = latex (A/2 - B/2)
        ABCp_half = latex (A/2 + B/2 + C/2)

        ABp_half_brkt = f"\\left( {ABp_half} \\right)"
        ABm_half_brkt = f"\\left( {ABm_half} \\right)"
        ABCp_half_brkt = f"\\left( {ABCp_half} \\right)"

        
        AB2p_latex = latex(A+B)
        AB2m_latex = latex(A-B)

        eq = Eq(cos(4 * A) + cos(4 * B) + cos(4 * C), 
               4 * cos(2 * A) * cos(2 * B) * cos(2 * C) - 1)

        soln_items = []
        
        soln_item = f"""
        $\\displaystyle 
        \\begin{{aligned}}
        
        & {latex(eq.lhs)}
        \\\\ \\\\
        
        & = \\left[cos({latex(4*A)}) + cos({latex(4*B)})\\right] 
        + cos({latex(4*pi)} - 4({ABp})) 
        \\qquad \\text{{ by substituting }} 
        {latex(C)} = {latex(sp.pi)} - \\left( {latex(A)} + {latex(B)} \\right)
        \\\\ \\\\
        
        & = \\left[cos({latex(4*A)}) + cos({latex(4*B)})\\right] 
        + cos(- 4 ({ABp})) 
        \\qquad \\text{{ the value does not change by adding or subtracting multiple of }} 
        {latex(2*pi)}
        \\\\ \\\\
        
        & = \\left[cos({latex(4*A)}) + cos({latex(4*B)})\\right] 
        + cos(4 ({ABp}))
        \\qquad \\text{{ as }} {latex(cos(ueval(-theta)))} =  {latex(cos(theta))}
        \\\\ \\\\
        
        & = 2 \\; cos{ABp_double_brkt} 
        \\; cos{ABm_double_brkt} 
        \\quad + \\quad 
        \\left( 2cos^{{2}}{ABp_double_brkt} - 1\\right)
        \\qquad \\text{{simplifyig first term and using }} 
        {latex(cos(2 * theta))} =  2{latex(cos(theta) ** 2)} - 1
        \\\\ \\\\
        
        & = 2 \\; cos{ABp_double_brkt} 
        \\; cos{ABm_double_brkt} 
        \\quad + \\quad
        2cos^{{2}}{ABp_double_brkt} 
        \\quad - 1
        \\\\ \\\\

        & = 2 cos{ABp_double_brkt} 
        \\quad \\cdot \\quad 
        \\left[
        cos{ABm_double_brkt} 
        + cos{ABp_double_brkt}  
        \\right] 
        \\quad - 1
        \\qquad \\text{{ separating common factor }} 
        \\\\ \\\\
        
        & \\text{{ by substituting }} 
        {latex(C)} = {latex(sp.pi)} - \\left( {latex(A)} + {latex(B)} \\right)
        \\text{{ in first term and expanding the second term }} 
        \\\\ \\\\
        
        & = 2 cos\\left( {latex(2*pi)} - {latex(2*C)}\\right) 
        \\quad \\cdot \\quad 
        \\left[
        cos({latex(2*A)}) cos({latex(2*B)}) + sin({latex(2*A)}) sin({latex(2*B)})  
        \\; + \\;
        cos({latex(2*A)}) cos({latex(2*B)}) - sin({latex(2*A)}) sin({latex(2*B)})  
        \\right] 
        \\quad - 1
        \\\\ \\\\
        
        & = 2 cos({latex(2*C)}) 
        \cdot 2 cos({latex(2*A)}) \\cdot  cos({latex(2*B)}) - 1 
        \\qquad \\text{{ cancelling out terms }} 
        \\\\ \\\\
        
        & = {latex(eq.rhs)}
        
        \\end{{aligned}}
        $
        """
        soln_items.append(soln_item)

        proof = "\n\n".join(soln_items)

        return {'eq': eq, 'proof': proof}
        pass
    
    def _get_AB_plus_minus(self, A, B, C):  
        sInfo = f"""Info: {self.__class__.__name__}.{inspect.stack()[0][3]}
        """
        self._log(sInfo)

        AB2p = (A + B) / 2
        AB2m = (A - B) / 2
        AB2p_s_latex = latex_fraction(f"{latex(A)} + {latex(B)}", 2)
        AB2m_s_latex = latex_fraction(f"{latex(A)} - {latex(B)}", 2)
        
        AB2p_latex = latex_fraction(f"{latex(A)}", 2) + " + " + latex_fraction(f"{latex(B)}", 2)
        AB2m_latex = latex_fraction(f"{latex(A)}", 2) + " - " + latex_fraction(f"{latex(B)}", 2)
        
        return (AB2p, AB2m, 
                AB2p_latex, AB2m_latex,
                AB2p_s_latex, AB2m_s_latex
                )
    pass
#class TrigIdentityHelper:
