riiswa / colony-ant-simulator

Simulation of ants colony in python
GNU General Public License v3.0
57 stars 13 forks source link

[IMPROVEMENT] From TKinter to PyGame #14

Open riiswa opened 1 year ago

riiswa commented 1 year ago

It would be really cool to switch from TKinter to PyGame, especially for performance reasons and to allow the simulation of many more ants!

emmanuel-ch commented 1 year ago

The issue of speed is when we have a high number of pheromones. Since pheromones stack up on 1 position, maybe we could increase the "intensity" of the existing pheromones instead of creating new ones? It would imply a rework of the functions creating move_tab, but surely will be demanding less efforts!

If you can explain the logic behind the move_tab, find_nest(), pheromones_affinity(), STEP_GRID, then i could give a try to the suggestion above.

emmanuel-ch commented 1 year ago

@riiswa I'm working on a workaround using dataframes to store pheromones information, but that implies reworking functions pheromones_affinity and find_nest.

pheromones_affinity: Can you confirm that the intend is to have HG to store the number of pheromones in the top-left (Haut Gauche) corner of the canvas (relative to ant's position)? (And same for HD, BG, BD)


    HG_o = canvas.find_overlapping(0, 0, ant_coords[0], ant_coords[1])
    HD_o = canvas.find_overlapping(e_w, 0, ant_coords[0], ant_coords[1])
    BG_o = canvas.find_overlapping(0, e_h, ant_coords[0], ant_coords[1])
    BD_o = canvas.find_overlapping(e_w, e_h, ant_coords[0], ant_coords[1])
    HG = len(HG_o) - (2 + sim_args.n_ants)
    HD = len(HD_o) - (2 + sim_args.n_ants)
    BG = len(BG_o) - (2 + sim_args.n_ants)
    BD = len(BD_o) - (2 + sim_args.n_ants)

find_nest: Is it the same intend?

    HD_o = canvas.find_overlapping(e_w, 0, ant_coords[0], ant_coords[1])
    BG_o = canvas.find_overlapping(0, e_h, ant_coords[0], ant_coords[1])
    BD_o = canvas.find_overlapping(e_w, e_h, ant_coords[0], ant_coords[1])
    HGn = HG_o[0]
    HDn = HD_o[0]
    BGn = BG_o[0]
    BDn = BD_o[0]

    HG = len(HG_o) - 2 - sim_args.n_ants
    HD = len(HD_o) - 2 - sim_args.n_ants
    BG = len(BG_o) - 2 - sim_args.n_ants
    BD = len(BD_o) - 2 - sim_args.n_ants

Thanks for confirming! :)

dragonpop76 commented 1 year ago

Is this still something that's being pursued for this project? Agree that it would be a great way to improve simulation performance

nickumia commented 1 year ago

I agree with @emmanuel-ch.. I don't think the GUI framework is the root cause of performance issues. I was trying to find out what the most performant GUI framework is, but to no avail. I think @emmanuel-ch is correct in saying that the slowdown is attributable to the creation of memory components all of which grow exponentially with the number of ants. To refactor the code and represent each cell as a single unit that has a pheromone value is more trouble than I would put effort towards, but it is the better solution.

I haven't looked at the code in great detail in a while, but the Nest, Food and Ant classes all track position in itself. So if there are 1,000,000 ants, there are 1,000,000 objects with position data as opposed to 400,000 position boxes (assuming the 800x500 grid). It could be further optimized and discretized to a smaller level (i.e. 4,000 for 80x50 grid each box representing 10 sub-cells). Performance optimizations are always a delicate tradeoff.

The best solution that I can think of is a sort of sparse matrix or dictionary lookup of initialized positions. Essentially, you don't need to track 400,000 positions at the start. You can start with just the positions that have a Nest, an Ant or some Food and if the Ant moves to a valid position that hasn't been initialized, then create it. It'll grow to a maximum of the largest size of the m x n grid, but it might never reach the full amount still.

I'm happy to help again if we come up with an accepted solution and break it up into manageable pieces 🏗️

P.S. I was the one who converted the original code into the code fragments you referenced @emmanuel-ch, but I don't know if it was supposed to be (0,0) at the top-left. The general standard for TK is for (0,0) in the top-left though and I don't suspect we changed that default.

References:

emmanuel-ch commented 1 year ago

@nickumia - I have a branch ready with the solution you mentioned: a numpy array storing pheromones. Displaying only the "reduced" version on the screen: 1 circle for each location of pheromone. I'll make a PR for it in the next couple of days.

riiswa commented 1 year ago

Thank you for you research @nickumia , and I think you're right, we should save time in the data management, and not on the GUI part.

@emmanuel-ch It could be interesting to see if we can use numba, to have a GPU compatible simulation. I can't wait to see your PR :)

emmanuel-ch commented 1 year ago

Challenge accepted! I'll share my conclusions once the current PR is accepted and we perform additional refactoring - I can still see places where code is suboptimal.