def nsolve(self,h,lower,upper):
        #h is step, then lower and upper bounds the numeric solution is to be good for
        y0=self.cond
        t=list(np.arange(lower,upper+h,h))

        ystar=len(t)*[0]
        ystar[0]=y0
        ypfunction=self.func
        op=self.ypoperator
        for i in range(0, len(t) - 1):
            k1 = op.apply(self.coeffs[1] * ystar[i] , ypfunction.apply(t[i]))
            y1 = ystar[i] + k1 * h / 2
            k2 = op.apply(self.coeffs[1] * y1 , ypfunction.apply(t[i] + h / 2))
            y2 = ystar[i] + k2 * h / 2
            k3 = op.apply(self.coeffs[1] * y2 , ypfunction.apply(t[i] + h / 2))
            y3 = ystar[i] + k3 * h
            k4 = op.apply(self.coeffs[1] * y3 , ypfunction.apply(t[i] + h))
            ystar[i + 1] = ystar[i] + (k1 + 2 * k2 + 2 * k3 + k4) * h / 6
        return fun.InterpolatingFunction(t, ystar,lower,upper)
 def nsolve(self,h,lower,upper):
     #constant coefficients
     q0=np.matrix(str(self.cond)).transpose()
     t=list(np.arange(lower,upper+h,h))
     a=np.matrix(np.zeros((self.order,self.order)))
     a[:(self.order-1),1:]=np.identity(self.order-1)
     coeffs=self.coeffs
     coeffs=coeffs[::-1]
     coeffs=coeffs[:-1]
     a[-1:]=coeffs
     qstar=np.matrix(np.zeros((self.order,len(t))))
     qstar[:,0]=q0
     for i in range(0, len(t) - 1):
         b=np.matrix(np.array([[0],[0],[self.func.apply(i)]]))
         k1=a*qstar[:,i]+b
         q1=qstar[:,i]+k1*h/2
         k2=a*q1+b
         qstar[:,i+1]=qstar[:,i]+k2*h
     return fun.InterpolatingFunction(t, np.array(qstar)[0],lower,upper)
#comparing numerical and exact solutions of example higher order diffy eq via graphing

import numpy as np
import matplotlib.pyplot as plt
from math import *

import numSolveDQ.modules.dqsolve as dqs
import numSolveDQ.modules.function as fun

#diffy eq is:
# of order 3
#init conds: y''(x=0)=0, y'(x=0)=-1 , y(x=0)=0
#eq is: 1*y''' = -4*y'' -6*y' -4*y +1
new = dqs.DifferentialEquation(3, [0, -1, 0], [1, -4, -6, -4], 1)
ans = new.nsolve(.05, 0, 5)
ans.graph()
#exact solution:
x = [j for j in list(np.arange(0, 5, .05))]
y = [
    1 / 4 + exp(-t) * (cos(t) - 5 * sin(t) / 2) - 5 * exp(-2 * t) / 4
    for t in list(np.arange(0, 5, .05))
]
sus = fun.InterpolatingFunction(x, y, 0, 5)
sus.graph()

#plotting both to compare
plt.plot(ans.x, ans.y, 'r--', x, y)
plt.show()
import numexpr as ne
from math import *

import numSolveDQ.modules.neville as nev
import numSolveDQ.modules.dqsolve as dqs
import numSolveDQ.modules.function as fun

bob = dqs.FirstDEQ(3, [1, -2])  # the dq being solved is: y'=-2y where
ans = bob.nsolve(.025, 0,
                 10)  #being solved from x=0 to x=10 in 0.025 increments
#smaller increments means better accuracy at the cost of execution time and storage
ans.graph()
#the exact soln:
x = [j for j in list(np.arange(0, 10, .025))]
y = [3 * exp(-2 * i) for i in list(np.arange(0, 10, .025))]
sus = fun.InterpolatingFunction(x, y, 0, 10)
sus.graph()
#plotting them together
plt.plot(ans.x, ans.y, 'r--', x, y)
plt.show()
#show them zoomed in

#testing the computed soln to the known exact soln
#these should match:
print(ans.apply(3.73))
print(3 * exp(-2 * 3.73))
#and these should match:
print(ans.apply(6.725))
print(3 * exp(-2 * 6.725))

#plotting the error between the numerical and exact soln