0% found this document useful (0 votes)
48 views10 pages

ClosestPairProblem Lab03 ADA

This document describes an experiment to compare the time complexity of two algorithms, brute force and divide and conquer, for solving the closest pair problem. It provides pseudocode for the two algorithms. The coding section describes how the algorithms were implemented in Java and how timing tests were run for increasing numbers of random points from 100 to 1000000, with results written to a CSV file.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
48 views10 pages

ClosestPairProblem Lab03 ADA

This document describes an experiment to compare the time complexity of two algorithms, brute force and divide and conquer, for solving the closest pair problem. It provides pseudocode for the two algorithms. The coding section describes how the algorithms were implemented in Java and how timing tests were run for increasing numbers of random points from 100 to 1000000, with results written to a CSV file.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 10

Universidad Nacional de San Agustín, Escuela de Ingenieria de Sistemas

..

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.

Algoritmo 1 Algoritmo de Fuerza Bruta


1: procedure bruteForce(points)
2: numP oints ← points.size
3: if numPoints <2 then
4: return ← null
5: P air ← (points.get(0),points.get(1))
6: if numPoints >2 then
7: for points do
8: P oint1 ← points.get(i)
9: for points do
10: P oint2 ← points.get(j)
11: distance ←Pair.distance(point1, point2)
12: if distance <Pair.distance then
13: P air ← (Point1,Point2,distance(point1, point2))
14: return ← Pair

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 u b l i c s t a t i c v o i d sortByX ( L i s t <? e x t e n d s Point> p o i n t s ) {


C o l l e c t i o n s . s o r t ( p o i n t s , new Comparator<Point >() {
p u b l i c i n t compare ( P o i n t p o i n t 1 , P o i n t p o i n t 2 ) {
i f ( point1 . x < point2 . x)
r e t u r n −1;
i f ( point1 . x > point2 . x)
return 1;
return 0;
}
});
}

p u b l i c s t a t i c v o i d sortByY ( L i s t <? e x t e n d s Point> p o i n t s ) {


C o l l e c t i o n s . s o r t ( p o i n t s , new Comparator<Point >() {
p u b l i c i n t compare ( P o i n t p o i n t 1 , P o i n t p o i n t 2 ) {
i f ( point1 . y < point2 . y)
r e t u r n −1;
i f ( point1 . y > point2 . y)
return 1;
return 0;
}
});
}

p u b l i c s t a t i c P a i r divideAndConquer ( L i s t <? e x t e n d s Point> p o i n t s ) {


L i s t <Point> pointsSortedByX = new A r r a y L i s t <Point >( p o i n t s ) ;
sortByX ( pointsSortedByX ) ;
L i s t <Point> pointsSortedByY = new A r r a y L i s t <Point >( p o i n t s ) ;
sortByY ( pointsSortedByY ) ;
r e t u r n divideAndConquer ( pointsSortedByX , pointsSortedByY ) ;
}

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 ) ;

L i s t <Point> t e m p L i s t = new A r r a y L i s t <Point >( l e f 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 = divideAndConquer ( l e f t O f C e n t e r , t e m p L i s t ) ;

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 ) ;

i f ( closestPairRight . distance < closestPair . distance )


closestPair = closestPairRight ;

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

Figura 1.1: Testing CSV File, 100 to 500 data

100 a 1000000 con paso de 900 datos, obteniendo los resultados en otro archivo csv.

Figura 1.2: Complejidad Temporal:ForceBrute(RED)-DivideAndConquer(GREEN)

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.

Figura 1.4: Time of Execute: time1 (F B), time2 (DC)

8
1.4.2. What are the plots for each test.

Figura 1.5: Time of Execute: Force Brute

Figura 1.6: Time of Execute: Divide and Conquer

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.

Figura 1.7: Divide and Conquer - Generalizado

1.4.5. Demonstrate the cost using master theorem and analytically


Asumiendo T (n) como complejidad de tiempo y el algoritmo de ordenamiento que ga-
rantize n ∗ log2 (n) el cual Java utiliza MergeSort, y seguido de la recursividad 2 ∗ T (n/2)
y finalmente el Orden total es T (n) = n ∗ (log2 (n))2

Figura 1.8: Demostrate Cost

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,

[2] Complexity of Algoritmic for Iterative Solution of Not Linear Equation

10

You might also like