Problem Builder
Define a custom optimization problem step by step, no code required. Supports multiple objectives.
Go to the live page Open the Problem BuilderThe Problem Builder is a guided wizard that lets you define a custom optimization problem from scratch. You pick the variables, write a formula or choose a built-in fitness function, optionally add more objectives, and the platform runs the problem for you. Saved problems show up under My problems so you can re-run or tweak them later.
Why use the Problem Builder?¶
Quick submissions cover the handful of pre-built problem shapes the platform ships with. The New Submission form gives you a blank canvas of Python code. The Problem Builder sits between them and earns its place for several reasons.
- Define your own problem shape. Pick your own variables, ranges, and objectives. You are not limited to the categories Quick submissions list.
- Save your GA parameters once. When you run a saved problem, the GA settings you picked when building it become the defaults. You only override what changes for this run.
- One source of truth, many runs. Save a problem, then start a new run any time. Tweak generations or mutation for this run only; the saved problem stays the same so you can compare runs cleanly.
- Multi-objective without ceremony. Add more than one objective and the system switches to NSGA-II automatically. No need to remember which parent-selection type is allowed.
- See it before you run it. Each objective shows a live preview as you build, and a Generated fitness function panel shows the exact Python the GA will run. Wrong formulas surface in seconds, not after a full run.
- No code required for common shapes. Pick a library template (sum, target-matching, regression, constrained) and fill in inline parameters. Move to Custom code only when you need to.
- Code with confidence when you need to. When you switch to Custom code, the editor lists every variable name and the GA parameters you can reach via
ga_instance. The code you write is the code the GA runs.
The five steps¶
The wizard walks you through six steps. You can move forwards and backwards freely, and you can jump straight to a step by clicking the label at the top. Nothing is saved until you reach Step 6 and choose Save without running or Save and run.
1. Basics¶
Give the problem a short, recognisable name. Add a description if you want a reminder of what it is for.
2. Genes¶
Each row on this step defines one gene, one value the GA will tune. Inside your fitness function, the genes arrive as the entries of solution in the order you list them here. The first gene becomes solution[0], the second solution[1], and so on.
Pick the type that matches each gene's search space:
- Continuous (low/high) is the common case. Set a low and a high; optionally add a step to snap the gene to a regular grid.
- List of values restricts the gene to a fixed set of numbers (use
Noneto mean "unconstrained for this entry"). - Integer range wraps
range(start, stop)and optionally a step. - Linspace wraps
numpy.linspace(start, stop, num). - Any leaves the gene unconstrained.
Names must be valid Python identifiers like x, lr, or batch_size. Names cannot repeat within the same problem.
This step is a friendly wizard for PyGAD's gene_space. If you want raw control instead, leave the step minimal and write the gene_space directly in Step 5 → Show advanced parameters → gene_space (override). Whatever you put there wins over what this step derives.
Constants the fitness function uses but the GA does not tune belong in the next step (Problem parameters), not here.
3. Problem parameters¶
Problem parameters are constants your fitness function uses alongside the genes. The GA does not optimise them; they stay fixed for the whole run. Reference them in formulas, library templates, or custom code by name.
For each parameter, give it a name (a valid Python identifier), pick a type, and set the value:
- Number for a single float.
- List of numbers for a 1-D array, written comma-separated (e.g.
1, 2, 3). - 2-D list of numbers for a matrix, one row per line.
- String for a label.
- Other (raw Python) when none of the above fits. Type any Python literal here (for example
numpy.array([1, 2, 3])or{"a": 1, "b": 2}); the wizard emits it verbatim into the rendered fitness source, so it is your responsibility to make sure it is valid Python.
Examples: a target value to match, an input matrix for a regression, a coefficient. If your fitness needs no constants, skip this step.
The wizard rejects names that clash with a gene's name because both end up as in-scope Python identifiers when the fitness function runs. This step is a friendly wizard for declaring constants once and reusing them across formulas, library templates, and custom code. If you prefer raw control, skip it and hard-code the same constants directly inside your Custom code in the next step.
4. Fitness function¶
This is the single function the GA evaluates for every candidate. Each row in this step contributes one objective to that function. When you have more than one objective, the system combines them into one function that returns all the values together, and the GA switches to NSGA-II to balance them. A panel at the bottom of the step shows the generated Python source so you can see exactly what the GA will run.
Each objective has:
- Direction: Maximize or Minimize. The system handles the sign flip so your formula or code stays readable.
- Source: Formula, Library template, or Custom code.
Formula mode is the default. Type a mathematical expression using the variable names from Step 2. For example, x**2 + y - 10. As you type, a preview evaluates the formula with each variable at the midpoint of its range. The allowed operators and functions are: + - * / **, abs, min, max, sum, round, pow, and your variable names.
Library template mode picks a built-in fitness function from a gallery: Sum of Genes, Reciprocal of Sum-of-Squares, Match a Target, Linear Regression Target, Regression error (1 / MSE), Constrained Sum. Most entries expose inline parameters you can tune without writing code (for example, the target value to match, the inputs and target vector for the regression entries, or the limit for the constrained sum). The Python source updates as you edit the parameters so there are no surprises.
If you have already defined a problem parameter with the same name as one of a library entry's slots, the slot picks up that value automatically. Per-objective inline overrides still win, so you can use one global default and bend it for individual objectives.
Click Browse & customize to open the gallery. It opens with the current template selected and the editor pre-filled. If you change the code, the row switches to Custom code mode with your edits in place. If you do not change the code, the row stays in Library template mode with the parameters you picked.
Custom code mode is for when you want to write the Python yourself. The editor lists which gene maps to each solution[i], which Problem parameters are in scope, and which GA parameters are accessible via ga_instance.*. Any Problem parameters you defined in Step 3 are emitted as top-level assignments above your fitness_func, so you can reference them by name. The code must define fitness_func(ga_instance, solution, solution_idx). Preview is not available for Custom code; the actual run executes it in a secure environment.
5. GA parameters¶
The genetic algorithm has a handful of knobs that control how it searches. The defaults are sensible for a first run; tweak from there if you need to. Every knob has a small help icon next to it that explains what it does.
The wizard exposes:
- Number of generations
- Population size
- Number of parents mating
- Mutation type
- Crossover type
- Parent selection type
Click Show advanced parameters to reveal more controls (probabilities, keep parents, keep elitism, K-tournament, init range, save flags, stop criteria, and a builder for the initial population). The advanced section also lets you override the auto-derived gene space with a custom one using the same visual builder available on the New Submission form, and it exposes the seven lifecycle callbacks (on_start, on_fitness, on_parents, on_crossover, on_mutation, on_generation, on_stop). Each callback is optional; leave a field blank to skip it. The same scope hints as Step 3 are shown next to each callback so you always know what is available.
The wizard checks two rules for you:
- The number of parents mating cannot be larger than the population size.
- Multi-objective runs use NSGA-II for parent selection.
6. Review and save¶
The last step shows everything you defined in one place. Each card has an Edit link that jumps you back to the relevant step. When you are happy:
- Save without running stores the problem under My problems without using any of your run budget. You can come back and run it any time.
- Save and run stores the problem and immediately starts a run. You land on the live result page where you can watch the generations tick by.
Running a saved problem¶
Open My problems and click New run on the card. You land on a two-section page:
- Problem definition is read-only here. It shows the genes, problem parameters, and objectives you saved. Use Edit problem if you want to change them.
- GA parameters are pre-filled with the values you saved with the problem. Override anything for this run; the saved defaults stay the same.
Click Run to start the run. Every run is a normal submission and appears in your usual User submissions list with full results and history.
Click Edit instead of New run when you want to change the problem itself. The wizard opens with all your saved values pre-filled.
When to write code instead¶
The Problem Builder is intentionally focused. If your fitness function needs to load a dataset, call a Python library, or run anything more complex than what the library templates cover, the New submission form is the right path. There you can paste a full Python function and use every parameter the GA supports. Custom code mode in the Problem Builder is a good middle ground: write the function inline and keep the saved-defaults benefit of a stored problem.