<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
Step2:  Numerical Integration
Step3:  Below is, mathematically, $f_{-h} 
Step4:  Then, we can use sympy to calculate, symbolically, $f_{h} 
Step5:  Success! Trapezoid rule was rederived (stop using pen/pencil and paper or chalkboard; computers can do computations faster and without mistakes)
For a second order polynomial, $p_{N=2}(x)$,
Step6:  Legendre Polynomials
I don't find the sympy documentation very satisfying (other than listing the argument syntax, no examples of usage, nor further explanation, beyond the barebones argument syntax, is given).  So what I've done here is to try to show what I've done.
<ASSISTANT_TASK:>
Python Code:
from itertools import combinations
import sympy
from sympy import Function, integrate, Product, Sum, Symbol, symbols
from sympy.abc import a,b,h,i,k,m,n,x
from sympy import Rational as Rat
def lagrange_basis_polys(N,x,xpts=None):
    
    lagrange_basis_polynomials(N,x,xpts)
    returns the Lagrange basis polynomials as a list
    
    INPUTS/PARAMETERS
    -----------------
    <int> N - N > 0.  Note that there are N+1 points total
    <sympy.Symbol> x
    <list> xpts
    
    assert N > 0
    if xpts != None:
        assert len(xpts) == N + 1
    if xpts == None:
        print "I'll generate symbolic sympy symbols for you for xpts"
        xpts = symbols('x0:'+str(N+1))
        
    basis_polys = []
    for i in range(N+1):
        tmpprod = Rat(1)
        for k in [k for k in range(N+1) if k != i]:
            tmpprod = tmpprod * (x - xpts[k])/(xpts[i]-xpts[k])
        basis_polys.append(tmpprod)
    return basis_polys
def lagrange_interp(N,x,xpts=None,ypts=None):
    
    lagrange_interp(N,x,xpts,ypts)
    Lagrange interpolation formula
    
    if xpts != None and ypts != None:
        assert len(xpts) == len(ypts)
    
    if xpts == None:
        print "I'll generate symbolic sympy symbols for you for xpts"
        xpts = symbols('x0:'+str(N+1))
    if ypts == None:
        print "I'll generate symbolic sympy symbols for you for xpts"
        ypts = symbols('y0:'+str(N+1))
        
    basis = lagrange_basis_polys(N,x,xpts)
    p_N = sum( [ypts[i]*basis[i] for i in range(N+1)] )
    return p_N
xpts = symbols('x0:'+str(1+1))
ypts = symbols('y0:'+str(1+1))
p_1x = lagrange_interp(1,x,xpts,ypts)
Explanation: Numerical Integration
End of explanation
x_0 = Symbol('x_0',real=True)
f = Function('f')
f_minush = p_1x.subs({xpts[0]:x_0-h,xpts[1]:x_0, ypts[0]:f(x_0-h), ypts[1]:f(x_0) })
integrate( f_minush, (x,x_0-h,x_0 ) )
Explanation: Below is, mathematically, $f_{-h} := p_1(x)$ with $(x_0,y_0) = (x_0-h, f(x_0-h)), (x_1,y_1) = (x_0,f(x_0))$ and
$\int_{x_0-h}^{x_0} f_{-h}$
End of explanation
f_h = p_1x.subs({xpts[0]:x_0,xpts[1]:x_0+h, ypts[0]:f(x_0), ypts[1]:f(x_0+h) })
integrate( f_h, (x,x_0,x_0+h ) )
( integrate( f_minush, (x,x_0-h,x_0 ) ) + integrate( f_h, (x,x_0,x_0+h ) )  ).simplify()
Explanation: Then, we can use sympy to calculate, symbolically, $f_{h} := p_1(x)$ with $(x_0,y_0) = (x_0, f(x_0)), (x_1,y_1) = (x_0+h,f(x_0+h))$ and
$\int_{x_0}^{x_0+h} f_{h}$
End of explanation
xpts = symbols('x0:'+str(2+1))
ypts = symbols('y0:'+str(2+1))
p_2x = lagrange_interp(2,x,xpts,ypts)
f2_h = p_2x.subs({xpts[0]:x_0-h,xpts[1]:x_0,xpts[2]:x_0+h,ypts[0]:f(x_0-h), ypts[1]:f(x_0),ypts[2]:f(x_0+h) })
integrate( f2_h,(x,x_0-h,x_0+h)).simplify()
Explanation: Success! Trapezoid rule was rederived (stop using pen/pencil and paper or chalkboard; computers can do computations faster and without mistakes)
For a second order polynomial, $p_{N=2}(x)$,
End of explanation
from sympy.polys.orthopolys import legendre_poly
print "n \t \t \t \t P_n(x) \n"
for i in range(11):
    print str(i) + "\t \t \t \t " , legendre_poly(i,x) 
sympy.latex(legendre_poly(2,x))
sympy.N( sympy.integrate(1/(2+x**2),(x,0,3)) )
Explanation: Legendre Polynomials
I don't find the sympy documentation very satisfying (other than listing the argument syntax, no examples of usage, nor further explanation, beyond the barebones argument syntax, is given).  So what I've done here is to try to show what I've done.
End of explanation
<END_TASK>