-
Notifications
You must be signed in to change notification settings - Fork 333
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
Feature parameterize obj #144
Feature parameterize obj #144
Conversation
both global_best and local_best
Hi @bradahoward ! Awesome PR, I appreciate the unit tests and the updates in documentation. Some comments:
def optimize(f, iters, print_step, verbose, *args, **kwargs):
# Stuff...
self.swarm.current_cost = objective_func(self.swarm.position, *args, **kwargs)
self.swarm.pbest_cost = objective_func(self.swarm.pbest_pos, *args, **kwargs) Would you mind testing this one out? Using So as far as I know, we just need to update the
|
pyswarms/base/base_discrete.py
Outdated
@@ -193,7 +193,7 @@ def _populate_history(self, hist): | |||
self.pos_history.append(hist.position) | |||
self.velocity_history.append(hist.velocity) | |||
|
|||
def optimize(self, objective_func, iters, print_step=1, verbose=1): | |||
def optimize(self, objective_func, iters, args=(), kwargs={}, print_step=1, verbose=1): | |||
"""Optimizes the swarm for a number of iterations. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe *args
and **kwargs
will work here instead of args=()
and kwargs={}
?
pyswarms/base/base_single.py
Outdated
@@ -224,7 +224,7 @@ def _populate_history(self, hist): | |||
self.pos_history.append(hist.position) | |||
self.velocity_history.append(hist.velocity) | |||
|
|||
def optimize(self, objective_func, iters, print_step=1, verbose=1): | |||
def optimize(self, objective_func, iters, args=(), kwargs={}, print_step=1, verbose=1): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe *args
and **kwargs
will work here instead of args=()
and kwargs={}
?
pyswarms/discrete/binary.py
Outdated
@@ -149,7 +149,7 @@ def __init__( | |||
# Initialize the topology | |||
self.top = Ring() | |||
|
|||
def optimize(self, objective_func, iters, print_step=1, verbose=1): | |||
def optimize(self, objective_func, iters, args=(), kwargs={}, print_step=1, verbose=1): | |||
"""Optimizes the swarm for a number of iterations. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe *args
and **kwargs
will work here instead of args=()
and kwargs={}
?
pyswarms/single/global_best.py
Outdated
|
||
cli_print("Arguments Passed to Objective Function: \nargs: %s \nkwargs: %s\n" % (args, kwargs), | ||
verbose, 2, logger=self.logger) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is good, keep this. I'd suggest using:
cli_print("Arguments passed to objective function: \nargs: %s \nkwargs: %s\n" % (*args, **kwargs),
verbose, 2, logger=self.logger)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It appears that using **
outside of a function call throws an IndexError
. The Python documentation around this uses them without the decorators in the outside of the function call.
https://docs.python.org/dev/tutorial/controlflow.html#more-on-defining-functions
Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops. Yes, you are correct, just remove **
and it should print. One last Python 3.X thing, perhaps a .format()
is better?
name = 'ljvmiranda921'
print("Hi my name is: {}".format(name))
I'd probably update my cli_print
soon to make everything uniform.
pyswarms/single/global_best.py
Outdated
self.swarm.current_cost = objective_func(self.swarm.position) | ||
self.swarm.pbest_cost = objective_func(self.swarm.pbest_pos) | ||
self.swarm.current_cost = objective_func(self.swarm.position, *args, **kwargs) | ||
self.swarm.pbest_cost = objective_func(self.swarm.pbest_pos, *args, **kwargs) | ||
self.swarm.pbest_pos, self.swarm.pbest_cost = compute_pbest( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my opinion, this is just the modification we need. That is, to provide flexibility in the objective_function by providing an optional *args
or **kwargs
argument. There's no need to put args = ()
or kwargs = {}
in the main optimize()
method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure! I fixed the optimize prototypes. The only goofy thing there is the *args had to be listed before the other key word arguments i.e. def fun(foo, bar, *args, baz=3, **kwargs)
@@ -104,7 +104,7 @@ def assertions(self): | |||
"Missing methods in optimizer, check " "pyswarms.base module" | |||
) | |||
|
|||
def __init__(self, optimizer, objective_func, iters): | |||
def __init__(self, optimizer, objective_func, iters, obj_args=(), obj_kwargs={}): | |||
"""Runs the optimizer against an objective function for a number |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to touch this 👍 This will be Deprecated soon. Simply revert this to the original to avoid merge conflicts down the road.
pyswarms/utils/search/base_search.py
Outdated
@@ -33,6 +33,8 @@ def __init__( | |||
options, | |||
objective_func, | |||
iters, | |||
obj_args=(), | |||
obj_kwargs={}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to avoid obj_args=()
and obj_kwargs={}
? If not, just revert this to the original. I'm planning to update its API soon
from pyswarms.single import GlobalBestPSO, LocalBestPSO | ||
from pyswarms.utils.functions.single_obj import rosenbrock_func | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the awesome tests! Just a few more tests to write:
- Can you please test if an error is raised when
*args
/**kwargs
is passed but it's not defined in the objective function itself? (e.g. I passedc
andd
but rosenbrock acceptsa
andb
). - Can you also test if error is raised when not all
*args
/**kwargs
are supplied? (e.g. I only passeda
but rosenbrock accepts botha
andb
) - Test what happens if I passed more than one
*args
/**kwargs
than necessary.
fixed function prototypes and added requested tests
Thanks for this @bradahoward! I'll go over this PR hopefully this weekend, just need to finish this week, etc. Noted on your questions, I will try some variants on my end and let's see what works. |
Hi @bradahoward , I'm thinking of just using # Sample usage
def f(x, a, b):
"""An objective function with two params a and b"""
j = (x**2.0).sum(axis=1)
return (a * j + b)
optimizer = GlobalBestPSO(n_particles=10, dimensions=2, options)
optimizer.optimize(f, iters=100, a=5, b=6) No need for This is a short demo on how I imagine it to be used: https://repl.it/@ljvmiranda921/PySwarmsKwargs |
hi @ljvmiranda921 -- thanks for the quick feedback! If it were me, i would only use For the |
change to only **kwargs implementation, changed to .format() string method, and fixed tests
Hi @bradahoward , Awesome! Everything looks good to me (LGTM) now. You're correct, I think explicitly naming the arguments via I will squash all your commits into a single one. Just update your own branch after I have merged your work into Anyway, super thankful for your help and contribution, I appreciate your help and you're very easy to work with! |
#143
Implementation
Used both
*args
and**kwargs
so user can choose which one they prefer. Added toGlobalBestPSO
,LocalBestPSO
andBinaryPSO
. Also added an example IPython notebook to demonstrate usage.