git » metnum-tp1.git » commit 7907c8f

Agregar gráficos

author Alberto Bertogli
2010-09-07 00:29:44 UTC
committer Alberto Bertogli
2010-09-07 01:28:24 UTC
parent e4926de3f18309aa13d40c267998582939bcc071

Agregar gráficos

Este commit agrega algunos scripts para generar automáticamente los gráficos.
Seguro faltan varios, pero es un comienzo.

Tiene dos partes: una que genera los datos en crudo, y otra que grafica.

La generación de los datos consiste en ejecutar los distintos algoritmos, y
pasar su salida (que fue estandarizada en commits anteriores) por un
scriptcito en Python que calcula el error de cada resultado con precisión fija
en 90 digitos, que es mas que suficiente.

Luego, se generan los gráficos con gnuplot, utilizando los datos de esos
archivos.

Tambien se agregaron targets en el Makefile para que todo eso se pueda hacer
automáticamente con "make plot".

Se modificaron binomial y binomial_inc para que vayan emitiendo los resultados
a medida que se generan, para optimizar las corridas.

.gitignore +3 -0
Makefile +16 -0
binomial.cpp +3 -2
binomial_inc.cpp +3 -2
err.py +30 -0
gen_plot_data.sh +74 -0
plot.gpi +94 -0

diff --git a/.gitignore b/.gitignore
index 332b482..bc38cef 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,6 @@ binomial_dec
 fcont
 fcont_int
 
+out/
+plot/
+
diff --git a/Makefile b/Makefile
index 312759d..eafd74f 100644
--- a/Makefile
+++ b/Makefile
@@ -27,6 +27,7 @@ binomial_inc: $(OBJS) binomial_inc.o
 binomial_dec: $(OBJS) binomial_dec.o
 	$(CXX) $(CXXFLAGS) $^ -o $@
 
+
 clean:
 	rm -f $(OBJS)
 	rm -f calc.o calc
@@ -37,3 +38,18 @@ clean:
 	rm -f binomial_inc binomial_inc.o
 	rm -f binomial_dec binomial_dec.o
 
+plot_data: out/plot_data
+
+out/plot_data: all
+	mkdir -p out
+	./gen_plot_data.sh
+	touch out/plot_data
+
+plot: plot_data plot.gpi
+	mkdir -p plot/
+	gnuplot plot.gpi
+
+clean_plot:
+	rm -rf out/
+	rm -rf plot/
+
diff --git a/binomial.cpp b/binomial.cpp
index 18c6efd..24611c4 100644
--- a/binomial.cpp
+++ b/binomial.cpp
@@ -55,9 +55,10 @@ int main(int argc, char *argv[])
 		printf("  ---\n");
 		#endif
 		//printf(" %d %.60f 0x%" print_64t "x\n", i, n.to_double(), to_u64(n));
-	}
 
-	print_result(nterm, n);
+		/* Vamos emitiendo los resultados a medida que los tenemos */
+		print_result(i, n);
+	}
 
 	return 0;
 }
diff --git a/binomial_inc.cpp b/binomial_inc.cpp
index a350eb6..39587e5 100644
--- a/binomial_inc.cpp
+++ b/binomial_inc.cpp
@@ -64,9 +64,10 @@ int main(int argc, char *argv[])
 		printf("  ---\n");
 		#endif
 		//printf(" %d %.60f 0x%" print_64t "x\n", i, n.to_double(), to_u64(n));
-	}
 
-	print_result(nterm, n);
+		/* Vamos emitiendo los resultados a medida que los tenemos */
+		print_result(i + 1, n);
+	}
 
 	return 0;
 }
diff --git a/err.py b/err.py
new file mode 100755
index 0000000..e80ae18
--- /dev/null
+++ b/err.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+
+"""
+Esta utilidad recibe la salida de los distintos algoritmos (que esta siempre
+en el mismo formato), y la emite tal cual, pero agregando al final de cada
+linea el error del resultado, comparandolo con uno conocido y utilizando
+aritmetica de precision fija a 90 digitos.
+"""
+
+import sys
+from decimal import Decimal, getcontext
+
+# Precision de los decimales a 90 digitos
+getcontext().prec = 90
+
+# Cargamos la posta, tiene 98 digitos
+P = Decimal('1.41421356237309504880168872420969807856967187537694807317667973799073247846210703885038753432764157')
+
+# Procesamos la entrada
+for l in sys.stdin.readlines():
+	niters, prec, resultado, res_hex = l.split()
+
+	# Calculamos el error, escalado en 100 millones para graficarlo mejor
+	# ya que gnuplot usa doubles
+	r = Decimal(resultado)
+	error = abs(P - r) * 100 * 1000000
+
+	print l.strip(), error
+
+
diff --git a/gen_plot_data.sh b/gen_plot_data.sh
new file mode 100755
index 0000000..10a3c86
--- /dev/null
+++ b/gen_plot_data.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+# Directorio de salida, coordinado con el graficador
+OUTDIR="out/"
+mkdir -p $OUTDIR
+
+# Minima y maxima precision a calcular
+minprec=10
+maxprec=51
+
+# Tabla con los algoritmos a usar, y la cantidad minima y maxima de
+# iteraciones para el mismo
+declare -A maxiter
+declare -A miniter
+miniter["babilonio"]=1
+maxiter["babilonio"]=50
+miniter["binomial"]=1
+maxiter["binomial"]=300
+miniter["binomial_inc"]=1
+maxiter["binomial_inc"]=300
+miniter["binomial_dec"]=10
+maxiter["binomial_dec"]=300
+miniter["fcont"]=1
+maxiter["fcont"]=50
+miniter["fcont_int"]=1
+maxiter["fcont_int"]=50
+
+# Algunos algoritmos son incrementales, y nos dan los resultados en cada
+# iteración hasta que llegan a la indicada en la linea de comandos, para
+# optimizar las corridas. Estos estan indicados en este arreglo.
+declare -A isincr
+isincr["binomial"]=1
+isincr["binomial_inc"]=1
+
+algolist=${!maxiter[*]}
+
+
+# Corremos y guardamos en archivos por algoritmo y por precision
+for algo in $algolist; do
+	echo -n "$algo " >&2
+	for prec in `seq $minprec $maxprec`; do
+		echo -n "$prec " >&2
+		OF="$OUTDIR/OUT-$algo-prec:$prec"
+		rm -f "$OF"
+
+		# Si no es incremental, entonces hacemos nosotros a mano el
+		# loop para cada iteración; sino directamente corremos el
+		# programa con la máxima iteración buscada
+		if [ "${isincr[$algo]}" == "" ]; then
+			for iter in `seq ${miniter[$algo]} ${maxiter[$algo]}`; do
+				./$algo $prec $iter >> "$OF"
+			done
+		else
+			./$algo $prec ${maxiter[$algo]} > "$OF"
+		fi
+
+		# Obtenemos los errores de cada resultado
+		cat "$OF" | ./err.py > "$OF-err"
+	done
+	echo >&2
+done
+
+
+# Obtenemos archivos por iteracion, asegurandonos que esten bien ordenados
+# para no confundir al graficador
+echo "iter split"
+for algo in $algolist; do
+	for iter in `seq 1 ${maxiter[$algo]}`; do
+		cat "$OUTDIR"/OUT-$algo-prec:*-err | egrep "^$iter" \
+			| sort -n -k 2 \
+			> "$OUTDIR/OUT-$algo-iter:$iter-err"
+	done
+done
+
diff --git a/plot.gpi b/plot.gpi
new file mode 100644
index 0000000..1f2e43e
--- /dev/null
+++ b/plot.gpi
@@ -0,0 +1,94 @@
+
+set terminal png enhanced size 1024,768
+set autoscale
+set style data linespoints
+
+#
+# Error con precision fija e iteración variable
+#
+
+set ylabel "Error * 100 millones"
+
+set xlabel "Iteración"
+
+# Babilonio
+set output "plot/babilonio-err-p:51.png"
+set title "Babilonio con precisión 51 - Error"
+plot \
+	'out/OUT-babilonio-prec:51-err' using 1:5 title "Babilonio"
+
+set output "plot/babilonio-err-p:51-detalle.png"
+set title "Babilonio con precisión 51 - Error - Detalle"
+plot [2:10] \
+	'out/OUT-babilonio-prec:51-err' using 1:5 title "Babilonio"
+
+# Binomial
+set output "plot/binomial-err-p:51.png"
+set title "Binomial con precisión 51 - Error"
+plot \
+	'out/OUT-binomial-prec:51-err' using 1:5 title "Binomial", \
+	'out/OUT-binomial_inc-prec:51-err' using 1:5 title "Binomial inc", \
+	'out/OUT-binomial_dec-prec:51-err' using 1:5 title "Binomial dec"
+
+set output "plot/binomial-err-p:51-detalle.png"
+set title "Binomial con precisión 51 - Error - Detalle"
+plot [25:] \
+	'out/OUT-binomial-prec:51-err' using 1:5 title "Binomial", \
+	'out/OUT-binomial_inc-prec:51-err' using 1:5 title "Binomial inc", \
+	'out/OUT-binomial_dec-prec:51-err' using 1:5 title "Binomial dec"
+
+# Fracciones continuas
+set output "plot/fcont-err-p:51.png"
+set title "Fracciones continuas con precisión 51 - Error"
+plot \
+	'out/OUT-fcont-prec:51-err' using 1:5 title "Frac. continuas", \
+	'out/OUT-fcont_int-prec:51-err' using 1:5 title "Frac. continuas int"
+
+set output "plot/fcont-err-p:51-detalle.png"
+set title "Fracciones continuas con precisión 51 - Error - Detalle"
+plot [3:10] \
+	'out/OUT-fcont-prec:51-err' using 1:5 title "Frac. continuas", \
+	'out/OUT-fcont_int-prec:51-err' using 1:5 title "Frac. continuas int"
+
+
+# Comparativas
+set output "plot/todos-err-p:51-detalle.png"
+set title "Comparativa con precisión 51 - Error - Detalle"
+plot [25:] \
+	'out/OUT-fcont-prec:51-err' using 1:5 title "Frac. continuas", \
+	'out/OUT-fcont_int-prec:51-err' using 1:5 title "Frac. continuas int", \
+	'out/OUT-binomial-prec:51-err' using 1:5 title "Binomial", \
+	'out/OUT-binomial_inc-prec:51-err' using 1:5 title "Binomial inc", \
+	'out/OUT-binomial_dec-prec:51-err' using 1:5 title "Binomial dec", \
+	'out/OUT-babilonio-prec:51-err' using 1:5 title "Babilonio"
+
+
+#
+# Error con precision variable e iteración fija
+#
+
+set xlabel "Precisión (dígitos)"
+
+# Babilonio
+set output "plot/babilonio-err-i:50.png"
+set title "Babilonio en iteración 50 - Error"
+plot \
+	'out/OUT-babilonio-iter:50-err' using 2:5 title "Babilonio"
+
+# Binomial
+set output "plot/binomial-err-i:100.png"
+set title "Binomial en iteración 100 - Error"
+plot \
+	'out/OUT-binomial-iter:100-err' using 2:5 title "Binomial", \
+	'out/OUT-binomial_inc-iter:100-err' using 2:5 title "Binomial inc", \
+	'out/OUT-binomial_dec-iter:100-err' using 2:5 title "Binomial dec"
+
+# Fracciones continuas
+set output "plot/fcont-err-i:10.png"
+set title "Fracciones continuas en iteración 10 - Error"
+plot \
+	'out/OUT-fcont-iter:10-err' using 2:5 title "Frac. continuas", \
+	'out/OUT-fcont_int-iter:10-err' using 2:5 title "Frac. continuas int"
+
+# Comparativas
+