<jupyter_start><jupyter_text>Partial fraction decomposition - Input by functionWhen Laplace transform is used for system analysis, the Laplace transform of the output signal is obtained as a product of the transfer function and the Laplace transform of the input signal. The result of this multiplication can usually be quite difficult to comprehend. In order to execute the inverse Laplace transform we first perform the partial fraction decomposition. This example demonstrates this procedure.--- How to use this notebook?Toggle between the option *Input by function* or *Input by polynomial coefficients*.1. *Input by function*: * Example: To insert the function $\frac{1}{x^2(x^2 + 1)}$ (factored form) type 1/(x\*\*2\*(x\*\*2 + 1)); to insert the same function in the expanded form ($\frac{1}{x^4+x^2}$) type 1/(x\*\*4+x\*\*2).2. *Input by polynomial coefficients*: * Use the sliders to select the order of the numerator and denominator of a rational function of interest. * Insert the coefficients for both numerator and denominator in the dedicated textboxes and click *Confirm*.<jupyter_code>## System selector buttons
style = {'description_width': 'initial'}
typeSelect = widgets.ToggleButtons(
    options=[('Input by function', 0), ('Input by polynomial coefficients', 1),],
    description='Select: ',style={'button_width':'230px'})

btnReset=widgets.Button(description="Reset")

# function
textbox=widgets.Text(description=('Insert the function:'),style=style)
btnConfirmFunc=widgets.Button(description="Confirm") # ex btnConfirm

# poly
btnConfirmPoly=widgets.Button(description="Confirm") # ex btn

display(typeSelect)

def on_button_clickedReset(ev):
    display(Javascript("Jupyter.notebook.execute_cells_below()"))

def on_button_clickedFunc(ev):
    eq = sym.sympify(textbox.value)

    if eq==sym.factor(eq):
        display(Markdown('Input function $%s$ is written in a factored form. ' %sym.latex(eq) + 'Its expanded form is $%s$.' %sym.latex(sym.expand(eq))))
        
    else:
        display(Markdown('Input function $%s$ is written in an expanded form. ' %sym.latex(eq) + 'Its factored form is $%s$.' %sym.latex(sym.factor(eq))))
    
    display(Markdown('The result of the partial fraction decomposition is: $%s$' %sym.latex(sym.apart(eq)) + '.'))
    display(btnReset)
    
def transfer_function(num,denom):
    num = np.array(num, dtype=np.float64)
    denom = np.array(denom, dtype=np.float64)
    len_dif = len(denom) - len(num)
    if len_dif<0:
        temp = np.zeros(abs(len_dif))
        denom = np.concatenate((temp, denom))
        transferf = np.vstack((num, denom))
    elif len_dif>0:
        temp = np.zeros(len_dif)
        num = np.concatenate((temp, num))
        transferf = np.vstack((num, denom))
    return transferf

def f(orderNum, orderDenom):
    global text1, text2
    text1=[None]*(int(orderNum)+1)
    text2=[None]*(int(orderDenom)+1)
    display(Markdown('2. Insert the coefficients of the numerator.'))
    for i in range(orderNum+1):
        text1[i]=widgets.Text(description=(r'a%i'%(orderNum-i)))
        display(text1[i])
    display(Markdown('3. Insert the coefficients of the denominator.'))    
    for j in range(orderDenom+1):
        text2[j]=widgets.Text(description=(r'b%i'%(orderDenom-j)))
        display(text2[j])
    global orderNum1, orderDenom1
    orderNum1=orderNum
    orderDenom1=orderDenom

def on_button_clickedPoly(btn):
    clear_output()
    global num,denom
    enacbaNum=""
    enacbaDenom=""
    num=[None]*(int(orderNum1)+1)
    denom=[None]*(int(orderDenom1)+1)
    for i in range(int(orderNum1)+1):
        if text1[i].value=='' or text1[i].value=='Please insert a coefficient':
            text1[i].value='Please insert a coefficient'
        else:
            try:
                num[i]=int(text1[i].value)
            except ValueError:
                if text1[i].value!='' or text1[i].value!='Please insert a coefficient':
                    num[i]=sym.var(text1[i].value)
    
    for i in range (len(num)-1,-1,-1):
        if i==0:
            enacbaNum=enacbaNum+str(num[len(num)-i-1])
        elif i==1:
            enacbaNum=enacbaNum+"+"+str(num[len(num)-i-1])+"*x+"
        elif i==int(len(num)-1):
            enacbaNum=enacbaNum+str(num[0])+"*x**"+str(len(num)-1)
        else:
            enacbaNum=enacbaNum+"+"+str(num[len(num)-i-1])+"*x**"+str(i) 
    
    for j in range(int(orderDenom1)+1):
        if text2[j].value=='' or text2[j].value=='Please insert a coefficient':
            text2[j].value='Please insert a coefficient'
        else:
            try:
                denom[j]=int(text2[j].value)
            except ValueError:
                if text2[j].value!='' or text2[j].value!='Please insert a coefficient':
                    denom[j]=sym.var(text2[j].value)
                    
    for i in range (len(denom)-1,-1,-1):
        if i==0:
            enacbaDenom=enacbaDenom+"+"+str(denom[len(denom)-i-1])
        elif i==1:
            enacbaDenom=enacbaDenom+"+"+str(denom[len(denom)-i-1])+"*x"
        elif i==int(len(denom)-1):
            enacbaDenom=enacbaDenom+str(denom[0])+"*x**"+str(len(denom)-1)
        else:
            enacbaDenom=enacbaDenom+"+"+str(denom[len(denom)-i-1])+"*x**"+str(i)
        
    funcSym=sym.sympify('('+enacbaNum+')/('+enacbaDenom+')')

    DenomSym=sym.sympify(enacbaDenom)
    NumSym=sym.sympify(enacbaNum)
    DenomSymFact=sym.factor(DenomSym);
    funcFactSym=NumSym/DenomSymFact;
    
    if DenomSym==sym.expand(enacbaDenom):
        if DenomSym==DenomSymFact:
            display(Markdown('The function of interest is: $%s$. The numerator cannot be factored.' %sym.latex(funcSym)))
        else:
            display(Markdown('The function of interest is: $%s$. The numerator cannot be factored. The same function with the factored denominator can be written as: $%s$.' %(sym.latex(funcSym), sym.latex(funcFactSym))))

    if sym.apart(funcSym)==funcSym:
        display(Markdown('Partial fraction decomposition cannot be done.'))
    else:
        display(Markdown('The result of the partial fraction decomposition is: $%s$' %sym.latex(sym.apart(funcSym)) + '.'))
        
    btnReset.on_click(on_button_clickedReset)
    display(btnReset)
    
def partial_frac(index):

    if index==0:
        x = sym.Symbol('x')        
        display(widgets.HBox((textbox, btnConfirmFunc)))
        btnConfirmFunc.on_click(on_button_clickedFunc)
        btnReset.on_click(on_button_clickedReset)
    
    elif index==1:
        display(Markdown('1. Define the order of the numerator (orderNum) and denominator (orderDenom).'))
        widgets.interact(f, orderNum=widgets.IntSlider(min=0,max=10,step=1,value=0),
                 orderDenom=widgets.IntSlider(min=0,max=10,step=1,value=0));
        btnConfirmPoly.on_click(on_button_clickedPoly)
        display(btnConfirmPoly)      

input_data=widgets.interactive_output(partial_frac,{'index':typeSelect})
display(input_data)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14388179601204992, 'fraction_numerical': 0.014632047052072873, 'mean_word_length': 3.435114503816794, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '635666', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 2334, 'n_tokens_neox': 2272, 'n_words': 504, 'path': 'ICCT_en/examples/02/.ipynb_checkpoints/TD-09-Partial-fraction-decomposition-checkpoint.ipynb', 'repo_name': 'ICCTerasmus/ICCT', 'size': '6971'}