#!/usr/bin/env python
#  Copyright (C) 2019 Tomas Arturo Herrera Castro <taherrera@uc.cl>
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
# 
#  This was code was writen by Chilean Software and Hardware developer 
#  company Southern Lake Technologies as part of its blog.
# 
#  http://www.sltech.cl
#

from scipy.optimize import minimize

# O = output
# m = minus
# p = plus

def get_restrictions():
	Vpp = 4
	Vss = 1
	Om_0kPa = 2.31
	Op_0kPa = 2.31
	Om_40kPa = 2.27
	Op_40kPa = 2.34

	eq1 = lambda R: Vss - Vout(R[0],R[1],R[2],R[3],	Om_0kPa, 	Op_0kPa)
	eq2 = lambda R: Vpp - Vout(R[0],R[1],R[2],R[3],	Om_40kPa, 	Op_40kPa)
	restriction = [	{"type":"eq", 	"fun":eq1	}, 
					{"type":"eq",	"fun":eq2	}]
	return restriction

def get_bounds(rmin = 100, rmax=1e5):
	return (	(rmin, rmax),
				(rmin, rmax),
				(rmin, rmax),
				(rmin, rmax))

# maximizar el valor de las resistencias (impedancia de entrada alta)
def fun_objetivo(R):
	return -(sum(R)) 

# digamos que V1 es el Output - y V2 es Output +
def Vout(R1, R2, R3, R4, V1, V2):
	return V2*R4/(R2+R4)*(1+R3/R1) - V1*R3/R1


if __name__ == "__main__":
	r0 = (1e2,1e2,1e4,1e4)
	b = get_bounds()
	res = minimize(fun_objetivo, r0, bounds = b, constraints=get_restrictions())
	print res
	# Esto es solo verificacion
	print "Solo para verificar:"
	R = res.x
	Om = 2.31
	Op = 2.31
	print "Cuando Om = {}V y Op = {}V, Vout={}V".format(Om, Op, Vout(R[0],R[1],R[2],R[3],	Om, 	Op))
	Om = 2.27
	Op = 2.34
	print "Cuando Om = {}V y Op = {}V, Vout={}V".format(Om, Op, Vout(R[0],R[1],R[2],R[3],	Om, 	Op))


