# $Id: arg.py,v 1.4 2005/09/26 17:57:49 joan Exp joan $
# -*- encoding: utf8 -*-

"""	Verificación de argumentaciones lógicas
"""

import warnings
warnings.filterwarnings('ignore', category=FutureWarning)

def argument(nprops, premisses, conclusion):
	"""Determina si una conclusión se deriva de una serie de premisas.
	"""
	assert nprops >= 2
	assert len(premisses) >= 1

	def bitand(ns):
		a = -1
		for n in ns: a &= n
		return a

	mask = ~(-1 << 2**nprops)
	premiss = bitand(premisses)
	return ((~premiss | conclusion) & mask) == mask

def propositions(nprops):
	"""Construye una lista de proposiciones para su uso en argumentaciones.
	"""
	assert nprops >= 2

	props = []
	mbits = 2 ** nprops
	for p in range(0, nprops):
		nbits = 1 << (p + 1)
		if p == 0:
			mask = 0x02
		else:
			mask = ((2**(2**p)) - 1) << (nbits >> 1)
		proposition = mask
		for i in range(1, mbits / nbits):
			proposition <<= nbits
			proposition |= mask
		props.append(proposition)
	return props

########################################################################
# Test
########################################################################

if __name__ == '__main__':

	####################################################################
	# Reglas de inferencia
	####################################################################

	(P, Q) = propositions(2)

	# modus ponens
	assert argument(2, (~P|Q, P), Q) is True

	# modus tollens
	assert argument(2, (~P|Q, ~Q), ~P) is True

	# silogismo disyuntivo
	assert argument(2, (P|Q, ~P), Q) is True

	# simplificacion
	assert argument(2, (P&Q,), P) is True
	assert argument(2, (P&Q,), Q) is True

	# conjuncion
	assert argument(2, (P, Q), P&Q) is True

	# adición
	assert argument(2, (P,), P|Q) is True

	(P, Q, R) = propositions(3)

	# silogismo hipotético
	assert argument(3, (~P|Q, ~Q|R), ~P|R) is True

	(P, Q, R, S) = propositions(4)

	# dilema constructivo
	assert argument(4, ((~P|Q) & (~R|S), P|R), Q|S) is True

	# dilema destructivo
	assert argument(4, ((~P|Q) & (~R|S), ~P|~R), ~P|~R) is True

	####################################################################
	# Falacias
	####################################################################

	(P, Q) = propositions(2)

	# afirmar el consecuente
	assert argument(2, (~P|Q, Q), P) is False

	# negar el antecedente
	assert argument(2, (~P|Q, ~P), ~Q) is False

	####################################################################
	# Excepciones
	####################################################################

	try: print propositions(1)
	except: pass

	try: print argument(0,(0,0))
	except: pass

	try: print argument(2,())
	except: pass

# vim:syntax=python
