166
Vect_check_input_output_name(map->answer, output->answer, GV_FATAL_EXIT);
168
mapset = G_find_vector2(map->answer, NULL);
171
G_fatal_error(_("Vector map <%s> not found"), map->answer);
219
Vect_check_input_output_name(map->answer, output->answer, G_FATAL_EXIT);
173
221
Vect_set_open_level(2);
174
Vect_open_old(&Map, map->answer, mapset);
223
if (Vect_open_old(&Map, map->answer, "") < 0)
224
G_fatal_error(_("Unable to open vector map <%s>"), map->answer);
175
226
nnodes = Vect_get_num_nodes(&Map);
227
nlines = Vect_get_num_lines(&Map);
177
229
/* Create list of terminals based on list of categories */
178
for (i = 1; i <= nnodes; i++) {
179
nlines = Vect_get_node_n_lines(&Map, i);
180
for (j = 0; j < nlines; j++) {
181
line = abs(Vect_get_node_line(&Map, i, j));
182
ltype = Vect_read_line(&Map, NULL, Cats, line);
183
if (!(ltype & GV_POINT))
185
if (!(Vect_cat_get(Cats, tfield, &cat)))
187
if (Vect_cat_in_cat_list(cat, Clist)) {
188
Vect_list_append(TList, i);
230
for (i = 1; i <= nlines; i++) {
232
ltype = Vect_get_line_type(&Map, i);
233
if (!(ltype & GV_POINT))
236
Vect_read_line(&Map, Points, Cats, i);
237
if (!(Vect_cat_get(Cats, tfield, &cat)))
239
if (Vect_cat_in_cat_list(cat, Clist)) {
240
node = Vect_find_node(&Map, Points->x[0], Points->y[0], Points->z[0], 0, 0);
242
G_warning(_("Point is not connected to the network"));
245
tsp_list_append(TList, node);
192
249
ncities = TList->n_values;
193
G_message(_("Number of cities: [%d]"), ncities);
250
G_message(_("Number of cities: %d"), ncities);
195
252
G_fatal_error(_("Not enough cities (< 2)"));
198
255
cities = (int *)G_malloc(ncities * sizeof(int));
199
256
cused = (int *)G_malloc(ncities * sizeof(int));
200
257
for (i = 0; i < ncities; i++) {
201
G_debug(1, "%d\n", TList->value[i]);
258
G_debug(1, "%d", TList->value[i]);
202
259
cities[i] = TList->value[i];
203
260
cused[i] = 0; /* not in cycle */
206
263
costs = (COST **) G_malloc(ncities * sizeof(COST *));
207
costs = (COST **) G_malloc((ncities - 1) * sizeof(COST *));
208
264
for (i = 0; i < ncities; i++) {
209
265
costs[i] = (COST *) G_malloc(ncities * sizeof(COST));
267
cost_cache = (double **) G_malloc(ncities * sizeof(double *));
268
for (i = 0; i < ncities; i++) {
269
cost_cache[i] = (double *) G_malloc(ncities * sizeof(double));
272
bcosts = (COST **) G_malloc(ncities * sizeof(COST *));
273
for (i = 0; i < ncities; i++) {
274
bcosts[i] = (COST *) G_malloc(ncities * sizeof(COST));
212
280
cycle = (int *)G_malloc((ncities + 1) * sizeof(int)); /* + 1 is for output cycle */
214
282
/* Build graph */
215
Vect_net_build_graph(&Map, type, afield, 0, afcol->answer, NULL, NULL,
283
Vect_net_build_graph(&Map, type, afield, 0, afcol->answer, abcol->answer, NULL,
218
286
/* Create sorted lists of costs */
287
/* for a large number of cities this will become very slow, can not be fixed */
288
G_message(_("Creating cost cache..."));
219
289
for (i = 0; i < ncities; i++) {
290
G_percent(i, ncities, 2);
221
292
for (j = 0; j < ncities; j++) {
293
cost_cache[i][j] = 0.0;
225
298
Vect_net_shortest_path(&Map, cities[i], cities[j], NULL,
228
G_fatal_error(_("Destination node [%d] is unreachable "
229
"from node [%d]"), cities[i], cities[j]);
302
double coor_x, coor_y, coor_z;
305
Vect_get_node_coor(&Map, cities[i], &coor_x, &coor_y, &coor_z);
306
line = Vect_find_line(&Map, coor_x, coor_y, coor_z, GV_POINT, 0, 0, 0);
309
G_fatal_error(_("No point at node %d"), cities[i]);
311
Vect_read_line(&Map, Points, Cats, line);
312
if (!(Vect_cat_get(Cats, tfield, &cat1)))
313
G_fatal_error(_("No category for point at node %d"), cities[i]);
315
Vect_get_node_coor(&Map, cities[j], &coor_x, &coor_y, &coor_z);
316
line = Vect_find_line(&Map, coor_x, coor_y, coor_z, GV_POINT, 0, 0, 0);
319
G_fatal_error(_("No point at node %d"), cities[j]);
321
Vect_read_line(&Map, Points, Cats, line);
322
if (!(Vect_cat_get(Cats, tfield, &cat2)))
323
G_fatal_error(_("No category for point at node %d"), cities[j]);
325
G_fatal_error(_("Destination node [cat %d] is unreachable "
326
"from node [cat %d]"), cat1, cat2);
329
/* add to directional cost cache: from, to, cost */
231
330
costs[i][k].city = j;
232
331
costs[i][k].cost = cost;
332
cost_cache[i][j] = cost;
235
336
qsort((void *)costs[i], k, sizeof(COST), cmp);
237
/* debug: print sorted */
238
for (i = 0; i < ncities; i++) {
239
for (j = 0; j < ncities - 1; j++) {
240
city = costs[i][j].city;
241
G_debug(2, "%d -> %d = %f\n", cities[i], cities[city],
341
for (i = 0; i < ncities; i++) {
342
/* this should be fast, no need for G_percent() */
344
for (j = 0; j < ncities; j++) {
348
bcosts[i][k].city = j;
349
bcosts[i][k].cost = cost_cache[j][i];
353
qsort((void *)bcosts[i], k, sizeof(COST), cmp);
357
if (debug_level >= 2) {
358
/* debug: print sorted */
359
for (i = 0; i < ncities; i++) {
360
for (j = 0; j < ncities - 1; j++) {
361
city = costs[i][j].city;
362
G_debug(2, "%d -> %d = %f", cities[i], cities[city],
368
G_message(_("Searching for the shortest cycle..."));
246
369
/* find 2 cities with largest distance */
248
371
for (i = 0; i < ncities; i++) {
249
372
tmpcost = costs[i][ncities - 2].cost;
250
373
if (tmpcost > cost) {
255
G_debug(2, "biggest costs %d - %d\n", city,
378
G_debug(2, "biggest costs %d - %d", city,
256
379
costs[city][ncities - 2].city);
258
/* add this 2 cities to array */
381
/* add these 2 cities to array */
259
382
add_city(city, -1);
260
383
add_city(costs[city][ncities - 2].city, 0);
262
385
/* In each step, find not used city, with biggest cost to any used city, and insert
263
386
* into cycle between 2 nearest nodes */
387
/* for a large number of cities this will become very slow, can be fixed */
264
388
for (i = 0; i < ncities - 2; i++) {
389
G_percent(i, ncities - 3, 1);
266
G_debug(2, "---- %d ----\n", i);
391
G_debug(2, "---- city %d ----", i);
267
392
for (j = 0; j < ncities; j++) {
268
393
if (cused[j] == 1)
271
396
for (k = 0; k < ncities - 1; k++) {
272
G_debug(2, "? %d (%d) - %d (%d) \n", j, cnode(j),
397
G_debug(2, "forward? %d (%d) - %d (%d)", j, cnode(j),
273
398
costs[j][k].city, cnode(costs[j][k].city));
274
399
if (!cused[costs[j][k].city])
275
400
continue; /* only used */
401
/* directional costs j -> k */
276
402
tmpcost += costs[j][k].cost;
277
403
break; /* first nearest */
279
G_debug(2, " cost = %f x %f\n", tmpcost, cost);
405
/* forward/backward: tmpcost = min(fcost) + min(bcost) */
407
for (k = 0; k < ncities - 1; k++) {
408
G_debug(2, "backward? %d (%d) - %d (%d)", j, cnode(j),
409
bcosts[j][k].city, cnode(bcosts[j][k].city));
410
if (!cused[bcosts[j][k].city])
411
continue; /* only used */
412
/* directional costs k -> j */
413
tmpcost += bcosts[j][k].cost;
414
break; /* first nearest */
418
G_debug(2, " cost = %f x %f", tmpcost, cost);
280
419
if (tmpcost > cost) {
285
G_debug(2, "add %d\n", city);
424
G_debug(2, "add city %d", city);
287
/* add to cycle on lovest costs */
288
cycle[ncyc] = cycle[0]; /* tmp for cycle */
426
/* add to cycle on lowest costs */
427
cycle[ncyc] = cycle[0]; /* temporarily close the cycle */
289
428
cost = PORT_DOUBLE_MAX;
290
430
for (j = 0; j < ncyc; j++) {
291
node1 = cities[cycle[j]];
292
node2 = cities[cycle[j + 1]];
293
ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &tcost);
431
/* cost from j to j + 1 (directional) */
432
/* get cost from directional cost cache */
433
tcost = cost_cache[cycle[j]][cycle[j + 1]];
294
434
tmpcost = -tcost;
295
node1 = cities[cycle[j]];
296
node2 = cities[city];
297
ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &tcost);
299
node1 = cities[cycle[j + 1]];
300
node2 = cities[city];
301
ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &tcost);
304
G_debug(2, "? %d - %d cost = %f x %f\n", node1, node2, tmpcost,
436
/* check insertion of city between j and j + 1 */
438
/* cost from j to city (directional) */
439
/* get cost from directional cost cache */
440
tcost = cost_cache[cycle[j]][city];
442
/* cost from city to j + 1 (directional) */
443
/* get cost from directional cost cache */
444
tcost = cost_cache[city][cycle[j + 1]];
447
/* tmpcost must always be > 0 */
449
G_debug(2, "? %d - %d cost = %f x %f", node1, node2, tmpcost,
451
/* always true for j = 0 */
306
452
if (tmpcost < cost) {
312
457
add_city(city, city1);
460
/* TODO: optimize tour (some Lin-Kernighan method) */
317
G_debug(2, "Cycle:\n");
318
for (i = 0; i < ncities; i++) {
319
G_debug(2, "%d: %d: %d\n", i, cycle[i], cities[cycle[i]]);
462
if (debug_level >= 2) {
464
G_debug(2, "Cycle:");
465
for (i = 0; i < ncities; i++) {
466
G_debug(2, "%d: %d: %d", i, cycle[i], cities[cycle[i]]);
322
470
/* Create list of arcs */
323
cycle[ncities] = cycle[0];
471
cycle[ncities] = cycle[0]; /* close the cycle */
324
473
for (i = 0; i < ncities; i++) {
325
474
node1 = cities[cycle[i]];
326
475
node2 = cities[cycle[i + 1]];
327
G_debug(2, " %d -> %d\n", node1, node2);
476
G_debug(2, " %d -> %d", node1, node2);
328
477
ret = Vect_net_shortest_path(&Map, node1, node2, List, NULL);
478
cost += cost_cache[cycle[i]][cycle[i + 1]];
329
479
for (j = 0; j < List->n_values; j++) {
330
480
line = abs(List->value[j]);
331
Vect_list_append(StArcs, line);
481
/* Vect_list_append() appends only if value not yet present !!!
482
* this breaks the correct sequence */
483
tsp_list_append(StArcs, line);
332
484
Vect_get_line_nodes(&Map, line, &node1, &node2);
333
Vect_list_append(StNodes, node1);
334
Vect_list_append(StNodes, node2);
485
tsp_list_append(StNodes, node1);
486
tsp_list_append(StNodes, node2);
340
490
/* Write arcs to new map */
341
Vect_open_new(&Out, output->answer, Vect_is_3d(&Map));
491
if (Vect_open_new(&Out, output->answer, Vect_is_3d(&Map)) < 0)
492
G_fatal_error(_("Unable to create vector map <%s>"), output->answer);
342
494
Vect_hist_command(&Out);
344
fprintf(stdout, "\nCycle:\n");
345
fprintf(stdout, "Arcs' categories (layer %d, %d arcs):\n", afield,
496
G_verbose_message(_("Cycle with total cost %.3f"), cost);
497
G_debug(2, "Arcs' categories (layer %d, %d arcs):", afield,
346
498
StArcs->n_values);
347
500
for (i = 0; i < StArcs->n_values; i++) {
348
501
line = StArcs->value[i];
349
502
ltype = Vect_read_line(&Map, Points, Cats, line);
350
503
Vect_write_line(&Out, ltype, Points, Cats);
351
504
Vect_cat_get(Cats, afield, &cat);
354
fprintf(stdout, "%d", cat);
356
fprintf(stdout, "\n\n");
358
fprintf(stdout, "Nodes' categories (layer %d, %d nodes):\n", tfield,
505
G_debug(2, "%d. arc: cat %d", i + 1, cat);
511
if (strcmp(seq->answer, "-")) {
512
seqname = seq->answer;
515
seqname = G_tempfile();
519
fp = fopen(seqname, "w");
521
G_fatal_error(_("Unable to open file '%s' for writing"),
524
fprintf(fp, "sequence;category;cost_to_next\n");
361
for (i = 0; i < StNodes->n_values; i++) {
362
node = StNodes->value[i];
363
nlines = Vect_get_node_n_lines(&Map, node);
364
for (j = 0; j < nlines; j++) {
365
line = abs(Vect_get_node_line(&Map, node, j));
366
ltype = Vect_read_line(&Map, Points, Cats, line);
367
if (!(ltype & GV_POINT))
369
if (!(Vect_cat_get(Cats, tfield, &cat)))
371
Vect_write_line(&Out, ltype, Points, Cats);
373
fprintf(stdout, ",");
374
fprintf(stdout, "%d", cat);
530
/* this writes out only user-selected nodes, not all visited nodes */
531
G_debug(2, "Nodes' categories (layer %d, %d nodes):", tfield,
533
for (i = 0; i < ncities; i++) {
534
double coor_x, coor_y, coor_z;
536
node = cities[cycle[i]];
537
Vect_get_node_coor(&Map, node, &coor_x, &coor_y, &coor_z);
538
line = Vect_find_line(&Map, coor_x, coor_y, coor_z, GV_POINT, 0, 0, 0);
543
ltype = Vect_read_line(&Map, Points, Cats, line);
544
if (!(ltype & GV_POINT))
546
if (!(Vect_cat_get(Cats, tfield, &cat)))
548
Vect_write_line(&Out, ltype, Points, Cats);
551
fprintf(fp, "%d;%d;%.3f\n", k, cat, cost_cache[cycle[i]][cycle[i + 1]]);
554
G_debug(2, "%d. node: cat %d", k, cat);
378
fprintf(stdout, "\n\n");
380
557
Vect_build(&Out);