scikit-opt: Swarm Intelligence Algorithms in Python, and Where It Stops Being the Right Tool
Genetic Algorithm, Particle Swarm Optimization, Simulated Annealing, Ant Colony Optimization Algorithm,Immune Algorithm, Artificial Fish Swarm Algorithm, Differential Evolution and TSP(Traveling salesman)
At a glance
- What is it?
- scikit-opt packages genetic algorithms, particle swarm optimization, simulated annealing, ant colony optimization and several other metaheuristics behind a consistent Python API. It is a teaching and prototyping library, not a drop-in replacement for gradient-based optimizers or Bayesian optimization frameworks.
- Who is it for?
- Adopt scikit-opt when your objective is black-box, non-differentiable, or combinatorial, and when you want to swap operators without rewriting the loop. Do not adopt it for convex problems where scipy.optimize already converges, or for expensive evaluations where a surrogate model such as scikit-optimize would save more calls than a population method.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Activity is slowing. The repository last received commits 6 months ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What scikit-opt actually solves, and who reaches for it
Most Python optimization advice points at scipy.optimize, which expects gradients or at least a smooth, low-dimensional objective. scikit-opt targets the other case: the objective is a black box, the variables are mixed integer and continuous, or the search space is a permutation. The README describes the package as "Swarm Intelligence in Python" and lists genetic algorithm, particle swarm optimization, simulated annealing, ant colony algorithm, immune algorithm, artificial fish swarm algorithm and differential evolution. The TSP demos under examples/ (demo_ga_tsp.py, demo_pso_tsp.py, demo_sa_tsp.py, demo_aca_tsp.py) show the intended combinatorial use, and examples/vrp.py covers a vehicle routing variant. The audience is fairly narrow and fairly clear: researchers reproducing a metaheuristic, engineers who need a working baseline before investing in a custom solver, and instructors who want students to see selection, crossover and mutation as editable code rather than as a compiled black box. If your problem is differentiable and convex, this library is the wrong entry point, and nothing in its documentation claims otherwise.
How the algorithm loop is structured, and what the UDF hook changes
Each algorithm lives in its own module under sko/ (sko/GA.py, sko/DE.py, sko/PSO.py, sko/SA.py and so on), but the constructor signature is deliberately uniform: func, n_dim, size_pop, max_iter, lb, ub. You pass a callable that takes a candidate vector and returns a scalar. The algorithm owns the population, the bounds handling and the iteration counter; you own the objective. The interesting part is the operator registration API. The README states that UDF is available and that it supports "crossover, mutation, selection, ranking of GA". A registered operator receives the algorithm instance itself, which is why the example selection function reads algorithm.FitV and writes algorithm.Chrom directly. That is a wide interface: you are mutating internal state, not returning a value. It makes a dozen published variants expressible in a few lines, and it also means a miswritten operator can silently corrupt the population instead of raising. The README also shows subclassing GA and overriding selection, with ranking attached as a class attribute, for cases where registration is awkward. Both paths are documented; neither comes with a validation layer.
Installing scikit-opt and running a first differential evolution
The README gives a single install command, and setup.py confirms the runtime dependencies are numpy and scipy. Python 3.5 or newer is required. requirements.txt additionally lists matplotlib and pandas, but those are for the examples and plots, not for the library itself.
pip install scikit-optThe README also documents installing from a clone for the current developer version, using git clone followed by cd scikit-opt and pip install . The first real use is differential evolution on a constrained three-variable problem. The README's example minimizes x1^2 + x2^2 + x3^2 subject to x1*x2 >= 1, x1*x2 <= 5 and x2 + x3 = 1, with all variables in [0, 5]. Equality and inequality constraints are passed as separate lists of callables.
from sko.DE import DE
def obj_func(p):
x1, x2, x3 = p
return x1 ** 2 + x2 ** 2 + x3 ** 2
constraint_eq = [lambda x: 1 - x[1] - x[2]]
constraint_ueq = [lambda x: 1 - x[0] * x[1], lambda x: x[0] * x[1] - 5]
de = DE(func=obj_func, n_dim=3, size_pop=50, max_iter=800, lb=[0, 0, 0], ub=[5, 5, 5],
constraint_eq=constraint_eq, constraint_ueq=constraint_ueq)
best_x, best_y = de.run()
print('best_x:', best_x, '\n', 'best_y:', best_y)run() returns the best candidate and its objective value. Because the search is stochastic, two runs with the same arguments will not agree exactly; the README does not document a seed parameter, so do not expect bit-identical reproduction without checking the source of the module you use.
Resuming a run, and the four acceleration modes
Two features are worth knowing before you write your own outer loop. First, continuing a run: since version 0.3.6, calling run() twice on the same instance continues from the current population rather than restarting. The README's example runs ten iterations and then twenty more. That is useful for checkpointing long searches, but it also means the iteration budget is cumulative, so a stray second call changes your result.
from sko.GA import GA
func = lambda x: x[0] ** 2
ga = GA(func=func, n_dim=1)
ga.run(10)
ga.run(20)Second, the README lists four ways to accelerate the objective function: vectorization, multithreading, multiprocessing and cached. The implementation is demonstrated in examples/example_function_modes.py rather than in the README prose, so read that file before assuming a mode exists for your algorithm. The distinction matters because the acceleration applies to how func is evaluated, not to the search loop itself. A vectorized objective must accept a batch of candidates; a cached one must tolerate repeated inputs. The README does not state which algorithms support which modes, and the GPU path is explicitly described as under development, with stability promised for version 1.0.0 and an example at examples/demo_ga_gpu.py. Treat GPU as experimental for now.
Where scikit-opt is the wrong choice
Population methods spend function evaluations freely. If one evaluation costs minutes of simulation or a paid API call, a genetic algorithm or PSO will burn your budget before it converges, and a surrogate-based method is the better fit. scikit-opt has no surrogate model, no acquisition function and no Gaussian process layer; nothing in the README or the repository layout suggests one is planned.
The second limitation is convergence guarantees. Metaheuristics offer none. The documentation describes how to configure and extend the algorithms, not how many iterations a given problem needs, and there is no stopping criterion beyond max_iter. You will be tuning size_pop and max_iter by trial, and the library will not tell you whether the answer it returned is near-optimal or merely the best of a bad population.
The third is scale. The population is stored as a NumPy array indexed by individual, and the UDF examples manipulate it in Python loops over size_pop. That is fine for hundreds of individuals and dozens of dimensions. It is not a design for problems where the population itself must be distributed, and the README does not describe a distributed execution mode. Finally, the release history listed on the repository tops out at v0.6.5 from 2021-06-28, while the last push to master was on 2026-03-25. The repository is not archived, but a five-year gap between the newest listed release and a recent commit means you should read the current source, not the release notes, when you need to know what a function does today.
scikit-opt versus scikit-optimize, and why the names collide
The most common confusion is with scikit-optimize, imported as skopt. They share a naming convention and almost nothing else. scikit-optimize implements Bayesian optimization: it builds a probabilistic surrogate of the objective and chooses the next point by maximizing an acquisition function, which is the right approach when evaluations are expensive and the dimension is modest. scikit-opt implements population and trajectory metaheuristics, which sample many points per iteration and make no assumptions about smoothness. The trade is evaluations against assumptions. If a single call to your objective is cheap and you need to explore a rugged or combinatorial space, scikit-opt is the more natural fit. If a single call is costly, skopt's surrogate will usually reach a good region in fewer evaluations, at the price of assuming the objective is reasonably smooth and low-dimensional. Note also that scikit-opt is not scikit-learn and has no relation to it; it is a standalone package by Guo Fei under the MIT license, with numpy and scipy as its only install requirements.
Licence, maintenance and the cost of upgrading
scikit-opt is MIT licensed, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. That is among the least restrictive options and imposes no copyleft obligation on your own code. This is a description of the licence text, not legal advice; check LICENSE in the repository if your organization has specific requirements.
The upgrade cost is the part to plan for. The newest release listed is v0.6.5 from 2021-06-28, so pinning to a released version means pinning to code that predates recent commits on master. The last push to master was on 2026-03-25, which tells you the repository has seen activity, but the README does not document a changelog, a deprecation policy or a migration guide for the operator API. If you register custom operators, you are depending on internal attributes such as Chrom and FitV, and those are exactly the surfaces an upgrade can move. Install from a pinned version, keep your operator code in one module, and re-run your objective against the new version before switching. Because the only hard dependencies are numpy and scipy, the dependency-graph cost of upgrading is close to zero; the risk sits entirely in the operator interface you wrote.
Editorial conclusion
Adopt scikit-opt when your objective is black-box, non-differentiable, or combinatorial, and when you want to swap operators without rewriting the loop. Do not adopt it for convex problems where scipy.optimize already converges, or for expensive evaluations where a surrogate model such as scikit-optimize would save more calls than a population method. Before committing, verify that your installed version exposes the operator you need: the README documents UDF registration for crossover, mutation, selection and ranking of GA only, and the latest release listed is v0.6.5 from 2021-06-28, so check the sko/operators directory in the checkout you install rather than assuming the docs match it.
Frequently asked questions
What is scikit-opt used for in Python?
It provides implementations of genetic algorithms, particle swarm optimization, simulated annealing, ant colony optimization, differential evolution, immune algorithm and artificial fish swarm algorithm behind a consistent API. Typical uses shown in the repository are continuous objective minimization and traveling salesman style problems. The README describes the package as swarm intelligence in Python.
How do I install scikit-opt?
The README gives pip install scikit-opt as the install command, and setup.py lists numpy and scipy as the only runtime requirements. Python 3.5 or newer is required. For the developer version, the README documents cloning the repository and running pip install . from the checkout.
Can I supply my own crossover, mutation or selection operator to scikit-opt?
Yes. The README states that UDF is available and that it supports crossover, mutation, selection and ranking of GA, and shows registering a custom selection function with ga.register. The alternative it documents is subclassing GA and overriding the selection method. The README does not describe UDF registration for the other algorithms.
Does scikit-opt support GPU computation?
The README says GPU computation is being developed and will be stable on version 1.0.0, with an example at examples/demo_ga_gpu.py. It does not present GPU support as ready. Treat it as experimental until the documentation says otherwise.
Is scikit-opt the same as scikit-optimize or skopt?
No. scikit-opt is a separate MIT-licensed package by Guo Fei that implements population and trajectory metaheuristics. scikit-optimize, imported as skopt, implements Bayesian optimization with a surrogate model. The repository material does not describe any relationship between the two.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/guofei9987-scikit-opt)