Skip to content

File generator_rlitt.c

File List > gen-rlitt > src > generator_rlitt.c

Go to the documentation of this file

#include "generator_rlitt.h"
#include "bits/stdint-uintn.h"
#include "comp_rlitt_grafting.h"
#include "comp_wptt_vertex_canonicity.h"
#include "comp_rlitt_positivity.h"
#include "mut_rlitt_ringshift.h"
#include "computation_defs.h"
#include "generator_defs.h"
#include "notation_wptt.h"
#include "stdbool.h"
#include "stdlib.h"

/******************************************************************************/
/************************** Defines *******************************************/
/******************************************************************************/

/******************************************************************************/
/************************** Private Function Declarations *********************/
/******************************************************************************/
STATIC_INLINE const char *gen_rlitt_get_posstr(comp_rlitt_positivity_flvrs_e positivity);
STATIC_INLINE_UINT8 gen_rlitt_store_tangle(const note_wptt_t *result,
                                           const note_wptt_t *rootstock,
                                           const note_wptt_t *scion,
                                           const char *positivity);
STATIC_INLINE bool gen_rlitt_root_canon(const note_wptt_node_t *root,
                                        comp_wptt_vert_canon_positivity_e positivity);
STATIC_INLINE_UINT8 gen_rlitt_grafting_handler(size_t rootstock_idx, size_t scion_idx);

/******************************************************************************/
/************************** Local Variables ***********************************/
/******************************************************************************/

static gen_rlitt_config_t *gen_rlitt_localcfg = NULL;

static bool gen_rlitt_executed = false;

/******************************************************************************/
/************************** Public Function Definitions ***********************/
/******************************************************************************/

/*
 *  Documentation in header
 */
uint8_t gen_rlitt_config(gen_rlitt_config_t *config_arg)
{
    uint8_t ret_val = GEN_DEFS_CONFIG_FAIL;

    gen_rlitt_localcfg = NULL;

    /*Ensure the cfg is not empty.*/
    if (config_arg == NULL)
    {
        ret_val |= GEN_RLITT_CONFIG_IS_NULL;
    }
    /*Ensure the rootstock is not empty.*/
    else if ((config_arg->rootstocks == NULL) ||
             (config_arg->rootstocks_len == 0))
    {
        ret_val |= GEN_RLITT_CONFIG_ROOTSTOCKS_ERROR;
    }
    /*Ensure the scion is not empty.*/
    else if ((config_arg->scions == NULL) ||
             (config_arg->scions_len == 0))
    {
        ret_val |= GEN_RLITT_CONFIG_SCIONS_ERROR;
    }
    else
    {
        /* Set the config. */
        gen_rlitt_localcfg = config_arg;

        /*clear the executed status*/
        gen_rlitt_executed = false;

        ret_val = COMP_DEFS_CONFIG_SUCCESS;
    }
    return ret_val;
}

/*
 *  Documentation in header
 */
uint8_t gen_rlitt_generate()
{
    uint8_t ret_val = COMP_DEFS_COMPUTE_FAIL;

    /*Ensure the cfg is not empty.*/
    if (gen_rlitt_localcfg == NULL)
    {
        ret_val |= GEN_RLITT_GENERATE_CFG_ERROR;
    }
    /*Ensure not executed.*/
    else if (gen_rlitt_executed != false)
    {
        ret_val |= GEN_RLITT_GENERATE_ALREADY_COMPUTED;
    }
    else
    {
        gen_rlitt_executed = true;
        ret_val            = GEN_DEFS_GENERATION_SUCCESS;
        size_t i;
        /* for each rootstock */
        for (i = 0; i < gen_rlitt_localcfg->rootstocks_len; i++)
        {
            if (GEN_DEFS_GENERATION_SUCCESS == ret_val)
            {
                size_t j;
                /* for each scion */
                for (j = 0; j < gen_rlitt_localcfg->scions_len; j++)
                {
                    /* Run the grafting process */
                    ret_val |= gen_rlitt_grafting_handler(i, j);
                }
            }
            else
            {
                break;
            }
        }
    }

    return ret_val;
}

/******************************************************************************/
/************************** Private Function Definitions **********************/
/******************************************************************************/

STATIC_INLINE_UINT8 gen_rlitt_grafting_handler(size_t rootstock_idx, size_t scion_idx)
{
    uint8_t ret_val      = GEN_DEFS_GENERATION_SUCCESS;
    uint8_t compute_flag = COMP_DEFS_COMPUTE_SUCCESS;

/* clang-format off */
    note_wptt_node_t note_wptt_node[2 * UTIL_TANG_DEFS_MAX_CROSSINGNUM] = {{ {NULL},
                                                                             {0},
                                                                             0,
                                                                             0,
                                                                             NOTE_WPTT_ORDER_UNINIT 
                                                                           }};
/* clang-format on */
    note_wptt_node_buffer_t             buffer = { note_wptt_node,
                                                   2u * UTIL_TANG_DEFS_MAX_CROSSINGNUM, 0 };
    note_wptt_t                         output_wptt = { NULL, &buffer, NOTE_WPTT_V4_LABEL_I };
    comp_rlitt_grafting_config_t        graft_cfg   = { NULL,
                                                        gen_rlitt_localcfg->rootstocks[rootstock_idx],
                                                        gen_rlitt_localcfg->scions[scion_idx],
                                                        0,
                                                        &output_wptt };
    const comp_rlitt_grafting_result_t *graft_res = NULL;

    /* Compute the grafting operation. */
    compute_flag |= comp_rlitt_grafting_config(&graft_cfg);
    compute_flag |= comp_rlitt_grafting_compute();
    graft_res     = comp_rlitt_grafting_result();

    /* Ensure grafting was successful. */
    if ((COMP_DEFS_COMPUTE_SUCCESS == compute_flag) &&
        (NULL != graft_res))
    {
        note_wptt_t *shifted_wptt;
        mut_rlitt_ringshift_config_t shift_cfg;
        shift_cfg.wptt = graft_res->grafted_wptt;

        /* Compute the right leaning version of the grafted tree. */
        compute_flag |= mut_rlitt_ringshift_config(&shift_cfg);
        compute_flag |= mut_rlitt_ringshift_mutate();
        shifted_wptt  = graft_res->grafted_wptt;

        /* Ensure rings shift was successful. */
        if ((COMP_DEFS_COMPUTE_SUCCESS == compute_flag) &&
            (NULL != shifted_wptt))
        {
            /* Check if the root is plus or minus canonical. */
            if ((true == gen_rlitt_root_canon((const note_wptt_node_t * )shifted_wptt->root,
                                              COMP_WPTT_VERT_CANON_POS_POS)) ||
                (true == gen_rlitt_root_canon((const note_wptt_node_t * )shifted_wptt->root,
                                              COMP_WPTT_VERT_CANON_POS_NEG)))
            {
                comp_rlitt_positivity_config_t        positivity_cfg;
                const comp_rlitt_positivity_result_t *positivity_res = NULL;

                positivity_cfg.storage_write = NULL;
                positivity_cfg.wptt          = shifted_wptt;

                /* Compute the positivity of the grafted and shifted tree. */
                compute_flag  |= comp_rlitt_positivity_config(&positivity_cfg);
                compute_flag  |= comp_rlitt_positivity_compute();
                positivity_res = comp_rlitt_positivity_result();

                /* Verify the positivity is defined.*/
                if ((COMP_DEFS_COMPUTE_SUCCESS == compute_flag) &&
                    (NULL != positivity_res) &&
                    (COMP_RLITT_POSITIVITY_FLVR_UND != positivity_res->positivity) &&
                    (COMP_RLITT_POSITIVITY_FLVR_UNINIT != positivity_res->positivity))
                {
                    /* Store the grafted tangle. */
                    ret_val |= gen_rlitt_store_tangle(shifted_wptt,
                                                      gen_rlitt_localcfg->rootstocks[rootstock_idx],
                                                      gen_rlitt_localcfg->scions[scion_idx],
                                                      gen_rlitt_get_posstr(
                                                          positivity_res->positivity));
/* clang-format off */
                    /* If the tree rootstock is a stick at the root we need to invert the sign of 
                     * the root vertex and store the result.
                     */
                    if (1 == gen_rlitt_localcfg->rootstocks[rootstock_idx]->root->number_of_children) 
/* clang-format on */
                    {
                        uint8_t number_of_children = shifted_wptt->root->number_of_children;
                        shifted_wptt->root->weights[number_of_children] *= -1;
                        ret_val |= gen_rlitt_store_tangle(shifted_wptt,
                                                          gen_rlitt_localcfg->rootstocks[
                                                              rootstock_idx],
                                                          gen_rlitt_localcfg->scions[scion_idx],
                                                          gen_rlitt_get_posstr(
                                                              positivity_res->positivity));
                    }
                }
            }
        }
        else
        {
            ret_val = GEN_STATUS_BLDR(GEN_DEFS_GENERATION_FAIL, GEN_RLITT_GENERATE_NEUTRALITY);
        }
    }
    else
    {
        ret_val = GEN_STATUS_BLDR(GEN_DEFS_GENERATION_FAIL, GEN_RLITT_GENERATE_GRAFTING);
    }

    return ret_val;
}

STATIC_INLINE const char *gen_rlitt_get_posstr(comp_rlitt_positivity_flvrs_e positivity)
{
    switch (positivity)
    {
    case COMP_RLITT_POSITIVITY_FLVR_UND:
        return "undefined";

    case COMP_RLITT_POSITIVITY_FLVR_POS:
        return "positive";

    case COMP_RLITT_POSITIVITY_FLVR_NEG:
        return "negative";

    case COMP_RLITT_POSITIVITY_FLVR_NEU:
        return "neutral";

    default:
        break;
    }
    return NULL;
}

STATIC_INLINE_UINT8 gen_rlitt_store_tangle(const note_wptt_t *result,
                                           const note_wptt_t *rootstock,
                                           const note_wptt_t *scion,
                                           const char *positivity)
{
    uint8_t ret_val = GEN_RLITT_GENERATE_PRINT_ERROR;

    uint8_t encode_ret = NOTE_DEFS_ENCODE_SUCCESS;
    char    result_str[NOTE_WPTT_MAX_STR_LEN]    = { '\0' };
    char    rootstock_str[NOTE_WPTT_MAX_STR_LEN] = { '\0' };
    char    scion_str[NOTE_WPTT_MAX_STR_LEN]     = { '\0' };

    /* Encode the three trees as strings.*/
    encode_ret |= note_wptt_encode(*result,
                                   result_str,
                                   NOTE_WPTT_MAX_STR_LEN);
    encode_ret |= note_wptt_encode(*rootstock,
                                   rootstock_str,
                                   NOTE_WPTT_MAX_STR_LEN);
    encode_ret |= note_wptt_encode(*scion,
                                   scion_str,
                                   NOTE_WPTT_MAX_STR_LEN);

    if (encode_ret == NOTE_DEFS_ENCODE_SUCCESS)
    {
        char *is_good_str = "true";
        /* Determine if the resulting tree is "good". */
        if ((result->root->number_of_children < 2) &&
            (result->root->weights[result->root->number_of_children] == 0))
        {
            is_good_str = "false";
        }
        /* Report the results to the write interface. */
        ret_val  = GEN_DEFS_GENERATION_SUCCESS;
        ret_val |= gen_rlitt_localcfg->storage_write(result_str, "rootstock", rootstock_str);
        ret_val |= gen_rlitt_localcfg->storage_write(result_str, "scion", scion_str);
        ret_val |= gen_rlitt_localcfg->storage_write(result_str, "positivity", positivity);
        ret_val |= gen_rlitt_localcfg->storage_write(result_str, "is_good", is_good_str);
    }
    return ret_val;
}

STATIC_INLINE bool gen_rlitt_root_canon(const note_wptt_node_t *root,
                                        comp_wptt_vert_canon_positivity_e positivity)
{
    uint8_t compute_flag = COMP_DEFS_COMPUTE_SUCCESS;
    const comp_wptt_vert_canon_result_t *canvertex_res = NULL;
    comp_wptt_vert_canon_config_t        canvertex_cfg;

    canvertex_cfg.storage_write  = NULL;
    canvertex_cfg.wptt           = NULL;
    canvertex_cfg.parent         = NULL;
    canvertex_cfg.vertex         = root;
    canvertex_cfg.positivity     = positivity;
    canvertex_cfg.parent_is_root = false;

    /* Compute the vertex canonicity of the root of the resulting tree. */
    compute_flag |= comp_wptt_vert_canon_config(&canvertex_cfg);
    compute_flag |= comp_wptt_vert_canon_compute();
    canvertex_res = comp_wptt_vert_canon_result();
    if ((COMP_DEFS_COMPUTE_SUCCESS == compute_flag) &&
        (COMP_WPTT_VERT_CANON_IS_CANONICAL == canvertex_res->is_canonical))
    {
        size_t i;
        canvertex_cfg.parent         = root;
        canvertex_cfg.parent_is_root = true;
        /* For each child of the root. */
        for (i = 0; i < root->number_of_children; i++)
        {
            canvertex_cfg.vertex = root->children[i];
            compute_flag        |= comp_wptt_vert_canon_config(&canvertex_cfg);
            compute_flag        |= comp_wptt_vert_canon_compute();
            canvertex_res        = comp_wptt_vert_canon_result();
            if ((COMP_DEFS_COMPUTE_SUCCESS == compute_flag) &&
                (COMP_WPTT_VERT_CANON_IS_CANONICAL != canvertex_res->is_canonical))
            {
                return false;
            }
        }
    }
    else
    {
        return false;
    }

    return true;
}