Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
# Changelog

## Unreleased

Changes:
* Feat: enforce maximum evolved tree-GP size with `max_len` instead of just the initial size ([#245](https://github.com/xcsf-dev/xcsf/pull/245))

## Version 1.5.1 (Aug 24, 2026)

Changes:
* CI fix macosx_x86_64 wheel building ([#244](https://github.com/xcsf-dev/xcsf/pull/244))
* CI: fix macosx_x86_64 wheel building ([#244](https://github.com/xcsf-dev/xcsf/pull/244))

## Version 1.5.0 (Aug 24, 2026)

Expand Down
6 changes: 5 additions & 1 deletion test/cond_gp_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* @file cond_gp_test.cpp
* @author Richard Preen <rpreen@gmail.com>
* @copyright The Authors.
* @date 2023--2024.
* @date 2023--2026.
* @brief GP condition tests.
*/

Expand Down Expand Up @@ -114,6 +114,10 @@ TEST_CASE("COND_GP")
// check trees are different
CHECK(!check_array_eq_int(dest_cond->gp.tree, src_cond->gp.tree, n));

/* Test max_len enforced during crossover */
tree_param_set_max_len(targs, 2);
CHECK(!cond_gp_crossover(&xcsf, c1, c2));

/* Smoke test export */
char *json_str = cond_gp_json_export(&xcsf, c1);
CHECK(json_str != NULL);
Expand Down
6 changes: 2 additions & 4 deletions xcsf/cond_gp.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@
* @file cond_gp.c
* @author Richard Preen <rpreen@gmail.com>
* @copyright The Authors.
* @date 2016--2022.
* @date 2016--2026.
* @brief Tree GP condition functions.
*/

#include "cond_gp.h"
#include "ea.h"
#include "sam.h"
#include "utils.h"

/**
Expand Down Expand Up @@ -149,8 +148,7 @@ cond_gp_crossover(const struct XCSF *xcsf, const struct Cl *c1,
struct CondGP *cond1 = c1->cond;
struct CondGP *cond2 = c2->cond;
if (rand_uniform(0, 1) < xcsf->ea->p_crossover) {
tree_crossover(&cond1->gp, &cond2->gp);
return true;
return tree_crossover(&cond1->gp, &cond2->gp, xcsf->cond->targs);
}
return false;
}
Expand Down
40 changes: 24 additions & 16 deletions xcsf/gp.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* @file gp.c
* @author Richard Preen <rpreen@gmail.com>
* @copyright The Authors.
* @date 2016--2022.
* @date 2016--2026.
* @brief An implementation of GP trees based upon TinyGP.
* @see Poli, Langdon, and McPhee (2008) "A Field Guide to Genetic Programming"
*/
Expand All @@ -26,20 +26,20 @@
#include "sam.h"
#include "utils.h"

#define GP_NUM_FUNC (4) //!< Number of selectable GP functions
#define ADD (0) //!< Addition function
#define SUB (1) //!< Subtraction function
#define MUL (2) //!< Multiplication function
#define DIV (3) //!< Division function
#define GP_NUM_FUNC 4 //!< Number of selectable GP functions
#define ADD 0 //!< Addition function
#define SUB 1 //!< Subtraction function
#define MUL 2 //!< Multiplication function
#define DIV 3 //!< Division function

#define STRING_ADD ("+\0") //!< Addition
#define STRING_SUB ("-\0") //!< Subtraction
#define STRING_MUL ("*\0") //!< Multiplication
#define STRING_DIV ("/\0") //!< Division
#define STRING_ADD "+\0" //!< Addition
#define STRING_SUB "-\0" //!< Subtraction
#define STRING_MUL "*\0" //!< Multiplication
#define STRING_DIV "/\0" //!< Division

#define N_MU (1) //!< Number of tree-GP mutation rates
#define RET_MIN (-1000) //!< Minimum tree return value
#define RET_MAX (1000) //!< Maximum tree return value
#define N_MU 1 //!< Number of tree-GP mutation rates
#define RET_MIN -1000 //!< Minimum tree return value
#define RET_MAX 1000 //!< Maximum tree return value

/**
* @brief Self-adaptation method for mutating GP trees.
Expand Down Expand Up @@ -313,9 +313,11 @@ tree_copy(struct GPTree *dest, const struct GPTree *src)
* @brief Performs sub-tree crossover.
* @param [in] p1 The first GP tree to perform crossover.
* @param [in] p2 The second GP tree to perform crossover.
* @param [in] args Tree GP parameters.
*/
void
tree_crossover(struct GPTree *p1, struct GPTree *p2)
bool
tree_crossover(struct GPTree *p1, struct GPTree *p2,
const struct ArgsGPTree *args)
{
const int len1 = p1->len;
const int len2 = p2->len;
Expand All @@ -324,12 +326,17 @@ tree_crossover(struct GPTree *p1, struct GPTree *p2)
const int start2 = rand_uniform_int(0, len2);
const int end2 = tree_traverse(p2->tree, start2);
const int nlen1 = start1 + (end2 - start2) + (len1 - end1);
const int nlen2 = start2 + (end1 - start1) + (len2 - end2);

if (nlen1 > args->max_len || nlen2 > args->max_len) {
return false;
}

int *new1 = malloc(sizeof(int) * nlen1);
memcpy(&new1[0], &p1->tree[0], sizeof(int) * start1);
memcpy(&new1[start1], &p2->tree[start2], sizeof(int) * (end2 - start2));
memcpy(&new1[start1 + (end2 - start2)], &p1->tree[end1],
sizeof(int) * (len1 - end1));
const int nlen2 = start2 + (end1 - start1) + (len2 - end2);
int *new2 = malloc(sizeof(int) * nlen2);
memcpy(&new2[0], &p2->tree[0], sizeof(int) * start2);
memcpy(&new2[start2], &p1->tree[start1], sizeof(int) * (end1 - start1));
Expand All @@ -341,6 +348,7 @@ tree_crossover(struct GPTree *p1, struct GPTree *p2)
p2->tree = new2;
p1->len = tree_traverse(p1->tree, 0);
p2->len = tree_traverse(p2->tree, 0);
return true;
}

/**
Expand Down
9 changes: 5 additions & 4 deletions xcsf/gp.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* @file gp.h
* @author Richard Preen <rpreen@gmail.com>
* @copyright The Authors.
* @date 2016--2022.
* @date 2016--2026.
* @brief An implementation of GP trees based upon TinyGP.
*/

Expand All @@ -34,7 +34,7 @@ struct ArgsGPTree {
int n_inputs; //!< Number of inputs
int n_constants; //!< Number of constants available
int init_depth; //!< Initial depth
int max_len; //!< Maximum initial length
int max_len; //!< Maximum length
double *constants; //!< Constants available for GP trees
};

Expand Down Expand Up @@ -70,8 +70,9 @@ tree_json_import(struct GPTree *gp, const struct ArgsGPTree *args,
double
tree_eval(struct GPTree *gp, const struct ArgsGPTree *args, const double *x);

void
tree_crossover(struct GPTree *p1, struct GPTree *p2);
bool
tree_crossover(struct GPTree *p1, struct GPTree *p2,
const struct ArgsGPTree *args);

bool
tree_mutate(struct GPTree *gp, const struct ArgsGPTree *args);
Expand Down
Loading