-
Notifications
You must be signed in to change notification settings - Fork 335
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement new Topologies #129
Comments
Wanna try one, @szhan? |
Yes! I am just finishing up a PR on another repo. I will get to this next! P.S. The new release looks awesome! Great job! |
FYI: Found this one when googling around a bit. According to that page, the pyramid and Von Neumann topologies are the best ones. There is also this WK-recursive pyramid topology which seems like bleeding edge technology (sadly I have no access to the paper). |
Woops just read this one. Sure go ahead and pick one, @szhan ! I'm still finding ways on how to best represent the data structures for other topologies so this will be a learning experience for me too. Awesome, @whzup ! Yes, I think pyramid and Von Neumann topologies are actually good. Really hoping we can implement one (or both) to release v.0.3.0. Thanks for pointing that one out! |
Hey guys! I have implemented a class for a pyramid topology using the Delaunay triangulation from the
Which is kind of ironical as I have implemented these two functions similarly to the other two existing topologies like so: Since the generation of the swarm is not dependent on the topology and the |
Hey thanks @whzup ! Hmmm, that sounds weird. Would you mind opening a PR so we can see the code itself? My guess is that the invisible argument is coming from Just make sure that the branch you are working on is different from the inverse kinematics branch before (so we won't have any merge conflicts later on). 👍 I'll look at this later tonight or on Monday. Maybe @SioKCronin might want to take a look? |
Awesome! Since @whzup has already implemented the pyramid topology, I will take a stab at the Von Neumann topology. |
Sorry to be slow on response. @szhan, I'm happy to help if you need anything with the Von Neumann topology. |
Reference: #129 Created a class for the implementation of a pyramid topology using Delaunay triangulation. Additionally, @whzup changed a small error in the description of the `compute_velocity()` method in the Ring class. Notes: - For v.0.2.0-dev.3. - TODO: Update README in dev Committed with: @whzup Signed-off-by: Lester James V. Miranda <ljvmiranda@gmail.com>
Hey, guys! I was looking around on the internet for some interesting topologies and I found this paper. It actually claims that a Von Neumann topology is nothing more than a static ring topology with 4 neighbours 🙈. So I guess we can cross this one out. Furthermore, I found this paper, I like this proposal of the mixture of topologies (static and dynamic) in one swarm to combine the best of both. But it might require another |
Another thing: Currently we only have dynamic approaches for the topologies, except the
If we use the swarm as a static attribute in the superclass |
We can keep the neighbor parameter as an attribute to the Swarm class. It
is flexible given the attrs module.
We initialize the number of particles in the SwarmOptimizer beforehand, by
that stage we can assign which one is a neighbor if which.
```python
t = Ring(static=True)
opt = GeneralOptimizer(n_particles=10, dimensions=2, options=options,
topology=t)
# By this stage we already have the indexing information for each neighbor.
Computing gbest or lbest will just require accessing this matrix/data
structure. We can keep this matrix either as an attribute to the Swarm or
SwarmOptimizer.
```
The idea is that if you have 6 particles, we create a vector containing the
“clusters.” Say we have a Ring topology (static with 2 neighbors), then we
have a vector:
[1, 1, 1, 2, 2, 2] : not necessarily in the order.
Computing lbest for each cluster will then be as simple as accessing which
particle is in group 1 or group 2, etc.
|
The reason why we want to separate the Swarm and the Topology is because we
want to delineate the particles and how they are connected:
- The `Swarm` holds the data while the `Topology` holds the interactions among these datapoints (particles).
- The latter governs how everything behaves, etc. And then, we have a SwarmOptimizer that enables this behavior.
|
Ok, I see your point. But we still need to pass the topology information to the swarm or vice versa. How about we implement a new method into the topology classes called if self.top.static:
self.top.assign_neighborhood(self.swarm) in the if not self.top.static:
self.top.assign_neighborhood(self.swarm) in the iteration. @ljvmiranda921 do you think this is more approriate? |
Hi, @whzup that works and it's closer to how I imagined it. My e-mail replies are a bit confusing (and I realized that I cannot use markdown in e-mails). Design-wise, I'd prefer to have a few number of methods in the By maintaining a strict set of methods exposed in the Topology class, it's easier to swap-out topologies whenever needed in the I understand your point that we should not compute the neighbor information for each iteration, and there should be a way to store it. And this requires passing the To add to your suggestion, what if we add an optional # ring.py
def __init__(static=False, swarm=None):
if static and swarm==None:
raise ValueError In that case, we can create a We can also add a |
There is one problem if we pass in the swarm as an optional parameter. If you use the import pyswarms as ps
# Other code
...
swarm = ps.backend.swarms.Swarm(params)
my_topology = Ring(static=True, swarm)
ps.single.GeneralOptimizer(func, swarm, topology=my_toplogy) Which, in my opinion, adds an extra layer of complexity for the user. How about this, we have a # in compute_gbest()
if self.static and neighbor_idx is None or not self.static:
# Set neighbor_idx So in the former, the On the |
Awesome, that's a good solution, @whzup ! So, the sample use-case will then be (?): import pyswarms as ps
# Other code
t = Ring(static=True)
opt = ps.single.GeneralOptimizer(func, n_particles, dimensions, topology=t) And then the For the cluster (I'm not sure of the correct name, unfortunately), it's just the local best between neighbors. So if we have 6 particles with 2 neighbors:
We compute for the best position found by those with index 1,2, and so on. |
Yes, that would be the sample use-case I guess 👍. Isn't this almost the same as calculating the best neighbour then? |
Hmmm...not sure with the best terminology though. Let's just leave that for now. Maybe |
Hey guys! I was pondering a bit about PSO topologies and I thought of another way to calculate a topology, I don't know if this already exists but it may be worth a thought. I thought about using convex hulls of the particles to create different layers of rings. So in the first stage we calculate the convex hull of the whole set of particles and connect the particles that lie on the convex hull: |
@szhan if you still want to implement the |
Reference: #129 Added a new topology with random neighbors. Added documentation and a test file for it and reworked the documentation of the GeneralOptimizer class to incorporate all available topologies. Simplified the fixture function for the GeneralOptimizer class. Cited the relevant paper for the algorithm implemented. Updated the documentation of the Random class. Especially the __compute_neighbor() method. Added the comments inside the method to the docstring and deleted irrelevant comments. Changed the nested for-loops to one loop with the itertools library. Added a new test for the return value of the __compute_neighbor() method, which checks the shape and the symmetry. Added a new test for the return value of the __compute_neighbors() method, which compares the returned matrix with a preset comparison matrix using a seed. Signed-off-by: Lester James V. Miranda <ljvmiranda@gmail.com> Committed-by: @whzup
Reference: #129 Added two new attributes to the topologies. `static` decides whether the topology is a static or a dynamic one, it is initialized together with the class. `neighbor_idx` is an array that stores the indices of the neighbors of every particle. Changed all occurrences of topologies to fit the new initialization. Reworked the tests to fit the new functionality and added more parametrization of fixture functions. Updated the documentation to incorporate the new functionality. Signed-off-by: Lester James V. Miranda <ljvmiranda@gmail.com> Commited-by: @whzup
I'll close this for now since we got the major ones in the development branch. Let's just refer back to this issue in the future for other swarm topologies. 👍 |
There are some topologies that we can implement in
pyswarms.backend
:static
): currently, our Ring topology is dynamic. It looks for the nearest neighbors in the current iteration and there is some neighbor overlap. In a static-ring topology, the neighbors are locked down for each particle. There is still overlap, but it doesn't change every iteration. low-hanging fruitReferences: HeuristicLab.
Implementing a Topology
To implement a Topology, simply:
pyswarms.backend.topology.Topology
classcompute_gbest()
,compute_position
, andcompute_velocity
.You can check the implementations in the Star or Ring topologies.
References:
The text was updated successfully, but these errors were encountered: