import numpy as np
import sympy
import matplotlib.pyplot as plt



def false_position(function, aa, bb, eps = 0.001, nombre = 'Gráfica',
    iteraciones = 30, graph = True, err_graph = False):
	a = float(aa)
	b = float(bb)
	m = 0.
	n = 0
	err = float(abs((a-b)/2))
	err_steps = [err]
	
	def f(x):
		return eval(function)
		
	domain = np.linspace(a,b,1000)
	plt.plot(domain,f(domain))
	plt.grid(True, which='both')
	plt.axhline(y=0, color='k')
	plt.axvline(x=0, color='k')
	plt.title(nombre)
	if graph:
		plt.show()
	plt.close()

	while eps < err:
		if n < iteraciones:	
			try:
				m = b - (f(b) * (a - b))/(f(a) - f(b))
				n += 1
			except ZeroDivisionError:
				print('Error por división de cero: f(a) y f(b) son iguales. Pruebe'
							    + ' nuevo intervalo')
				break	
			
			if f(m) == 0:
				print('Raíz exacta: ' + str(m))
				break
			
			if f(a)*f(m)<0:
				a, b = a, m
				b=m
			else:
				a, b = m, b
			
			err = abs((a-b)/2)
			err_steps.append(err)
			print('Nuevo valor: ' + str(m) + '. Loop Nº' + str(n) +
						    '. Error: ' + str(err))
		
		else:
			print('End of loop \n \n')
			break
	m = (a + b) / 2
	print('Nuevo valor: %f. Loop Nº %f. Error: %f' % (m, n, err))

	if err_graph:
		domain_err = np.arange(len(err_steps))
		plt.plot(domain_err, err_steps)
		plt.grid(True, which='both')
		plt.axhline(y=0, color='k')
		plt.axvline(x=0, color='k')
		plt.yscale('log')
		plt.show()
		plt.close()


def biparticion(function, aa, bb, eps=0.001, nombre = 'Grafica',
    iteraciones = 30, graph = True, err_graph = False):
	a = float(aa)
	b = float(bb)
	m = 0
	n = 0
	err = abs((a-b)/2)
	err_steps = [err]

	def f(x):
		return eval(function)


	domain = np.linspace(a, b, 1000)
	plt.plot(domain, f(domain))
	plt.grid(True, which='both')
	plt.axhline(y = 0, color = 'k')
	plt.axvline(x = 0, color = 'k')
	plt.title(nombre)
	if graph:
		plt.show()
	plt.close()
			
	while eps < err:
		if n < iteraciones:
			m = (a + b) / 2
			n += 1						
			
			if f(m) == 0:
				print('Raíz exacta: ' + str(m))
				break
			
			if f(a) * f(m) < 0:
				a, b = a, m
			else:
				a, b = m, b
				
			err = abs((a-b)/2)
			err_steps.append(err)
			print('Nuevo valor: ' + str(m) + '. Loop Nº' + str(n) + 
						    '. Error: ' + str(err))
		
		else:
			print('End of loop')
			break

	if err_graph:
		domain_err = np.arange(len(err_steps))
		plt.plot(domain_err, err_steps)
		plt.grid(True, which='both')
		plt.axhline(y=0, color='k')
		plt.axvline(x=0, color='k')
		plt.yscale('log')
		plt.show()
		plt.close()

# biparticion(, -2, 6, nombre = 'Ejercicio 2')
# false_position('x - 15**0.5', 3, 4, nombre = 'Ejercicio 2', eps= 0.49)

ecuacion = '-0.13952954729309466/np.sqrt(x**5) - 0.86*np.log(0.07027027027027026/x + (9.168716265367385e-6*x)/np.sqrt(x**5))'
biparticion(ecuacion, 0.2, 0.8, eps=0.00001, iteraciones=10000, err_graph=True)
false_position(ecuacion, 0.2, 0.8, eps=0.00001, iteraciones=100000, err_graph=True)
