@@ -34,97 +34,109 @@ pub fn form_abstracted_graph(g: &dyn Digraph, node_ids: &Vec<NodeID>) -> AMDigra
34
34
abstracted_graph
35
35
}
36
36
37
- fn get_potential_new_path (
38
- rng : & mut ThreadRng ,
39
- g : & dyn Digraph ,
40
- current_path : & GraphPath ,
41
- ) -> GraphPath {
42
- let mut potential_new_path = current_path . clone ( ) ;
43
-
44
- let node_index_to_mutate = rng . gen_range ( 0 .. ( g . num_vertices ( ) - 1 ) ) ;
37
+ pub struct SimulatedAnnealing < ' a > {
38
+ g : & ' a dyn Digraph ,
39
+ result_data : Vec < ( f64 , f64 ) > ,
40
+ current_path : GraphPath ,
41
+ path_length : f64 ,
42
+ best_path : GraphPath ,
43
+ rng : ThreadRng ,
44
+ }
45
45
46
- let reverse_or_transport: bool = rng. gen ( ) ;
46
+ impl < ' a > SimulatedAnnealing < ' a > {
47
+ pub fn new ( g : & ' a dyn Digraph ) -> Self {
48
+ let mut rng = thread_rng ( ) ;
47
49
48
- if reverse_or_transport {
49
- let node_index_to_swap_with = if node_index_to_mutate < ( g. num_vertices ( ) - 1 ) {
50
- node_index_to_mutate + 1
51
- } else {
52
- 0
50
+ let mut current_path = GraphPath {
51
+ path : ( 0 ..g. num_vertices ( ) ) . map ( NodeIndex ) . collect ( ) ,
53
52
} ;
54
- potential_new_path
55
- . path
56
- . swap ( node_index_to_mutate, node_index_to_swap_with) ;
57
- } else {
58
- // Cyclic permutation
59
- let node_to_move = potential_new_path. path [ node_index_to_mutate] ;
60
- // -2 because we are looking for new position with 1 node missing
61
- let new_node_position = rng. gen_range ( 0 ..( g. num_vertices ( ) - 2 ) ) ;
62
- potential_new_path. path . remove ( node_index_to_mutate) ;
63
- potential_new_path
64
- . path
65
- . insert ( new_node_position, node_to_move)
53
+ current_path. path . shuffle ( & mut rng) ;
54
+
55
+ let path_length = current_path. get_length_on_graph ( g) ;
56
+
57
+ let best_path = current_path. clone ( ) ;
58
+ SimulatedAnnealing {
59
+ g,
60
+ result_data : vec ! [ ] ,
61
+ current_path,
62
+ path_length,
63
+ best_path,
64
+ rng,
65
+ }
66
66
}
67
67
68
- potential_new_path
69
- }
70
-
71
- pub fn travelling_salesman ( g : & dyn Digraph , output_graph : bool ) -> GraphPath {
72
- let mut result_data: Vec < ( f64 , f64 ) > = vec ! [ ] ;
73
-
74
- let mut rng = thread_rng ( ) ;
68
+ pub fn run ( & mut self ) {
69
+ let mut temp = f64:: sqrt ( self . g . num_vertices ( ) as f64 ) ;
70
+ let mut iterations = 0 ;
71
+ while temp > 1e-8_f64 && iterations < ( 100 * self . g . num_vertices ( ) ) {
72
+ let potential_new_path = self . get_potential_new_path ( ) ;
73
+
74
+ let new_path_length = potential_new_path. get_length_on_graph ( self . g ) ;
75
+ if new_path_length < self . path_length {
76
+ self . current_path = potential_new_path;
77
+ self . best_path . clone_from ( & self . current_path ) ;
78
+ self . path_length = new_path_length;
79
+ } else {
80
+ // TODO: Is this between 0 and 1?
81
+ if f64:: exp ( -f64:: abs ( new_path_length - self . path_length ) / temp) > self . rng . gen :: < f64 > ( ) {
82
+ self . current_path = potential_new_path;
83
+ self . path_length = new_path_length;
84
+ }
85
+ }
75
86
76
- let mut current_path = GraphPath {
77
- path : ( 0 ..g . num_vertices ( ) ) . map ( NodeIndex ) . collect ( ) ,
78
- } ;
79
- current_path . path . shuffle ( & mut rng ) ;
80
- let mut path_length = current_path . get_length_on_graph ( g ) ;
87
+ temp *= 0.995 ;
88
+ iterations += 1 ;
89
+ self . result_data . push ( ( temp , self . path_length ) ) ;
90
+ }
91
+ }
81
92
82
- let mut best_path = current_path. clone ( ) ;
93
+ fn get_potential_new_path ( & mut self ) -> GraphPath {
94
+ let mut potential_new_path = self . current_path . clone ( ) ;
83
95
84
- // println!("Initial state");
85
- //
86
- // println!("\t{:?}", best_path.path);
87
- // println!("\t{}", path_length);
96
+ let node_index_to_mutate = self . rng . gen_range ( 0 ..( self . g . num_vertices ( ) - 1 ) ) ;
88
97
89
- let mut temp = f64:: sqrt ( g. num_vertices ( ) as f64 ) ;
90
- let mut iterations = 0 ;
91
- while temp > 1e-8_f64 && iterations < ( 100 * g. num_vertices ( ) ) {
92
- // println!("{}", temp);
93
- let potential_new_path = get_potential_new_path ( & mut rng, g, & current_path) ;
98
+ let reverse_or_transport: bool = self . rng . gen ( ) ;
94
99
95
- let new_path_length = potential_new_path. get_length_on_graph ( g) ;
96
- if new_path_length < path_length {
97
- current_path = potential_new_path;
98
- best_path. clone_from ( & current_path) ;
99
- path_length = new_path_length;
100
+ if reverse_or_transport {
101
+ let node_index_to_swap_with = if node_index_to_mutate < ( self . g . num_vertices ( ) - 1 ) {
102
+ node_index_to_mutate + 1
103
+ } else {
104
+ 0
105
+ } ;
106
+ potential_new_path
107
+ . path
108
+ . swap ( node_index_to_mutate, node_index_to_swap_with) ;
100
109
} else {
101
- // TODO: Is this between 0 and 1?
102
- if f64:: exp ( -f64:: abs ( new_path_length - path_length) / temp) > rng. gen :: < f64 > ( ) {
103
- current_path = potential_new_path;
104
- path_length = new_path_length;
105
- }
110
+ // Cyclic permutation
111
+ let node_to_move = potential_new_path. path [ node_index_to_mutate] ;
112
+ // -2 because we are looking for new position with 1 node missing
113
+ let new_node_position = self . rng . gen_range ( 0 ..( self . g . num_vertices ( ) - 2 ) ) ;
114
+ potential_new_path. path . remove ( node_index_to_mutate) ;
115
+ potential_new_path
116
+ . path
117
+ . insert ( new_node_position, node_to_move)
106
118
}
107
119
108
- temp *= 0.995 ;
109
- iterations += 1 ;
110
- result_data. push ( ( temp, path_length) ) ;
120
+ potential_new_path
121
+ }
122
+
123
+ pub fn get_best_path ( & self ) -> & GraphPath {
124
+ & self . best_path
111
125
}
112
126
113
- if output_graph {
127
+ pub fn output_graph ( & self ) {
114
128
// We create our scatter plot from the data
115
129
let s1: Plot =
116
- Plot :: new ( result_data. clone ( ) ) . line_style ( LineStyle :: new ( ) . colour ( "#DD3355" ) ) ;
130
+ Plot :: new ( self . result_data . clone ( ) ) . line_style ( LineStyle :: new ( ) . colour ( "#DD3355" ) ) ;
117
131
118
132
// The 'view' describes what set of data is drawn
119
133
let v = ContinuousView :: new ( )
120
134
. add ( s1)
121
135
. x_label ( "Temperature" )
122
136
. y_label ( "Path length" )
123
- . y_range ( 0.0 , result_data[ 0 ] . 1 + 100.0 ) ;
137
+ . y_range ( 0.0 , self . result_data [ 0 ] . 1 + 100.0 ) ;
124
138
125
139
// A page with a single view is then saved to an SVG file
126
140
Page :: single ( & v) . save ( "out/tsp_test_1.svg" ) . unwrap ( ) ;
127
141
}
128
-
129
- best_path
130
142
}
0 commit comments