| Pages: 1 2 :: [one page] |
| Author |
Thread Statistics | Show CCP posts - 0 post(s) |

Alvaliella
|
Posted - 2008.11.05 17:15:00 -
[1]
I'm trying to make a trade tool and I'm currently investigating how to work out the shortest route between two systems.
I'm planning on using the A* algorithm but I was wondering what to use for H? I'm guessing that the distance from the x,y,z position of the current node to the x,y,z position of the goal node would be useable but that seems prone to error.
Any ideas for what would be good to use for H please? Thanks! |

Ambo
State Protectorate
|
Posted - 2008.11.05 18:16:00 -
[2]
x,y,z distances are pretty useless when working out number of jumps because some jumps are waaaay longer than others.
Personally I didn't use an A* algorithm but I'd think H should be the number of inter-region jumps and, if you're already in the right region, then the number of inter-constellation jumps. If you're in the right constellation then a complete search will take virtually no time at all. --------------------------------------
Trader? Investor? Just want to track your finances? Check out EMMA |

Alvaliella
|
Posted - 2008.11.05 18:40:00 -
[3]
Originally by: Ambo x,y,z distances are pretty useless when working out number of jumps because some jumps are waaaay longer than others.
Personally I didn't use an A* algorithm but I'd think H should be the number of inter-region jumps and, if you're already in the right region, then the number of inter-constellation jumps. If you're in the right constellation then a complete search will take virtually no time at all.
Thanks for the reply Ambo. I was planning on using the x,y,z distances to evaluate how suitable the next potential jump nodes would be- whichever node was physically closest to the goal node would be selected as the most suitable... I can see it backfiring in cases where nodes move you physically farther away before getting you much closer with a massive jump though 
If you don't mind me asking, what did you use to find you routes? Dijkstra's algorithm or did you just keep expanding nodes until one hit the desired region, then constellation etc? |

Ambo
State Protectorate
|
Posted - 2008.11.05 20:43:00 -
[4]
I'm not sure if it has a name or not... I used a recursive procedure that stars from the destination and works backwards.
First I do regions, I then use that list of potential regions in the route to get the route through constellations, finally, I do the same for systems.
I suppose it's essentially a restricted bredth-first search with a lot of cacheing to speed things up, prevent back-tracking, etc. Frankly, I think it's over complicated and a little slow... I really should re write it as an A* algorithm. --------------------------------------
Trader? Investor? Just want to track your finances? Check out EMMA |

Alvaliella
|
Posted - 2008.11.05 21:09:00 -
[5]
Originally by: Ambo I'm not sure if it has a name or not... I used a recursive procedure that stars from the destination and works backwards.
First I do regions, I then use that list of potential regions in the route to get the route through constellations, finally, I do the same for systems.
I suppose it's essentially a restricted bredth-first search with a lot of cacheing to speed things up, prevent back-tracking, etc. Frankly, I think it's over complicated and a little slow... I really should re write it as an A* algorithm.
Thanks for the info, I might give that approach a shot and see what happens! The region & constellation connection data might make it equivalent to the A* method... will see what happens anyway |

Jethro Jechonias
Ki Tech Industries
|
Posted - 2008.11.05 21:55:00 -
[6]
Edited by: Jethro Jechonias on 05/11/2008 22:02:32
You could try using a lookup table has a heuristic guide.
Given that distances are symmetrical, you could halve the size of your lookup table by ordering the query elements.
For example:
h(a, b) { if (a == b) { return 0; // if input is SolarSystemID return 1; // if input is ConstellationID or RegionID } else if (b < a) { return h(b, a); } else { return lookup[a][b]; } }
The size of the jagged array (lookup[][] in the pseudo-code above) would depend on what level of detail you use with the array.
If you limit it to just regions, the array would contain 2,016 elements. Using constellations it would contain 281,625 elements. If you go right down to the solar system level, you would need 13,522,600 elements.
Given that the maximum distance between any two systems is 99 jumps, you could use a single byte as the array element. Thus the size of array needed for a region / constellation / solar system lookup table would be 2KB / 276KB / 13MB.
The lookup table could be loaded from the same source as your jump table. Either a file or database.
|

Alvaliella
|
Posted - 2008.11.05 22:46:00 -
[7]
Originally by: Jethro Jechonias Edited by: Jethro Jechonias on 05/11/2008 22:24:42
You could try using a lookup table has a heuristic guide.
Given that distances are symmetrical, you could halve the size of your lookup table by ordering the query elements.
For example:
h(a, b) { if (a == b) { return 0; // if input is SolarSystemID return 1; // if input is ConstellationID or RegionID } else if (b < a) { return h(b, a); } else { return lookup[a][b]; } }
The size of the jagged array (lookup[][] in the pseudo-code above) would depend on what level of detail you use with the array.
If you limit it to just regions, the array would contain 2,016 elements. Using constellations it would contain 281,625 elements. If you go right down to the solar system level, you would need 13,522,600 elements.
Given that the maximum distance between any two systems is 99 jumps, you could use a single byte as the array element. Thus the size of array needed for a region / constellation / solar system lookup table would be 2KB / 276KB / 13MB.
The lookup table could be loaded from the same source as your jump table. Either a file or database. Given that you would be hard pressed to get the Jumps table down to less than 58KB, the regional lookup table is probably quite reasonable for any application and even the constellation lookup table doesn't look too bad.
Thanks for the suggestion Jethro but I'm afraid that it's almost over my head I'm not really a programmer, just a determined jack of all trades 
I do understand your idea of referring to a table for guidance on the suitability of a node but I can't think of how I'd put such a table together. I have all of the region, constellation & solar system jump connection data but I dunno how I could crunch it into something meaningful so that I could ask the table whether x node would be better to go to than y node in order to get to z node etc.
Meh, I'll figure something out anyway- I'm currently filtering down the data as much as possible (removing all systems below a certain security level) which trims the lists of possible jumps down a lot- I reckon it might be possible to just use brute force and expand nodes from the start/end position until they meet 
|

Jethro Jechonias
Ki Tech Industries
|
Posted - 2008.11.05 22:59:00 -
[8]
What language are you developing in?
Your question has got me think that A* might be a huge improvement over my current methods, so I am starting to build something that works along those lines in C#.
The table is not too hard to put together in SQL. The catch is that the SQL version is much larger than the memory structure that you can use in C#, and that is why I am working on putting one together.
|

Alvaliella
|
Posted - 2008.11.05 23:19:00 -
[9]
Originally by: Jethro Jechonias What language are you developing in?
Your question has got me think that A* might be a huge improvement over my current methods, so I am starting to build something that works along those lines in C#.
The table is not too hard to put together in SQL. The catch is that the SQL version is much larger than the memory structure that you can use in C#, and that is why I am working on putting one together.
Promise not to laugh?... I'm using VBA with Excel 
I'm making a giant market order crunching machine and Excel seemed to be the most hassle free option at the time- it's going great so far it must be said! It was a doddle to get all of the relevant Eve data from SQL into worksheets, automate importing of market export files & crunching the numbers etc.
I dunno how you could get over the memory limitation in C#... if you're using the A* algorithm then maybe you could use SQL to split up all of the jump information into separate tables for each region/constellation and only pull in the data for the region/constellation that you're currently in.
If you use the x,y,z distance as the heuristic (crappy but better than nothing), then you could work blind & "feel" your way there- the x,y,z of your destination never changes and you'd get your current x,y,z from the region/constellation file that you current have in memory.
I came across this in my research- it might be of use?
Eve Toolbox AutoPilot source |

Jethro Jechonias
Ki Tech Industries
|
Posted - 2008.11.06 00:30:00 -
[10]
Edited by: Jethro Jechonias on 06/11/2008 00:33:06
Originally by: Alvaliella I dunno how you could get over the memory limitation in C#... if you're using the A* algorithm then maybe you could use SQL to split up all of the jump information into separate tables for each region/constellation and only pull in the data for the region/constellation that you're currently in.
If I store the information in SQL, I am looking at a table with 9 bytes per row: 4 bytes for each of the Celestial ID's and 1 byte for the distance.
If I store the information in a C# jagged array, I am looking at 1 byte per row: there is no need to store the Celestial ID's as they form the dimensions of the array.
All I need is a means of converting the Celestial ID to a continuos range of integers and back again: that looks like it will be simple enough to do.
So by moving from SQL to C# I can decrease my memory requirements by approx 9x: well worth the effort.
Not sure how you might go about implementing it in VBA. The Regional distance table is small enough that you could implement it as a sheet in Excel. It is the Jump Table and such that would be much harder to implement.
Using a Regional distance table is likely to be a much better huristic than using the x,y,z distance; possibly supplimented it with a limited Constellation table.
Footnote: by Celectial ID, I mean either SolarSystemID, ConstellationID, or RegionID depending on which lookup table I am using.
|

Ambo
State Protectorate
|
Posted - 2008.11.06 08:24:00 -
[11]
Incidentally, when I was writting my algorithm I initally found that my program would usually give the fasted route but would somtimes come up with longer routes than the in-game auto pilot. After a while I realised that this was always occuring for routes where both systems where in the same region but the quickest route went through a different region. i.e. If you're in the right region, that does not mean you want to ignore inter-region jumps.
Just thought I'd highlight this potential stumbling block
I'm also going to be working on a proper A* version because I think it could be a fair bit faster and simpler than my current solution. --------------------------------------
Trader? Investor? Just want to track your finances? Check out EMMA |

Xaroth Brook
Minmatar BIG Libertas Fidelitas
|
Posted - 2008.11.06 08:33:00 -
[12]
If you try A*, use it as suggested above, though I personally would add some 'changes' to that idea.
1) Calculate from-region to-region path, store that 'map' of nodes traversed 2) Calculate from-constellation to-constellation path, using ONLY the regions in the map and their adjacent ones (while 2 regions might be tied together it might be faster to nip into a neighbouring region to get there quicker (going / instead of _| .. ) store this in a map as well 3) Calculate from-sol to-sol path using the constellation map and 1(or 2) adjacent constellations.
If you were to just calculate the from-sol to-sol path you'll be taking minutes for an accurate path (in eve going from A to B won't always be in a straight line, so you can't use guessing methods in your formulla based on direction), by ruling out half of EVE's regions, and of those regions almost half of the constellations you'll be taking down the calculation time to seconds (if not less)
I used to have a snippet that calculated that but i think i lost it in one of the recent reformats i had to do, but the above concept pretty much sums it up.
It was like a baby, it landed on my lap and was helpless and totally defenseless. Then I shot it and bragged about it on a killboard.
|

Alvaliella
|
Posted - 2008.11.06 09:07:00 -
[13]
Edited by: Alvaliella on 06/11/2008 09:08:52 Thanks for the replies & help all- some very good ideas there and I hadn't thought about the region-to-region issue (i.e. that it's not always quicker). I'll try calculating the path for regions first, then constellations then solar systems as it seems best.
Does anyone know how CCP make the AutoPilot work? The more I work on this, the more amazed I'm getting at how fast it can work out a route **hugs on board computer**
|

Jethro Jechonias
Ki Tech Industries
|
Posted - 2008.11.06 15:44:00 -
[14]
Originally by: Alvaliella Does anyone know how CCP make the AutoPilot work?
CCP's implementation of the autopilot is very ineffiencient. I wouldn't recommend using that as a guide on how to build an autopilot.
|

sumtool
Amarr Sniggerdly Pandemic Legion
|
Posted - 2008.11.08 20:58:00 -
[15]
The basic way of doing it is to use Dijkstra's algorithm, systems will become the nodes with jumps being the paths between said nodes. You can modify the algorithm by assigning different weights to the jumps to influence whether a certain path gets chosen or not.
I.e. start off all jumps at weight 10, but jumps that go from hisec -> lowsec end up on 5 -- this way the algorithm will try to keep you out of lowsec.
For a full explanation on the algorithm: http://en.wikipedia.org/wiki/Dijkstra%27s_Algorithm
|

Kazuo Ishiguro
House of Marbles Zzz
|
Posted - 2008.11.09 11:23:00 -
[16]
Originally by: Jethro Jechonias
Originally by: Alvaliella Does anyone know how CCP make the AutoPilot work?
CCP's implementation of the autopilot is very ineffiencient. I wouldn't recommend using that as a guide on how to build an autopilot.
It does a good job at finding the quickest route between any 2 systems. It'd be better if it settled for a compromise with longer routes rather than trying to find an optimal solution. --- Can't afford that BPO? Look here. 20:1 mineral compression The EVE f@h team |

Blazing Fire
Interstellar Operations Incorporated
|
Posted - 2008.11.13 08:45:00 -
[17]
I use A* with x,y,z and the number of jumps from the start point for H.
Sometimes it gives 1-3 jumps longer routes then the EVE Auto Pilot.
I don't bother to include the security status in the H. If I don't want to go into lowsec/nulsec, I just don't add those systems in the Open list. Of course this does not work if you need to go there. If you want to, the sec status doesn't matter, you just want the shortest path.
Keep in mind that shortes path in number of jumps, but it may not be the fastest. Sometimes the travel time on alternate routes is much small because closer distance between stargates. |

Entity
X-Factor Industries Synthetic Existence
|
Posted - 2008.11.13 17:34:00 -
[18]
Originally by: Kazuo Ishiguro
Originally by: Jethro Jechonias
Originally by: Alvaliella Does anyone know how CCP make the AutoPilot work?
CCP's implementation of the autopilot is very ineffiencient. I wouldn't recommend using that as a guide on how to build an autopilot.
It does a good job at finding the quickest route between any 2 systems. It'd be better if it settled for a compromise with longer routes rather than trying to find an optimal solution.
Dijkstra is near instant for any single route. Don't confuse finding shortest route between A and B with finding the shortest tour through a variable number of waypoints. _
Got Item? | EVE API? |

Kniht
D.M.T inc Bionic Dawn
|
Posted - 2008.11.15 00:55:00 -
[19]
While dijkstra works, it's designed for a weighted graph. If you just want shortest path by stargates, breadth-first search with trimming already visited nodes is all you need. It's what dijkstra becomes when all edge weights are identical, except you store less state and it's almost trivial to write from scratch.
My current route planner uses this, is very fast, and always finds one of the shortest routes. (You can continue the search and find all equally shortest routes, but I currently have no need for this.)
|

Kazuo Ishiguro
House of Marbles Zzz
|
Posted - 2008.11.15 01:16:00 -
[20]
Are the locations of stargates within systems available as part of the data dump? If so, someone could come up with a route planner that minimises time in warp as well as jumps... |

Ki Anna
Ki Tech Industries
|
Posted - 2008.11.15 01:22:00 -
[21]
Originally by: Kazuo Ishiguro Are the locations of stargates within systems available as part of the data dump? If so, someone could come up with a route planner that minimises time in warp as well as jumps...
Yup, that data is there. |

Blazing Fire
Interstellar Operations Incorporated
|
Posted - 2008.11.17 12:23:00 -
[22]
Originally by: Kazuo Ishiguro Are the locations of stargates within systems available as part of the data dump? If so, someone could come up with a route planner that minimises time in warp as well as jumps...
I have done this for my tools. It is very easy done with precalculated SQL table. All you have to do is to caclulate the distance from each gate to the others in the same systems and store the results in a table. Mine contains source system ID, target system Id, ID of the system where teh gates are located and the precalculated distance between the gates.
When using gate to gate distance and jumps from the start system and the 3d distance from the current system to the target system for Path scoring, I get similar if not the same results as the ingame autopilot.
|

Blazing Fire
Interstellar Operations Incorporated
|
Posted - 2008.11.17 12:31:00 -
[23]
in short if the Path score is F=G+H, where G is the movement cost fro mthe starting system to the current node, and H is the estimated movement cost from the current node to the destination I use this:
G=gate to gate distance/100000000000000 + jumps from start node H=3D distance from current node to the target system/100000000000000
This gives me pretty good results. |

Kazuo Ishiguro
House of Marbles Zzz
|
Posted - 2008.11.17 19:27:00 -
[24]
I've done a fair bit of research on how much distance ships cover during warp - you accelerate exponentially for 10 seconds and slow down exponentially for 20 seconds. Thus a lower bound for each jump is 30 seconds (this is also enforced by the session change timer).
During this time, excluding any additional ground covered while at full warp, you typically cover a distance equivalent to travelling at full warp speed for 1.33 seconds.
Also, it's worth finding your average grid load time (leave the log window open while on autopilot for 10-20 jumps and all the relevant data will end up in a single text file). --- Can't afford that BPO? Look here. 20:1 mineral compression The EVE f@h team |

Blazing Fire
Interstellar Operations Incorporated
|
Posted - 2008.11.18 14:06:00 -
[25]
Originally by: Kazuo Ishiguro I've done a fair bit of research on how much distance ships cover during warp - you accelerate exponentially for 10 seconds and slow down exponentially for 20 seconds. Thus a lower bound for each jump is 30 seconds (this is also enforced by the session change timer).
During this time, excluding any additional ground covered while at full warp, you typically cover a distance equivalent to travelling at full warp speed for 1.33 seconds.
Also, it's worth finding your average grid load time (leave the log window open while on autopilot for 10-20 jumps and all the relevant data will end up in a single text file).
Ok, I have done some testing. I have started to calculate the Path score in time needed for travel. I have included the time needed to warp from gate to gate, the session change time, the align time, the time to accelerate and decelerate to/from warp.
The results are: *Same routes for short distances(20 jumps) *A bit different routes for longer distances (+50 jumps) *4 to 10 more time needed to calcualte the route *4 to 10 times increase of the number of visited by the algorithm systems
Bottom line - It is not worth it.
|

Alvaliella
|
Posted - 2008.11.23 16:53:00 -
[26]
Edited by: Alvaliella on 23/11/2008 16:57:45 Thanks for all the replies & discussion- some points raised pre-emptively answer a few other questions that I was wondering about
I just wanted to give some "closure" to my original question in case anyone has similar concerns in the future.
After much research & musing I gave Dijkstra a try using the method described here.
When I first implemented this in Excel VBA, it took around 6.5 seconds to solve for a node (i.e. work out the shortest paths from the starting node to all other nodes in the system).
After code tweaking, pruning of the Eve data (e.g. removal of systems below a security threshold etc.) and optimising/preprocessing the remaining data, I got the solution time down to ~1.5 seconds for starting node to all others, and ~0.5 seconds for starting node to a particular destination node.
I'm pretty happy with this solution time and I don't think that A* would offer any major time savings (for this particular application)... I also like the fact that Dijkstra guarantees the shortest route so I know that my routes will match those of the autopilot.
My conclusion: Use Dijkstra over A* |

Ambo
State Protectorate
|
Posted - 2008.11.23 21:53:00 -
[27]
Edited by: Ambo on 23/11/2008 21:54:10
Originally by: Alvaliella Edited by: Alvaliella on 23/11/2008 16:57:45 Thanks for all the replies & discussion- some points raised pre-emptively answer a few other questions that I was wondering about
I just wanted to give some "closure" to my original question in case anyone has similar concerns in the future.
After much research & musing I gave Dijkstra a try using the method described here.
When I first implemented this in Excel VBA, it took around 6.5 seconds to solve for a node (i.e. work out the shortest paths from the starting node to all other nodes in the system).
After code tweaking, pruning of the Eve data (e.g. removal of systems below a security threshold etc.) and optimising/preprocessing the remaining data, I got the solution time down to ~1.5 seconds for starting node to all others, and ~0.5 seconds for starting node to a particular destination node.
I'm pretty happy with this solution time and I don't think that A* would offer any major time savings (for this particular application)... I also like the fact that Dijkstra guarantees the shortest route so I know that my routes will match those of the autopilot.
My conclusion: Use Dijkstra over A*
Interesting stuff.
I've been doing some investigation of my own. I've got a basic Dijkstra that solves for any node-node pretty fast. However, it's not always fast than my current solution, some example results were:
my solution - none-node 9 jumps - 0.16s my solution - none-node 60 jumps - 1.3s
Dijkstra - node-node 9 jumps - 0.28s Dijkstra - node-node 60 jumps - 9.8s
In other words, both solutions are fast enough for short routes but neither are really as fast as I want for longer routes.
I think that running Dijkstra for regions, then constellations, then systems rather than just systems right off the bat would result in better times for the longer routes but would surely slow up the shorted routes...
I've also not got around to fully implementing an A* algorithm yet.
Your removal of systems below a certain security level is not an option for me. I've also yet to introduce any preference system for high security systems or anything like that.
I'll be sure to keep you updated once I've done some more coding and run a few more tests.  --------------------------------------
Trader? Investor? Just want to track your finances? Check out EMMA |

Ambo
State Protectorate
|
Posted - 2008.11.25 16:21:00 -
[28]
Just thought I'd update this with my new findings.
Search routines I've tried:
My own (still not sure if it even has a proper name.. a recursive reverse search with the search space restricted to systems that are members of the best constellation route + neighbours - the constellation route having been calculated in the same manner from constellations in the best region route + neighbours. Essentially, this is equivalent to my best-first implementation) Dijkstra A* Best-first
Pre-processing, optimisations and restrictions:
1) Both my own method and Dijkstra require no pre-processing of the datadump tables. 2) A* and best-first can either use a distance-based heuristic (no pre-processing needed but slower) or a constellation jumps based heuristic (can either have no pre-processing and be slow or pre-generate a table with all routes between constellations and thier lengths (takes a few minutes and added about 20 Mb to the DB on my system) 3) My method is very tricky to ristrict in any way (i.e. prefer high-sec routes, etc). All the others are fairly easy to tweak with different path wieghts for different route requirements. 4) This one may sound obvious but optimise your algorithm. Generalised solutions will always perform worse so put timers in to measure what is slow, watch for places where you can cache and reuse data, etc. 5) My Dijkstra algorithm is highly optimised for unit path lenghts (i.e. all jumps having a 'cost' of 1).
Test Results Note - these are all from a slower machine that the previous results I posted. ;)
59 jumps - 9S-GPT in Outer Passage to XG-D1L in Cloud Ring (actually 50 jumps, see obsevations)
1st run 2nd run My algorithm 4.5 3.7 Dijkstra 5.9 2.6 A* (constellation jumps) 40.5 38.6 A* (actual distance) 4.2 3.3 Best first (constellation jumps) 2.5 1.1 Best first (actual distance) 3.0 2.1 (Result was a 104 jump route!)
6 jumps = Jita to Vuorrassi
1st run 2nd run My algorithm 1.4 0.4 Dijkstra 2.1 0.6 A* (constellation jumps) 3.5 1.1 A* (actual distance) 1.5 0.5 Best first (constellation jumps) 1.7 0.6 Best first (actual distance) 1.2 0.2 (Result was a 7 jump route)
Observations
Having got all I could out of Dijkstra and my own algorithm, I set about implementing A* using constellation jumps as the estimated distnace remaining to the destination. Clearly, this gave very disapointing performance because constellation jumps was simply not a good enough approximation of the actual number of jumps that would be required.
I tried using the actual distance between systems as a heuristic and was pleasantly suprised by the speed. However, I then noticed a problem. With the 59 jump route (from 9S-GPT in Outer Passage to XG-D1L in Cloud Ring), A* came up with a route of 50 jumps?! After some head-scratching and investigating, I found that the A* route was passing through regions that were excluded from my algorithm and Dijkstra because they were not either on or neighbouring the shortest regional route from Outer Passage to Cloud Ring (Outer Passage->Perrigen Falls->Venal->Tribute->Pure Blind->Cloud Ring). In fact, the real shortest route went through completely different regions (Outer Passage->The Spire->Etherium Reach->The Forge->Metropolis->Sinq Laison->Essence->Placid->Cloud Ring). --------------------------------------
Trader? Investor? Just want to track your finances? Check out EMMA |

Ambo
State Protectorate
|
Posted - 2008.11.25 16:22:00 -
[29]
Unsure how to combat this problem in Dijkstra and my own algorithm, I decided to try optimising A* as much as possible. I pretty soon realised that the A* using constellation jump heuristic would be far more effective if I choose the next possible node based solely on the number of constellation jumps remaining. Turns out my A* was now a best first search. I was frankly amazed by the performance of this algorithm on the longer routes, we might finally have a winner.
Alas, Best first using a constellation jump hueristic may have been very fast but also suffered from the same problem as Dijkstra and my original algorithm! I tried best first using the actual distance heuristic instead and the results seemed ok... until I looked at the route itself and found that it was significantly longer than it should be.
Thoughts
1) I remain convinced that there is a better solution. However, given the results I've had so far, I'd have to say the best algorithm is A* using the actual distance as the heuristic (actually distance / 10000000000000000). 2) Number of constellation/region jumps is clearly too unreliable as a heuristic. actual distance is also not great. Need to find somthing else...
--------------------------------------
Trader? Investor? Just want to track your finances? Check out EMMA |

Ki Tarra
Caldari Ki Tech Industries
|
Posted - 2008.11.25 17:51:00 -
[30]
Ambo, what enviorment are you running this in and what units are you measuring the runtimes in?
|

Ambo
State Protectorate
|
Posted - 2008.11.25 18:07:00 -
[31]
The times are in seconds.
System is a P4 2.8 with 1 gig RAM running Windows XP. --------------------------------------
Trader? Investor? Just want to track your finances? Check out EMMA |

Ki Tarra
Caldari Ki Tech Industries
|
Posted - 2008.11.25 18:10:00 -
[32]
Originally by: Ambo The times are in seconds.
System is a P4 2.8 with 1 gig RAM running Windows XP.
Running in Excel VBA, .NET, PHP or what other programming enviroment.
Times that long in seconds seems to be excessive for just a route calculation.
Any chance of sharing your source code, if you are interested in some help getting it to run a bit faster?
|

Ambo
State Protectorate
|
Posted - 2008.11.25 20:04:00 -
[33]
Edited by: Ambo on 25/11/2008 20:06:01 I'm using C# on an SQL server express database.
I also tried implementing Djikstra in SQL to see if avoiding all the to-ing and fro-ing required normaly would speed things up. Unfortunately it was waaay slower (31 seconds for the 50 jump route).
I'd be open to any suggestions on improvements. Here's the Djikstra algorithm:
private static List<int> GetSystemRouteDijkstra(int startSystemID, int endSystemID, List<int> constellations) { Dictionary<int, int> indexToId = new Dictionary<int, int>(); Dictionary<int, int> idToIndex = new Dictionary<int, int>(); int nextFreeIndex = 0; short[] distance = new short[10000]; int[] previous = new int[10000]; bool[] vistited = new bool[10000];
indexToId.Add(0, startSystemID); idToIndex.Add(startSystemID, 0); nextFreeIndex = 1; bool complete = false;
distance[0] = 0; for (int i = 1; i < 10000; i++) { distance[i] = short.MaxValue; previous[i] = int.MaxValue; vistited[i] = false; }
if (startSystemID == endSystemID) { complete = true; }
int iterations = 0; while (!complete) { iterations++; //int minIndex = 0; short minDistance = short.MaxValue; for (int i = 1; i < 10000; i++) { if (distance[i] < minDistance && !vistited[i]) { minDistance = distance[i]; minIndex = i; } if (distance[i] == short.MaxValue) { i = 10000; } }
vistited[minIndex] = true; foreach (int system in GetNeighbourSystems(indexToId[minIndex])) { if (SolarSystems.InConstellation(system, constellations)) { if (!idToIndex.ContainsKey(system)) { idToIndex.Add(system, nextFreeIndex); indexToId.Add(nextFreeIndex, system); nextFreeIndex++; } short possible = (short)(distance[minIndex] + 1); if (possible < distance[idToIndex[system]]) { distance[idToIndex[system]] = possible; previous[idToIndex[system]] = minIndex; } // This optimisation can only be made because the distance between each node is // always 1 if (system == endSystemID) { complete = true; } } } }
List<int> route = new List<int>(); int systemId = endSystemID; route.Add(systemId); while (systemId != startSystemID) { int prevId = indexToId[previous[idToIndex[systemId]]]; route.Add(prevId); systemId = prevId; }
route.Reverse(); return route; }
This looks a little messy but I've tried a few variations with queue systems etc and this still gives the best performance.
The performance bottlenecks are GetNeighbourSystems and, to a lesser extent, InConstellation. The vast majority of the execution time (around 96%+) is taken up by calls to the database. I cache data as much as possible but many calls simply must be made and several hundred of them are always going to take a reasonable length of time. --------------------------------------
Trader? Investor? Just want to track your finances? Check out EMMA |

Ki Tarra
Caldari Ki Tech Industries
|
Posted - 2008.11.25 22:10:00 -
[34]
Originally by: Ambo The performance bottlenecks are GetNeighbourSystems and, to a lesser extent, InConstellation. The vast majority of the execution time (around 96%+) is taken up by calls to the database. I cache data as much as possible but many calls simply must be made and several hundred of them are always going to take a reasonable length of time.
Have you thought about making just one call to the database to get the jump table and storing it in a jagged array?
While it might be an expensive intial operation, it would likely save you a lot of long latency database operations later on.
If you structure the array properly, you could also avoid the frequent calls to a Dictionary object as those also carry a higher overhead than a basic array.
I'll see about drafting up some code to show you what I mean.
|

WolfSinger SilverShadow
Gallente Caldari Deep Space Ventures Arcane Alliance
|
Posted - 2008.11.25 22:36:00 -
[35]
I wrote soemthing like this in PHP about a month back using a varriant of Dijkstra's algorithm. A* works great if you can estimate distances between nodes in some way - you realy can't do this in EVE easily because of the way jump gates are laid out.
With mine, I was able to adjust "movement costs" so that it would try to avoind lowsec and 0.0 if you want. I never really got around to optimizing it, so each tiem you refresh the page, its gawd-awful slow as it reloads the the compelte universe system and node list from the static-dump DB. I also never beutified the outputm so it currently just dumps the best path array to the screen, displaying system numbers. Since I don't even look at contellations or regions, it should automaticly find a best path, even if it leads outside the region.
http://www.wolfsinger.com/~wolfsinger/eve/paths.php
|

Ambo
State Protectorate
|
Posted - 2008.11.26 08:09:00 -
[36]
Originally by: Ki Tarra
Originally by: Ambo The performance bottlenecks are GetNeighbourSystems and, to a lesser extent, InConstellation. The vast majority of the execution time (around 96%+) is taken up by calls to the database. I cache data as much as possible but many calls simply must be made and several hundred of them are always going to take a reasonable length of time.
Have you thought about making just one call to the database to get the jump table and storing it in a jagged array?
While it might be an expensive intial operation, it would likely save you a lot of long latency database operations later on.
If you structure the array properly, you could also avoid the frequent calls to a Dictionary object as those also carry a higher overhead than a basic array.
I'll see about drafting up some code to show you what I mean.
Maknig just the one database call to get all jump data is a nice idea and it certainly can improve things for the longer routes. However, overall performance for shorter routes does suffer.
You might be on to somthing with trying to remove the calls to the dictionary objects... Perhaps just subtracting 30000000 from the systemID and using that as the index would be better. I'll give it a go and see what happens. --------------------------------------
Trader? Investor? Just want to track your finances? Check out EMMA |

Ambo
State Protectorate
|
Posted - 2008.11.26 08:13:00 -
[37]
Originally by: WolfSinger SilverShadow I wrote soemthing like this in PHP about a month back using a varriant of Dijkstra's algorithm. A* works great if you can estimate distances between nodes in some way - you realy can't do this in EVE easily because of the way jump gates are laid out.
With mine, I was able to adjust "movement costs" so that it would try to avoind lowsec and 0.0 if you want. I never really got around to optimizing it, so each tiem you refresh the page, its gawd-awful slow as it reloads the the compelte universe system and node list from the static-dump DB. I also never beutified the outputm so it currently just dumps the best path array to the screen, displaying system numbers. Since I don't even look at contellations or regions, it should automaticly find a best path, even if it leads outside the region.
http://www.wolfsinger.com/~wolfsinger/eve/paths.php
Nice, it certainly seems to be accurate.
It's also a little slow though, 15 seconds or so for my longer route. --------------------------------------
Trader? Investor? Just want to track your finances? Check out EMMA |

Ambo
State Protectorate
|
Posted - 2008.11.26 18:06:00 -
[38]
I've had an idea:
reorganise the physical locations of systems so that the longest jump is much closer to the average.
This way, the distance-heuristic based A* algorithm becomes very fast indeed.
The only problem is how to reorganise all the systems... I'm working on an SQL algorithm to do it but it's proving tricky. --------------------------------------
Trader? Investor? Just want to track your finances? Check out EMMA |

Amida Ta
German Mining and Manufacture Corp.
|
Posted - 2008.11.26 20:04:00 -
[39]
I think you are doing wrong something ;)
I am using a simple breadth-first search and even for the longest paths my application does not need longer than 0.02 seconds to calculate them. On the other hand I'm using my EveAI data structures and no Database.
|

Alvaliella
|
Posted - 2008.11.26 22:10:00 -
[40]
Originally by: Amida Ta I think you are doing wrong something ;)
I am using a simple breadth-first search and even for the longest paths my application does not need longer than 0.02 seconds to calculate them. On the other hand I'm using my EveAI data structures and no Database.
Any chance you could elaborate please? Granted I'm not a proper programmer but I simply can't think of how this is possible- I mean surely you have to crunch through masses of route data at some point?  |

Amida Ta
German Mining and Manufacture Corp.
|
Posted - 2008.11.26 22:57:00 -
[41]
Originally by: Alvaliella Edited by: Alvaliella on 26/11/2008 22:37:23
Originally by: Amida Ta I think you are doing wrong something ;)
I am using a simple breadth-first search and even for the longest paths my application does not need longer than 0.02 seconds to calculate them. On the other hand I'm using my EveAI data structures and no Database.
Any chance you could elaborate please? Granted I'm not a proper programmer but I simply can't think of how this is possible- I mean surely you have to crunch through masses of route data at some point? 
Edit: Just had a thought- if you can add up the "jumps per hour" statistic over a few days for each system then that might be good to use as an A* heuristic? You'd chose whichever system had the highest number of jumps per hour (indicating that it's on a well travelled highway) rather than physical distance... it should eventually filter you onto the most commly used AutoPilot routes
Nothing fancy, really. You could even boost it a little bit by replacing the foreach, but it's not neccessary anyways...
public List<SolarSystem> FindRoute (SolarSystem start, SolarSystem end) { Queue<SolarSystem> openRoute = new Queue<SolarSystem> ();
start.Tag = start; openRoute.Enqueue (start);
while (openRoute.Count > 0) { SolarSystem current = openRoute.Dequeue (); if (current == end) { List<SolarSystem> way = new List<SolarSystem> (); while (current != start) { way.Add (current); current = (SolarSystem)current.Tag; } way.Add (start); way.Reverse (); return way; }
foreach (SolarSystem system in current.Jumps) { if (system.Tag != null) continue; system.Tag = current; openRoute.Enqueue (system); } } return null; }
|

Ki Tarra
Caldari Ki Tech Industries
|
Posted - 2008.11.26 23:31:00 -
[42]
Originally by: Alvaliella Any chance you could elaborate please? Granted I'm not a proper programmer but I simply can't think of how this is possible- I mean surely you have to crunch through masses of route data at some point? 
There really isn't that much crunching, atleast not for a computer.
I am working on building my own C# route generator.
First draft can load all of the data it needs form the database in ~0.13 second, and can calculate a 50 jump route in ~0.07 seconds.
I figure that I still have plenty of room to optimize that further as my current code still needlessly copies arrays in a few places.
As for possible heuristics for A*, don't forget the vital detail that the heuristic must never overestimate the distance to the destination. If the heuristic can over estimate its distances, then it may fail to find the proper route.
|

Amida Ta
German Mining and Manufacture Corp.
|
Posted - 2008.11.26 23:45:00 -
[43]
Btw: The route (9S-GPT in Outer Passage to XG-D1L in Cloud Ring) with 50 Jumps takes 0.0156250 sec to calculate using the method above on my Athlon 3500+ (2,2GHz).
|

Alvaliella
|
Posted - 2008.11.27 00:11:00 -
[44]
Originally by: Amida Ta magic code
Oooh- thank you kindly! Will examine/interrogate the code until it reveals it secrets...
Originally by: Ki Tarra First draft can load all of the data it needs form the database in ~0.13 second, and can calculate a 50 jump route in ~0.07 seconds.
Originally by: Amida Ta Btw: The route (9S-GPT in Outer Passage to XG-D1L in Cloud Ring) with 50 Jumps takes 0.0156250 sec to calculate using the method above on my Athlon 3500+ (2,2GHz).
Show offs ;P
As tempted as I am to put my crappy performance times down to my ailing P4 3.2GHz, I think it's more likely that my code may need further tweakage  |

Ambo
State Protectorate
|
Posted - 2008.11.27 08:15:00 -
[45]
Originally by: Ki Tarra
Originally by: Alvaliella Any chance you could elaborate please? Granted I'm not a proper programmer but I simply can't think of how this is possible- I mean surely you have to crunch through masses of route data at some point? 
There really isn't that much crunching, atleast not for a computer.
I am working on building my own C# route generator.
First draft can load all of the data it needs form the database in ~0.13 second, and can calculate a 50 jump route in ~0.07 seconds.
I figure that I still have plenty of room to optimize that further as my current code still needlessly copies arrays in a few places.
As for possible heuristics for A*, don't forget the vital detail that the heuristic must never overestimate the distance to the destination. If the heuristic can over estimate its distances, then it may fail to find the proper route.
Indeed, if I pre-load all the data I'll need then any of the methods I use will be blazingly fast.
However, loading everything into datatables when the app starts takes up too much memory and loading it all before calculating a route is too slow.
I think that my problem might be my use of the VS generated data access stuff. I'll try writing some stripped down access routines with more basic data structures and see where that gets me. --------------------------------------
Trader? Investor? Just want to track your finances? Check out EMMA |

Amida Ta
German Mining and Manufacture Corp.
|
Posted - 2008.11.27 09:24:00 -
[46]
Originally by: Ambo
Indeed, if I pre-load all the data I'll need then any of the methods I use will be blazingly fast.
However, loading everything into datatables when the app starts takes up too much memory and loading it all before calculating a route is too slow.
I think that my problem might be my use of the VS generated data access stuff. I'll try writing some stripped down access routines with more basic data structures and see where that gets me.
If you build an OO-representation (see my post above) we are talking about some 500kb of memory here which, on a current computer, is just about nothing. Also 500kb memory can be allocated in some milliseconds.
|

Ambo
State Protectorate
|
Posted - 2008.11.27 09:53:00 -
[47]
woohoo, that's got it!
I can load all the data I need in about 0.6 seconds when the program starts (memory useage is around 300k) Dijkstra then takes 0.09 seconds for the 50 jump route. --------------------------------------
Trader? Investor? Just want to track your finances? Check out EMMA |
| |
|
| Pages: 1 2 :: [one page] |