ClosestPairProblem Lab03 ADA
ClosestPairProblem Lab03 ADA
..
Lab03 - ADA
CUI:20103680
27 de octubre de 2019
1. To Do
El Closest Pair Problem es viable resolverlo mediante dos tecnicas conocidas en el diseño
de algoritmos (Brute-Force y Divide and Conquer), seguidamente se demostrara la Com-
plejidad Temporal de ambos metodos de forma empirica y teorica con los mismos datos,
generando un csv file y graficandolo en RStudio.
1.1. ALGORITHMS
A continuación se presenta los algoritmos mencionados en la sección anterior.
1
Algoritmo 2 Algoritmo de Divide y Venceras - Closest Pair Problem
1: procedure divideAndConquer(points)
2: pointsSortedByX ← points
3: pointsSortedByY ← points
4: return ← divideAndConquer(pointsSortedByX,pointsSortedByY)
5: procedure divideAndConquer(pointsSortedByX,pointsSortedByY)
6: if pointsSortedByX.size <= 3 then
7: return ← bruteForce(pointsSortedByX)
8: lef tOf Center ← pointsSortedByX
9: rightOf Center ← pointsSortedByX
10: tempList ←sortByY(leftOfCenter)
11: closestP air ← divideAndConquer(leftOfCenter,tempList)
12: tempList ←sortByY(rightOfCenter)
13: closestP airRight ← divideAndConquer(rightOfCenter,tempList)
14: closestP air ←min(closestPair,closestPairRight)
15: shortestDistance ← closestPair.distance
16: centerX ← rightOfCenter.get(0).x;
17: tempList.clear
18: foreach P oint ∈ pointsSortedByY do
19: tempList ← centerX - Point.x <shortestDistance
20: end foreach
21: for tempList do
22: P oint1 ← tempList.get(i)
23: for tempList do
24: P oint2 ← tempList.get(j)
25: if Point2.y-Point1.y >=shortestDistance then
26: BREAK
27: if P air.distance(point1, point2) < closestPair.distance then
28: closestP air ← (Point1,Point2,distance(point1, point2))
29: shortestDistance ← distance(point1, point2)
30: return ← closestPair
2
1.2. CODING
Para la implementación se uso JAVA, en la Clase ClosestPair se encuentra las funcio-
nes de clase divideAndConquer y bruteForce, las cuales son llamadas por TimeWatch,
generando objetos de la Clase Point desde 100 a 1000000 con pasos de 500, ejecutan-
do bruteForce y luego divideAndConquer, para posteriormente guardar en un archivo
ClosestP airT est100to1000000.csv el numero de datos y los respectivos tiempos de eje-
cución para cada algoritmo.
p u b l i c c l a s s Point {
p u b l i c f i n a l double x ;
p u b l i c f i n a l double y ;
p u b l i c Point ( double x , double y ) {
this .x = x;
this .y = y;
}
public String toString () {
return " ( " + x + " , ␣" + y + " ) " ; }
}
p u b l i c c l a s s TimeWatch {
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) throws IOException {
L i s t <S t r i n g > r e g = new A r r a y L i s t <S t r i n g > ( ) ;
L i s t <Point> p o i n t s = new A r r a y L i s t <Point > ( ) ;
F i l e W r i t e r f w r i t e r = new F i l e W r i t e r ( " C l o s e s t P a i r _ T e s t 1 0 0 t o 5 0 0 . c s v " ) ;
S t r i n g time = n u l l , tmp = n u l l ;
// b o o l e a n swDQ_FB = f a l s e ; // F a l s e i s ForceBruta
f o r ( i n t i = 1 0 0 ; i <= 5 0 0 ; i += 1 0 0 ) {
AlgorithmOne a l g o r i t h m = new AlgorithmOne ( ) ;
System . out . p r i n t ( " T e s t i n g ␣ " + a l g o r i t h m . d e s c r i p t i o n ( ) + " : ␣ " ) ;
generarRandData ( i , p o i n t s ) ;
// f i r s t time i s swDQ_FB = 0
f o r ( i n t swDQ_FB = 0 ; swDQ_FB <= 1 ; swDQ_FB++) {
i f (swDQ_FB == 0 )
time = " " ;
l o n g s t a r t _ t i m e = System . c u r r e n t T i m e M i l l i s ( ) ;
l o n g nano_time_start = System . nanoTime ( ) ;
b o o l e a n s t a t e = a l g o r i t h m . run ( p o i n t s , swDQ_FB ) ;
i f ( state )
System . out . p r i n t l n ( " A l l ␣OK. ␣ ␣ " + swDQ_FB ) ;
else
System . out . p r i n t l n ( " Something ␣ went ␣ wrong ! " ) ;
l o n g end_time = System . c u r r e n t T i m e M i l l i s ( ) ;
l o n g nano_time_end = System . nanoTime ( ) ;
f l o a t tm = ( nano_time_end − nano_time_start ) / 1000000000F ;
System . out . p r i n t l n ( tm ) ;
i f (swDQ_FB == 0 )
time = i + " , " + S t r i n g . v a l u e O f ( tm) + " , " ;
e l s e { time += S t r i n g . v a l u e O f ( tm ) ; }
}
System . out . p r i n t l n ( time ) ;
r e g . add ( time ) ;
f w r i t e r . w r i t e ( time ) ;
f w r i t e r . append ( ’ \n ’ ) ;
}
3
fwriter . flush ();
fwriter . close ();
}
p r i v a t e s t a t i c v o i d generarRandData ( i n t numPoints , L i s t <Point> p o i n t s ) {
Random r = new Random ( ) ;
f o r ( i n t i = 0 ; i < numPoints ; i ++)
p o i n t s . add ( new P o i n t ( r . nextDouble ( ) , r . nextDouble ( ) ) ) ;
System . out . p r i n t l n ( " Generated ␣ " + numPoints + " ␣random␣ p o i n t s " ) ;
}
}
p u b l i c c l a s s AlgorithmOne implements I A l g o r i t h m {
public String description () {
r e t u r n new S t r i n g ( " C l o s e s t ␣ P a i r ␣ Problem " ) ;
}
p u b l i c b o o l e a n run ( L i s t <Point> p o i n t s , i n t swDQ_FB) {
i f (swDQ_FB!=0) {
P a i r d q C l o s e s t P a i r = C l o s e s t P a i r . divideAndConquer ( p o i n t s ) ;
System . out . p r i n t l n ( " D i v i d e ␣and␣ c onqu er : ␣ " + d q C l o s e s t P a i r ) ;
} else {
Pair bfClosestPair = ClosestPair . bruteForce ( points ) ;
System . out . p r i n t l n ( " Brute ␣ f o r c e : ␣ " + b f C l o s e s t P a i r ) ;
}
return true ;
}
@Override
p u b l i c b o o l e a n run ( ) {
return f a l s e ;
}
}
public c l a s s Pair {
p u b l i c Point point1 = n u l l ;
p u b l i c Point point2 = n u l l ;
p u b l i c double d i s t a n c e = 0 . 0 ;
p u b l i c P a i r ( ) {}
p u b l i c Pair ( Point point1 , Point point2 ) {
t h i s . point1 = point1 ;
t h i s . point2 = point2 ;
calcDistance ( ) ;
}
p u b l i c v o i d update ( P o i n t p o i n t 1 , P o i n t p o i n t 2 , d o u b l e d i s t a n c e ) {
t h i s . point1 = point1 ;
t h i s . point2 = point2 ;
this . distance = distance ;
}
public void calcDistance () {
t h i s . d i s t a n c e = d i s t a n c e ( point1 , point2 ) ;
}
public String toString () {
r e t u r n p o i n t 1 + "−" + p o i n t 2 + " ␣ : ␣ " + d i s t a n c e ;
}
p u b l i c s t a t i c d o u b l e d i s t a n c e ( P o i n t p1 , P o i n t p2 ) {
d o u b l e x d i s t = p2 . x − p1 . x ;
d o u b l e y d i s t = p2 . y − p1 . y ;
r e t u r n Math . hypot ( x d i s t , y d i s t ) ; }
}
4
public class ClosestPair {
p u b l i c s t a t i c P a i r b r u t e F o r c e ( L i s t <? e x t e n d s Point> p o i n t s ) {
i n t numPoints = p o i n t s . s i z e ( ) ;
i f ( numPoints < 2 )
return null ;
P a i r p a i r = new P a i r ( p o i n t s . g e t ( 0 ) , p o i n t s . g e t ( 1 ) ) ;
i f ( numPoints > 2 ) {
f o r ( i n t i = 0 ; i < numPoints − 1 ; i ++) {
Point point1 = p o i n t s . get ( i ) ;
f o r ( i n t j = i + 1 ; j < numPoints ; j ++) {
Point point2 = p o i n t s . get ( j ) ;
double d i s t a n c e = Pair . d i s t a n c e ( point1 , point2 ) ;
i f ( distance < pair . distance )
p a i r . update ( p o i n t 1 , p o i n t 2 , d i s t a n c e ) ;
}
}
}
return pair ;
}
p r i v a t e s t a t i c P a i r divideAndConquer
( L i s t <?e x t e n d s Point>pointsSortedByX , L i s t <?e x t e n d s Point>pointsSortedByY ) {
i n t numPoints = pointsSortedByX . s i z e ( ) ;
i f ( numPoints <= 3 ) r e t u r n b r u t e F o r c e ( pointsSortedByX ) ;
i n t d i v i d i n g I n d e x = numPoints >>> 1 ;
5
L i s t <? e x t e n d s Point> l e f t O f C e n t e r
=pointsSortedByX . s u b L i s t ( 0 , d i v i d i n g I n d e x ) ;
L i s t <? e x t e n d s Point> r i g h t O f C e n t e r
=pointsSortedByX . s u b L i s t ( d i v i d i n g I n d e x , numPoints ) ;
tempList . c l e a r ( ) ;
t e m p L i s t . add All ( r i g h t O f C e n t e r ) ;
sortByY ( t e m p L i s t ) ;
P a i r c l o s e s t P a i r R i g h t = divideAndConquer ( r i g h t O f C e n t e r , t e m p L i s t ) ;
tempList . c l e a r ( ) ;
double s h o r t e s t D i s t a n c e = c l o s e s t P a i r . d i s t a n c e ;
d o u b l e cen terX = r i g h t O f C e n t e r . g e t ( 0 ) . x ;
f o r ( P o i n t p o i n t : pointsSortedByY )
i f ( Math . abs ( cen terX − p o i n t . x ) < s h o r t e s t D i s t a n c e )
t e m p L i s t . add ( p o i n t ) ;
f o r ( i n t i = 0 ; i < t e m p L i s t . s i z e ( ) − 1 ; i ++) {
Point point1 = tempList . get ( i ) ;
f o r ( i n t j = i + 1 ; j < t e m p L i s t . s i z e ( ) ; j ++) {
Point point2 = tempList . get ( j ) ;
i f ( ( p o i n t 2 . y − p o i n t 1 . y ) >= s h o r t e s t D i s t a n c e )
break ;
double d i s t a n c e = Pair . d i s t a n c e ( point1 , point2 ) ;
i f ( distance < closestPair . distance ) {
c l o s e s t P a i r . update ( p o i n t 1 , p o i n t 2 , d i s t a n c e ) ;
shortestDistance = distance ;
}
}
6
1.3. RESULTADOS
Inicialmente se realizo una test de datos de 100 a 500 datos, comprobando el correcto
funcionamiento de ambos algoritmos al coincidir con el mismo par de Puntos mas Cer-
cano. Seguidamente para tener un panorama mas amplio, se aplico con la generación de
100 a 1000000 con paso de 900 datos, obteniendo los resultados en otro archivo csv.
7
Figura 1.3: Funciones
1.4. QUESTIONS
1.4.1. How much time take the algorithm with 100, 1000, 10000 and
1000000 of random points?
Los datos especificos se pueden revisar en el archivo ClosestP air1 00to1000000Data.csv,
sin embargo para cantidades de datos entre 100 y 1000, la diferencia de tiempo es im-
perceptible, es a partir de los 4000 donde se dispara considerablemente el tiempo de
ejecucion de fuerza bruta llegando a 6seg frente a 0.1seg de divide y venceras.
8
1.4.2. What are the plots for each test.
9
1.4.3. What can you describe about the plots for each test?
La grafica de ForceBrute parece una parabola, dando la posibilidad de presumir un
O(n2 ), seguidamente la grafica de DivideAndConquer parece una logaritmo O(n∗log2 (n)∗
log2 (n))
1.4.4. What would be the limits of points for a comparison between the
brute-force and divide and conquer approach.
El algoritmo de ForceBrute calcularia la distancia entre todos los posibles par de puntos,
en cambio DivideAndConquer subdivide los puntos ordenandolos por cada dimension y
calcula el minimo.
Referencias
[1] Time complexity analysis - How to calculate running time?-Youtube, Reed, Bruce,
Proceedings of the thirty-second annual ACM symposium on Theory of computing,
10