evil
parent
2a8e334d43
commit
a9235e9c17
|
@ -1,5 +1,5 @@
|
|||
cmake_minimum_required(VERSION 3.25)
|
||||
project(image-gp-6 VERSION 0.0.20)
|
||||
project(image-gp-6 VERSION 0.0.21)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
|
|
|
@ -19,13 +19,15 @@
|
|||
#ifndef IMAGE_GP_6_CONFIG_H
|
||||
#define IMAGE_GP_6_CONFIG_H
|
||||
|
||||
#include <custom_transformer.h>
|
||||
|
||||
inline constexpr size_t log2(size_t n) // NOLINT
|
||||
{
|
||||
return ((n < 2) ? 1 : 1 + log2(n / 2));
|
||||
}
|
||||
|
||||
//inline const blt::u64 SEED = std::random_device()();
|
||||
inline const blt::u64 SEED = 553372510;
|
||||
inline const blt::u64 SEED = std::random_device()();
|
||||
//inline const blt::u64 SEED = 553372510;
|
||||
inline constexpr blt::size_t IMAGE_SIZE = 128;
|
||||
inline constexpr blt::size_t IMAGE_PADDING = 16;
|
||||
inline constexpr blt::size_t POP_SIZE = 64;
|
||||
|
@ -35,9 +37,15 @@ inline constexpr blt::size_t DATA_CHANNELS_SIZE = DATA_SIZE * CHANNELS;
|
|||
inline constexpr blt::size_t BOX_COUNT = static_cast<blt::size_t>(log2(IMAGE_SIZE / 2));
|
||||
inline constexpr float THRESHOLD = 0.3;
|
||||
inline constexpr auto load_image = "../GSab4SWWcAA1TNR.png";
|
||||
|
||||
inline blt::gp::image_crossover_t image_crossover;
|
||||
inline blt::gp::image_mutation_t image_mutation;
|
||||
|
||||
//inline constexpr auto load_image = "../miles.png";
|
||||
|
||||
inline blt::gp::prog_config_t config = blt::gp::prog_config_t()
|
||||
.set_crossover(image_crossover)
|
||||
.set_mutation(image_mutation)
|
||||
.set_initial_min_tree_size(4)
|
||||
.set_initial_max_tree_size(8)
|
||||
.set_elite_count(2)
|
||||
|
|
|
@ -19,4 +19,80 @@
|
|||
#ifndef IMAGE_GP_6_CUSTOM_TRANSFORMER_H
|
||||
#define IMAGE_GP_6_CUSTOM_TRANSFORMER_H
|
||||
|
||||
#include <blt/gp/transformers.h>
|
||||
|
||||
namespace blt::gp
|
||||
{
|
||||
template<typename T>
|
||||
inline static constexpr double sum(const T& array)
|
||||
{
|
||||
double init = 0.0;
|
||||
for (double i : array)
|
||||
init += i;
|
||||
return init;
|
||||
}
|
||||
|
||||
template<blt::size_t size, typename... Args>
|
||||
static constexpr std::array<double, size> aggregate_array(Args... list)
|
||||
{
|
||||
std::array<double, size> data {list...};
|
||||
auto total_prob = sum(data);
|
||||
double sum_of_prob = 0;
|
||||
for (auto& d : data) {
|
||||
auto prob = d / total_prob;
|
||||
d = prob + sum_of_prob;
|
||||
sum_of_prob += prob;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
class image_crossover_t : public crossover_t
|
||||
{
|
||||
public:
|
||||
image_crossover_t() = default;
|
||||
|
||||
explicit image_crossover_t(const config_t& config): crossover_t(config)
|
||||
{}
|
||||
|
||||
blt::expected<result_t, error_t> apply(gp_program& program, const tree_t& p1, const tree_t& p2) final;
|
||||
};
|
||||
|
||||
class image_mutation_t : public mutation_t
|
||||
{
|
||||
public:
|
||||
enum class mutation_operator : blt::i32
|
||||
{
|
||||
EXPRESSION, // Generate a new random expression
|
||||
ADJUST, // adjust the value of the type.
|
||||
FUNC, // Change node into a different function. Args will be generated / removed.
|
||||
SUB_FUNC, // subexpression becomes argument to new random function. Other args are generated.
|
||||
JUMP_FUNC, // subexpression becomes this new node. Other arguments discarded.
|
||||
COPY, // node can become copy of another subexpression.
|
||||
END, // helper
|
||||
};
|
||||
|
||||
image_mutation_t() = default;
|
||||
|
||||
explicit image_mutation_t(const config_t& config): mutation_t(config)
|
||||
{}
|
||||
|
||||
tree_t apply(gp_program& program, const tree_t& p) final;
|
||||
|
||||
private:
|
||||
static constexpr auto operators_size = static_cast<blt::i32>(mutation_operator::END);
|
||||
private:
|
||||
// this value is adjusted inversely to the size of the tree.
|
||||
double per_node_mutation_chance = 1.0;
|
||||
|
||||
static constexpr std::array<double, operators_size> mutation_operator_chances = aggregate_array<operators_size>(
|
||||
0.01, // EXPRESSION
|
||||
0.11, // ADJUST
|
||||
0.05, // FUNC
|
||||
0.01, // SUB_FUNC
|
||||
0.1, // JUMP_FUNC
|
||||
0.05 // COPY
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
#endif //IMAGE_GP_6_CUSTOM_TRANSFORMER_H
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#define IMAGE_GP_6_HELPER_H
|
||||
|
||||
#include <images.h>
|
||||
#include <stb_perlin.h>
|
||||
|
||||
template<typename SINGLE_FUNC>
|
||||
constexpr static auto make_single(SINGLE_FUNC&& func)
|
||||
|
|
|
@ -16,9 +16,11 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <blt/math/vectors.h>
|
||||
#include <blt/gp/program.h>
|
||||
#include <functional>
|
||||
#include <helper.h>
|
||||
#include <stb_perlin.h>
|
||||
|
||||
#ifndef IMAGE_GP_6_IMAGE_OPERATIONS_H
|
||||
#define IMAGE_GP_6_IMAGE_OPERATIONS_H
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
#define IMAGE_GP_6_IMAGES_H
|
||||
|
||||
#include <config.h>
|
||||
#include <stb_image.h>
|
||||
#include <stb_image_resize2.h>
|
||||
#include <stb_image_write.h>
|
||||
|
||||
struct full_image_t
|
||||
{
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 593e02b6ffd36cfabda85e9dcfd88ec60b8a8741
|
||||
Subproject commit b10b4388897b1673b0dbe84b1db34584db0e9660
|
|
@ -15,4 +15,132 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <custom_transformer.h>
|
||||
#include <custom_transformer.h>
|
||||
#include <blt/gp/program.h>
|
||||
#include <images.h>
|
||||
#include <image_operations.h>
|
||||
#include <float_operations.h>
|
||||
|
||||
namespace blt::gp
|
||||
{
|
||||
|
||||
blt::expected<crossover_t::result_t, crossover_t::error_t> image_crossover_t::apply(gp_program& program, const tree_t& p1, const tree_t& p2)
|
||||
{
|
||||
return crossover_t::apply(program, p1, p2);
|
||||
}
|
||||
|
||||
|
||||
tree_t image_mutation_t::apply(gp_program& program, const tree_t& p)
|
||||
{
|
||||
// child tree
|
||||
tree_t c = p;
|
||||
|
||||
auto& ops = c.get_operations();
|
||||
auto& vals = c.get_values();
|
||||
|
||||
double node_mutation_chance = per_node_mutation_chance * (1.0 / static_cast<double>(ops.size()));
|
||||
|
||||
for (blt::size_t c_node = 0; c_node < ops.size(); c_node++)
|
||||
{
|
||||
if (!program.get_random().choice(node_mutation_chance))
|
||||
continue;
|
||||
auto selected_point = static_cast<blt::i32>(mutation_operator::COPY);
|
||||
auto choice = program.get_random().get_double();
|
||||
|
||||
for (const auto& [index, value] : blt::enumerate(mutation_operator_chances))
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
if (choice <= value)
|
||||
{
|
||||
selected_point = static_cast<blt::i32>(index);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (choice > mutation_operator_chances[index - 1] && choice <= value)
|
||||
{
|
||||
selected_point = static_cast<blt::i32>(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (static_cast<mutation_operator>(selected_point))
|
||||
{
|
||||
case mutation_operator::EXPRESSION:
|
||||
c_node += mutate_point(program, c, c_node);
|
||||
break;
|
||||
case mutation_operator::ADJUST:
|
||||
{
|
||||
// this is going to be evil >:3
|
||||
const auto& node = ops[c_node];
|
||||
if (node.is_value)
|
||||
{
|
||||
blt::size_t bytes_from_head = 0;
|
||||
for (auto it = ops.begin() + static_cast<blt::ptrdiff_t>(c_node) + 1; it != ops.end(); it++)
|
||||
bytes_from_head += it->is_value ? stack_allocator::aligned_size(it->type_size) : 0;
|
||||
// is a float
|
||||
if (node.type_size == sizeof(float))
|
||||
{
|
||||
auto& val = vals.from<float>(bytes_from_head);
|
||||
auto old = val;
|
||||
val += f_literal.get_function()();
|
||||
val /= 2.0f;
|
||||
if (std::isnan(val))
|
||||
val = old;
|
||||
} else // is an image
|
||||
{
|
||||
auto& val = vals.from<full_image_t>(bytes_from_head);
|
||||
auto type = program.get_typesystem().get_type<full_image_t>();
|
||||
auto& terminals = program.get_type_terminals(type.id());
|
||||
|
||||
// Annoying. TODO: fix all of this.
|
||||
operator_id id;
|
||||
do{
|
||||
id = program.get_random().select(terminals);
|
||||
} while(!program.is_static(id));
|
||||
|
||||
stack_allocator stack;
|
||||
|
||||
program.get_operator_info(id).function(nullptr, stack, stack);
|
||||
|
||||
//auto adjustment = lit.get_function()();
|
||||
auto& adjustment = stack.from<full_image_t>(0);
|
||||
|
||||
for (const auto& [index, value] : blt::enumerate(val.rgb_data))
|
||||
{
|
||||
auto old = value;
|
||||
// add and normalize.
|
||||
value += adjustment.rgb_data[index];
|
||||
value /= 2.0f;
|
||||
if (std::isnan(value))
|
||||
value = old;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case mutation_operator::FUNC:
|
||||
break;
|
||||
case mutation_operator::SUB_FUNC:
|
||||
break;
|
||||
case mutation_operator::JUMP_FUNC:
|
||||
break;
|
||||
case mutation_operator::COPY:
|
||||
break;
|
||||
case mutation_operator::END:
|
||||
default:
|
||||
#if BLT_DEBUG_LEVEL > 1
|
||||
BLT_ABORT("You shouldn't be able to get here!");
|
||||
#else
|
||||
BLT_UNREACHABLE;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -22,10 +22,6 @@
|
|||
#include <blt/std/memory_util.h>
|
||||
#include <blt/std/hashmap.h>
|
||||
#include <blt/std/time.h>
|
||||
#include <stb_image.h>
|
||||
#include <stb_image_resize2.h>
|
||||
#include <stb_image_write.h>
|
||||
#include <stb_perlin.h>
|
||||
#include <blt/gfx/window.h>
|
||||
#include "blt/gfx/renderer/resource_manager.h"
|
||||
#include "blt/gfx/renderer/batch_2d_renderer.h"
|
||||
|
|
Loading…
Reference in New Issue