Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extGraph / src / org / gvsig / graph / solvers / ShortestPathSolverAStar.java @ 35157

History | View | Annotate | Download (9.31 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41
package org.gvsig.graph.solvers;
42

    
43
import java.util.ArrayList;
44
import java.util.PriorityQueue;
45

    
46
import org.gvsig.exceptions.BaseException;
47
import org.gvsig.graph.core.GlobalCounter;
48
import org.gvsig.graph.core.GraphException;
49
import org.gvsig.graph.core.GvConnector;
50
import org.gvsig.graph.core.GvEdge;
51
import org.gvsig.graph.core.GvFlag;
52
import org.gvsig.graph.core.GvNode;
53
import org.gvsig.graph.core.GvTurn;
54
import org.gvsig.graph.core.IGraph;
55
import org.gvsig.graph.solvers.pqueue.FibHeap;
56

    
57
/**
58
 * @author fjp Este es ?til solo cuando podemos calcular la distancia estimada
59
 *         entre 2 nodos. (Es decir, para temas de cartograf?a). Para analizar
60
 *         relaciones creo que no servir?a).
61
 */
62
public class ShortestPathSolverAStar extends AbstractShortestPathSolver {
63

    
64
        /**
65
         * @return a list of features
66
         * @throws GraphException
67
         */
68
        public Route calculateRoute() throws GraphException {
69
                GvFlag[] flags = net.getFlags();
70
                if (flags.length == 0)
71
                        throw new RuntimeException("Please, add flags before");
72
                int desde = 0;
73
                int hasta = 1;
74
                double elCoste1 = 0;
75
                route = new Route();
76
                GvFlag fFrom = flags[0];
77
                fFrom.setCost(0);
78
                for (int i = 0; i < flags.length - 1; i++) {
79
                        fFrom = flags[desde];
80
                        GvFlag fTo = flags[hasta];
81

    
82
                        if (fFrom != fTo) {
83
                                int idStart = net.creaArcosVirtuales(fFrom);
84
                                int idStop = net.creaArcosVirtuales(fTo);
85

    
86
                                long tA1= System.currentTimeMillis();
87
                                double newCost = AStar(idStart, idStop);
88
                                long tA2= System.currentTimeMillis();
89
                                System.out.println("T Astar = " + (tA2-tA1));
90
                                
91
                                elCoste1 += newCost;
92
                                fTo.setCost(elCoste1);
93

    
94
                                if (newCost != Double.MAX_VALUE) {
95
                                        try {
96
                                                long t1 = System.currentTimeMillis();
97
                                                populateRoute(fFrom, fTo, idStart, idStop);
98
                                                long t2 = System.currentTimeMillis();
99
                                                System.out.println("T populateRoute=" + (t2-t1));
100
                                        } catch (BaseException e) {
101
                                                e.printStackTrace();
102
                                                net.reconstruyeTramo(fFrom.getIdArc());
103
                                                net.reconstruyeTramo(fTo.getIdArc());
104

    
105
                                                throw new GraphException(e);
106
                                        }
107
                                } else {
108
                                        // No way
109
                                }
110

    
111
                                net.reconstruyeTramo(fFrom.getIdArc());
112
                                net.reconstruyeTramo(fTo.getIdArc());
113
                                desde = hasta;
114
                        } // if son puntos distintos
115
                        hasta++;
116
                }
117
                return route;
118
        }
119

    
120
        private double AStar(int idStart, int idStop) {
121
                int nodeNum;
122
                int linkNum;
123
                double newCost;
124
                int idSiguienteNodo;
125
                GvNode node, toNode, finalNode, bestNode; // , *pNodoProv;
126
                GvEdge link;
127
                boolean bExit = false;
128

    
129
                boolean bGiroProhibido;
130
//                ArrayList candidatos = new ArrayList();
131

    
132
                // char Mensaje[200];
133

    
134
                IGraph graph = net.getGraph();
135

    
136
                // NUEVO: 27-6-2003
137
                // Cada nodo y cada arco llevan un nuemero de soluci?n. Se supone
138
                // que si lo del nodo y el arco no coincide con
139
                // este numero, todav?a no ha sido inicializado y hay que hacerlo.
140
                // Para evitar coincidencias cuando de la vuelta el contador, cada
141
                // 65000 peticiones (por ejemplo), repasamos toda
142
                // la red y ponemos numSolucGlobal a -1
143
                if (GlobalCounter.increment())
144
                {
145
                        for (nodeNum = 0; nodeNum < graph.numVertices(); nodeNum++) {
146
                                node = graph.getNodeByID(nodeNum);
147
                                node.initialize();
148
                        } // for nodeNum */
149
                }
150

    
151
//                candidatos.clear();
152
                // A?adimos el Start Node a la lista de candidatosSTL
153
                // Nodo final
154
                finalNode = graph.getNodeByID(idStop);
155
                finalNode.initialize();
156

    
157
                node = graph.getNodeByID(idStart);
158
                node.initialize();
159
//                bestNode = node;
160

    
161
//                candidatos.add(node);
162
                node.setCostZero();
163
                node.setStatus(GvNode.statNowInList);
164
                node.calculateStimation(finalNode, 0);
165
                
166
        // Priority Queue
167
        PriorityQueue<GvNode> pq = new PriorityQueue<GvNode>();
168
        pq.add(node);
169

    
170

    
171
                // Mientras que la lista de candidatosSTL no est? vac?a, procesamos
172
                // Nodos
173
                double bestStimation;
174

    
175
                while ((!bExit) && (!pq.isEmpty())) {
176
                        // Buscamos el nodo con m?nimo coste
177
//                        node = (GvNode) candidatos.get(0);
178
//                        bestNode = node;
179
//                        bestStimation = node.getStimation();
180
//                        int bestIndex = 0;
181
//                        for (nodeNum = 1; nodeNum < candidatos.size(); nodeNum++) {
182
//                                node = (GvNode) candidatos.get(nodeNum);
183
//                                if (node.getStimation() < bestStimation) {
184
//                                        bestStimation = node.getStimation();
185
//                                        bestNode = node;
186
//                                        bestIndex = nodeNum;
187
//                                }
188
//                        } // for nodeNum candidatosSTL
189

    
190
            node = pq.poll(); // get the lowest-weightSum Vertex 'u',
191
//                        node = bestNode;
192
                        // Borramos el mejor nodo de la lista de candidatosSTL
193
                        node.setStatus(GvNode.statWasInList);
194
//                        candidatos.remove(bestIndex);
195
                        // System.out.println("LINK " + link.getIdArc() + " from ");
196
                        // System.out.println("from " + idStart + " to " +
197
                        // finalNode.getIdNode() + ". node=" + node.getIdNode());
198
                        // Miramos si hemos llegado donde quer?amos
199
                        if (node.getIdNode() == idStop) {
200
                                bExit = true;
201
                                break;
202
                        }
203

    
204
                        // sprintf(Mensaje,"Enlaces en el nodo %ld:
205
                        // %ld.",pNodo->idNodo,pNodo->Enlaces.GetSize());
206
                        // AfxMessageBox(Mensaje);
207

    
208
                        // A?adimos a la lista de candidatosSTL los vecinos del nodo que
209
                        // acabamos de borrar
210
                        // HAY Arcos QUE SALEN Y Arcos QUE LLEGAN. SOLO MIRAMOS LOS QUE
211
                        // SALEN.
212
//                        for (linkNum = 0; linkNum < node.getOutputLinks().size(); linkNum++) {
213
                        for (int iConec=0; iConec< node.getConnectors().size();  iConec++) {
214
                                // Pillamos el nodo vecino
215
                                GvConnector c = node.getConnectors().get(iConec);
216
                                if (c.getEdgeOut() == null) continue;
217
                                
218
                                link = (GvEdge) c.getEdgeOut();
219
                                // Pillamos el nodo vecino
220
//                                link = (GvEdge) node.getOutputLinks().get(linkNum);
221
                                idSiguienteNodo = link.getIdNodeEnd();
222
                                
223
                                // To avoid U-turn
224
                                if (c.getEdgeIn() != null)
225
                                        if (c.getFrom_link_c() == c.getEdgeIn().getIdEdge())
226
                                                continue;
227

    
228
                                toNode = graph.getNodeByID(idSiguienteNodo);
229
                                
230
                                // 27_5_2004
231
                                // Si un arco tiene coste negativo, lo ignoramos
232
                                if (link.getWeight() < 0)
233
                                        continue;
234

    
235
                                // Fin arco con coste negativo
236
//                                int from_link = c.getFrom_link_c();
237
//
238
//                                if (from_link != -1) {
239
//                                        if (c.getEdgeIn().getIdEdge() == from_link) continue; // No queremos entrar y salir
240
                                                                                                                                // por el mismo conector
241
                                // NUEVO: 26-7-2003: Comprobamos si est? inicializado
242
                                if (toNode.getNumSoluc() != GlobalCounter.getGlobalSolutionNumber()) {
243
                                        toNode.initialize();
244
                                } else {
245
                                        // System.out.println("Nodo ya inicializado");
246
                                }
247
                                // Miramos a ver si podemos mejorar su best_cost
248
//                                double costeGiro = 0;
249
//
250
//                                // Miramos la lista de Giros de ese nodo
251
//                                bGiroProhibido = false;
252
//                                if (from_link != -1) {
253
//                                        GvEdge edgeFrom = graph.getEdgeByID(from_link);
254
//                                        for (int idGiro=0; idGiro < node.getTurnCosts().size(); idGiro++)
255
//                                        {
256
//                                                // Si est? prohibido, a por otro
257
//                                                GvTurn elGiro = node.getTurnCosts().get(idGiro);
258
//                                                if ((elGiro.getIdArcFrom() == edgeFrom.getIdArc()) && 
259
//                                                        (elGiro.getIdArcTo() == link.getIdArc()))
260
//                                                {
261
//                                                        if (elGiro.getCost() < 0)
262
//                                                        {
263
//                                                                bGiroProhibido = true;
264
//                                                        }
265
//                                                        else
266
//                                                                costeGiro = elGiro.getCost();
267
//        
268
//                                                        // Para que pueda volver a entrar en los c?lculos
269
//                                                        node.setStatus(GvNode.statNotInList);
270
//                                                        break; // Salimos del for porque ya hemos encontrado el giro
271
//                                                }
272
//                                        }
273
//                                }
274
//                                // Si est? prohibido, vamos a por otro enlace
275
//                                if (bGiroProhibido)
276
//                                {
277
//                                        continue;                                        
278
//                                }
279
                                // TODO: REVISAR SI HAY QUE SUMAR EL COSTE DEL GIRO A NEWCOST
280
                                // Y SI LO DE TURNCOSTS NO DEBE IR EN EXISTEMEJORA
281

    
282
                                // Miramos a ver si podemos mejorar su best_cost
283
                                newCost = c.getBestCostOut() + link.getWeight();
284

    
285
                                // Change to take care of turn costs
286
                                if (toNode.existeMejora(link, newCost)) {  // Es una mejora, as? que actualizamos el vecino y
287
//                                        // lo a?adimos a los candidatosSTL
288
//                                        toNode.setBestCost(newCost);
289
//                                         
290
//                                        toNode.setFromLink(link.getIdEdge());
291
                                        double newLength = node.getAccumulatedLength() + link.getDistance();
292
                                        toNode.setAccumulatedLength(newLength);
293

    
294

    
295
                                        toNode.calculateStimation(finalNode, newCost);
296

    
297
                                        if (toNode.getStatus() != GvNode.statNowInList) {
298
                                                toNode.setStatus(GvNode.statNowInList);
299
                                                pq.add(toNode);
300
//                                                candidatos.add(toNode);
301
                                        }
302
                                } // Si hay mejora
303

    
304
                        } // for linkNum
305
                } // while candidatosSTL
306

    
307
                newCost = finalNode.getBestCost();
308

    
309
                return newCost;
310
        }
311

    
312
}