[GRASS-SVN] r46229 - grass/trunk/vector/v.net.salesman

svn_grass at osgeo.org svn_grass at osgeo.org
Tue May 10 08:53:10 EDT 2011


Author: mmetz
Date: 2011-05-10 05:53:09 -0700 (Tue, 10 May 2011)
New Revision: 46229

Modified:
   grass/trunk/vector/v.net.salesman/main.c
Log:
v.net.salesman: add backward movement cost, ticket #1357

Modified: grass/trunk/vector/v.net.salesman/main.c
===================================================================
--- grass/trunk/vector/v.net.salesman/main.c	2011-05-10 12:22:58 UTC (rev 46228)
+++ grass/trunk/vector/v.net.salesman/main.c	2011-05-10 12:53:09 UTC (rev 46229)
@@ -35,9 +35,11 @@
 int nnodes;			/* number of nodes */
 int *cities;			/* array of cities */
 int *cused;			/* city is in cycle */
-COST **costs;			/* pointer to array of pointers to arrays of sorted costs */
+COST **costs;			/* pointer to array of pointers to arrays of sorted forward costs */
+COST **bcosts;			/* pointer to array of pointers to arrays of sorted backward costs */
 int *cycle;			/* path */
 int ncyc = 0;			/* number of cities in cycle */
+int debug_level;
 
 int cmp(const void *, const void *);
 
@@ -54,6 +56,7 @@
 	cycle[0] = city;
     }
     else {
+	/* for a large number of cities this will become slow */
 	for (j = ncyc - 1; j > after; j--)
 	    cycle[j + 1] = cycle[j];
 
@@ -62,9 +65,11 @@
     cused[city] = 1;
     ncyc++;
 
-    G_debug(2, "Cycle:\n");
-    for (i = 0; i < ncyc; i++) {
-	G_debug(2, "%d: %d: %d\n", i, cycle[i], cities[cycle[i]]);
+    if (debug_level >= 2) {
+	G_debug(2, "Cycle:");
+	for (i = 0; i < ncyc; i++) {
+	    G_debug(2, "%d: %d: %d", i, cycle[i], cities[cycle[i]]);
+	}
     }
 
 }
@@ -75,8 +80,8 @@
     int i, j, k, ret, city, city1;
     int nlines, type, ltype, afield, tfield, geo, cat;
     int node, node1, node2, line;
-    struct Option *map, *output, *afield_opt, *tfield_opt, *afcol, *type_opt,
-	*term_opt;
+    struct Option *map, *output, *afield_opt, *tfield_opt, *afcol, *abcol,
+	*type_opt, *term_opt;
     struct Flag *geo_f;
     struct GModule *module;
     struct Map_info Map, Out;
@@ -88,6 +93,7 @@
     struct cat_list *Clist;
     struct line_cats *Cats;
     struct line_pnts *Points;
+    const char *dstr;
 
     /* Initialize the GIS calls */
     G_gisinit(argv[0]);
@@ -120,11 +126,18 @@
     tfield_opt->description = _("Node layer (used for cities)");
 
     afcol = G_define_option();
-    afcol->key = "acolumn";
+    afcol->key = "afcolumn";
     afcol->type = TYPE_STRING;
     afcol->required = NO;
-    afcol->description = _("Arcs' cost column (for both directions)");
+    afcol->description =
+	_("Arc forward/both direction(s) cost column (number)");
 
+    abcol = G_define_option();
+    abcol->key = "abcolumn";
+    abcol->type = TYPE_STRING;
+    abcol->required = NO;
+    abcol->description = _("EXPERIMENTAL: Arc backward direction cost column (number)");
+
     term_opt = G_define_standard_option(G_OPT_V_CATS);
     term_opt->key = "ccats";
     term_opt->required = YES;
@@ -153,10 +166,19 @@
     Clist = Vect_new_cat_list();
     tfield = atoi(tfield_opt->answer);
     Vect_str_to_cat_list(term_opt->answer, Clist);
+    
+    dstr = G__getenv("DEBUG");
 
-    G_debug(1, "Imput categories:\n");
-    for (i = 0; i < Clist->n_ranges; i++) {
-	G_debug(1, "%d - %d\n", Clist->min[i], Clist->max[i]);
+    if (dstr != NULL)
+	debug_level = atoi(dstr);
+    else
+	debug_level = 0;
+
+    if (debug_level >= 1) {
+	G_debug(1, "Input categories:");
+	for (i = 0; i < Clist->n_ranges; i++) {
+	    G_debug(1, "%d - %d", Clist->min[i], Clist->max[i]);
+	}
     }
 
     if (geo_f->answer)
@@ -194,24 +216,32 @@
     cities = (int *)G_malloc(ncities * sizeof(int));
     cused = (int *)G_malloc(ncities * sizeof(int));
     for (i = 0; i < ncities; i++) {
-	G_debug(1, "%d\n", TList->value[i]);
+	G_debug(1, "%d", TList->value[i]);
 	cities[i] = TList->value[i];
 	cused[i] = 0;		/* not in cycle */
     }
 
     costs = (COST **) G_malloc(ncities * sizeof(COST *));
-    costs = (COST **) G_malloc((ncities - 1) * sizeof(COST *));
     for (i = 0; i < ncities; i++) {
 	costs[i] = (COST *) G_malloc(ncities * sizeof(COST));
     }
+    if (abcol->answer) {
+	bcosts = (COST **) G_malloc(ncities * sizeof(COST *));
+	for (i = 0; i < ncities; i++) {
+	    bcosts[i] = (COST *) G_malloc(ncities * sizeof(COST));
+	}
+    }
+    else
+	bcosts = NULL;
 
     cycle = (int *)G_malloc((ncities + 1) * sizeof(int));	/* + 1 is for output cycle */
 
     /* Build graph */
-    Vect_net_build_graph(&Map, type, afield, 0, afcol->answer, NULL, NULL,
+    Vect_net_build_graph(&Map, type, afield, 0, afcol->answer, abcol->answer, NULL,
 			 geo, 0);
 
     /* Create sorted lists of costs */
+    /* for a large number of cities this will become very slow, can not be fixed */
     for (i = 0; i < ncities; i++) {
 	k = 0;
 	for (j = 0; j < ncities; j++) {
@@ -220,27 +250,58 @@
 	    ret =
 		Vect_net_shortest_path(&Map, cities[i], cities[j], NULL,
 				       &cost);
+
 	    if (ret == -1)
 		G_fatal_error(_("Destination node [%d] is unreachable "
 				"from node [%d]"), cities[i], cities[j]);
 
+	    /* TODO: add to directional cost cache: from, to, cost */
 	    costs[i][k].city = j;
 	    costs[i][k].cost = cost;
+
 	    k++;
 	}
 	qsort((void *)costs[i], k, sizeof(COST), cmp);
     }
-    /* debug: print sorted */
-    for (i = 0; i < ncities; i++) {
-	for (j = 0; j < ncities - 1; j++) {
-	    city = costs[i][j].city;
-	    G_debug(2, "%d -> %d = %f\n", cities[i], cities[city],
-		    costs[i][j].cost);
+    
+    if (bcosts) {
+	for (i = 0; i < ncities; i++) {
+	    k = 0;
+	    for (j = 0; j < ncities; j++) {
+		if (i == j)
+		    continue;
+		    
+		/* TODO: get cost from directional cost cache */
+		/* from = cities[j], to = cities[i] */
+		ret =
+		    Vect_net_shortest_path(&Map, cities[j], cities[i], NULL,
+					   &cost);
+		if (ret == -1)
+		    G_fatal_error(_("Destination node [%d] is unreachable "
+				    "from node [%d]"), cities[j], cities[i]);
+		
+		if (bcosts[i][k].cost > cost) {
+		    bcosts[i][k].cost = cost;
+		}
+		    k++;
+	    }
+	    qsort((void *)bcosts[i], k, sizeof(COST), cmp);
 	}
     }
+    
+    if (debug_level >= 2) {
+	/* debug: print sorted */
+	for (i = 0; i < ncities; i++) {
+	    for (j = 0; j < ncities - 1; j++) {
+		city = costs[i][j].city;
+		G_debug(2, "%d -> %d = %f", cities[i], cities[city],
+			costs[i][j].cost);
+	    }
+	}
+    }
 
     /* find 2 cities with largest distance */
-    cost = -1;
+    cost = city = -1;
     for (i = 0; i < ncities; i++) {
 	tmpcost = costs[i][ncities - 2].cost;
 	if (tmpcost > cost) {
@@ -248,57 +309,84 @@
 	    city = i;
 	}
     }
-    G_debug(2, "biggest costs %d - %d\n", city,
+    G_debug(2, "biggest costs %d - %d", city,
 	    costs[city][ncities - 2].city);
 
-    /* add this 2 cities to array */
+    /* add these 2 cities to array */
     add_city(city, -1);
     add_city(costs[city][ncities - 2].city, 0);
 
     /* In each step, find not used city, with biggest cost to any used city, and insert 
      *  into cycle between 2 nearest nodes */
+    /* for a large number of cities this will become very slow, can be fixed */
     for (i = 0; i < ncities - 2; i++) {
 	cost = -1;
-	G_debug(2, "---- %d ----\n", i);
+	G_debug(2, "---- city %d ----", i);
 	for (j = 0; j < ncities; j++) {
 	    if (cused[j] == 1)
 		continue;
 	    tmpcost = 0;
 	    for (k = 0; k < ncities - 1; k++) {
-		G_debug(2, "? %d (%d) - %d (%d) \n", j, cnode(j),
+		G_debug(2, "? %d (%d) - %d (%d)", j, cnode(j),
 			costs[j][k].city, cnode(costs[j][k].city));
 		if (!cused[costs[j][k].city])
 		    continue;	/* only used */
+		/* directional costs j -> k */
 		tmpcost += costs[j][k].cost;
 		break;		/* first nearest */
 	    }
-	    G_debug(2, "    cost = %f x %f\n", tmpcost, cost);
+	    /* forward/backward: tmpcost = min(fcost) + min(bcost) */
+	    if (bcosts) {
+		for (k = 0; k < ncities - 1; k++) {
+		    G_debug(2, "? %d (%d) - %d (%d)", j, cnode(j),
+			    bcosts[j][k].city, cnode(bcosts[j][k].city));
+		    if (!cused[bcosts[j][k].city])
+			continue;	/* only used */
+		    /* directional costs j -> k */
+		    tmpcost += bcosts[j][k].cost;
+		    break;		/* first nearest */
+		}
+	    }
+
+	    G_debug(2, "    cost = %f x %f", tmpcost, cost);
 	    if (tmpcost > cost) {
 		cost = tmpcost;
 		city = j;
 	    }
 	}
-	G_debug(2, "add %d\n", city);
+	G_debug(2, "add city %d", city);
 
-	/* add to cycle on lovest costs */
-	cycle[ncyc] = cycle[0];	/* tmp for cycle */
+	/* add to cycle on lowest costs */
+	cycle[ncyc] = cycle[0];	/* temporarily close the cycle */
 	cost = PORT_DOUBLE_MAX;
+	city1 = 0;
 	for (j = 0; j < ncyc; j++) {
+	    /* cost from j to j + 1 (directional) */
 	    node1 = cities[cycle[j]];
 	    node2 = cities[cycle[j + 1]];
+	    /* TODO: get cost from directional cost cache */
+	    /* from = cities[cycle[j]], to = cities[cycle[j + 1]] */
 	    ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &tcost);
 	    tmpcost = -tcost;
+	    /* check insertion of city between j and j + 1 */
+	    /* cost from j to city (directional) */
 	    node1 = cities[cycle[j]];
 	    node2 = cities[city];
+	    /* TODO: get cost from directional cost cache */
 	    ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &tcost);
 	    tmpcost += tcost;
-	    node1 = cities[cycle[j + 1]];
-	    node2 = cities[city];
+	    /* cost from city to j + 1 (directional) */
+	    node1 = cities[city];
+	    node2 = cities[cycle[j + 1]];
+	    /* TODO: get cost from directional cost cache */
 	    ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &tcost);
 	    tmpcost += tcost;
+	    
+	    /* tmpcost must always be > 0 */
 
-	    G_debug(2, "? %d - %d cost = %f x %f\n", node1, node2, tmpcost,
+	    G_debug(2, "? %d - %d cost = %f x %f", node1, node2, tmpcost,
 		    cost);
+	    /* always true for j = 0 */
 	    if (tmpcost < cost) {
 		city1 = j;
 		cost = tmpcost;
@@ -309,18 +397,20 @@
 
     }
 
-    /* Print */
-    G_debug(2, "Cycle:\n");
-    for (i = 0; i < ncities; i++) {
-	G_debug(2, "%d: %d: %d\n", i, cycle[i], cities[cycle[i]]);
+    if (debug_level >= 2) {
+	/* debug print */
+	G_debug(2, "Cycle:");
+	for (i = 0; i < ncities; i++) {
+	    G_debug(2, "%d: %d: %d", i, cycle[i], cities[cycle[i]]);
+	}
     }
 
     /* Create list of arcs */
-    cycle[ncities] = cycle[0];
+    cycle[ncities] = cycle[0];  /* close the cycle */
     for (i = 0; i < ncities; i++) {
 	node1 = cities[cycle[i]];
 	node2 = cities[cycle[i + 1]];
-	G_debug(2, " %d -> %d\n", node1, node2);
+	G_debug(2, " %d -> %d", node1, node2);
 	ret = Vect_net_shortest_path(&Map, node1, node2, List, NULL);
 	for (j = 0; j < List->n_values; j++) {
 	    line = abs(List->value[j]);



More information about the grass-commit mailing list