silly functions

main
Brett 2024-11-08 19:22:55 -05:00
parent a69e3274dc
commit 3b13e48f36
6 changed files with 127 additions and 24 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25) cmake_minimum_required(VERSION 3.25)
project(COSC-4P80-Assignment-3 VERSION 0.0.8) project(COSC-4P80-Assignment-3 VERSION 0.0.9)
include(FetchContent) include(FetchContent)
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF) option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)

View File

@ -20,6 +20,7 @@
#define COSC_4P80_ASSIGNMENT_3_FUNCTIONS_H #define COSC_4P80_ASSIGNMENT_3_FUNCTIONS_H
#include <assign3/fwdecl.h> #include <assign3/fwdecl.h>
#include <blt/std/ranges.h>
namespace assign3 namespace assign3
{ {
@ -39,6 +40,16 @@ namespace assign3
[[nodiscard]] Scalar call(Scalar dist, Scalar r) const final; [[nodiscard]] Scalar call(Scalar dist, Scalar r) const final;
}; };
struct distance_function_t
{
[[nodiscard]] virtual Scalar distance(blt::span<const Scalar> x, blt::span<const Scalar> y) const = 0;
};
struct euclidean_distance_function_t : public distance_function_t
{
[[nodiscard]] Scalar distance(blt::span<const Scalar> x, blt::span<const Scalar> y) const final;
};
} }
#endif //COSC_4P80_ASSIGNMENT_3_FUNCTIONS_H #endif //COSC_4P80_ASSIGNMENT_3_FUNCTIONS_H

26
include/assign3/ui.h Normal file
View File

@ -0,0 +1,26 @@
#pragma once
/*
* Copyright (C) 2024 Brett Terpstra
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef COSC_4P80_ASSIGNMENT_3_UI_H
#define COSC_4P80_ASSIGNMENT_3_UI_H
namespace assign3 {
}
#endif //COSC_4P80_ASSIGNMENT_3_UI_H

View File

@ -17,6 +17,7 @@
*/ */
#include <assign3/functions.h> #include <assign3/functions.h>
#include <cmath> #include <cmath>
#include "blt/iterator/zip.h"
namespace assign3 namespace assign3
{ {
@ -26,4 +27,15 @@ namespace assign3
auto dist_sq = dist * dist; auto dist_sq = dist * dist;
return std::exp(-r * dist_sq); return std::exp(-r * dist_sq);
} }
Scalar euclidean_distance_function_t::distance(blt::span<const Scalar> x, blt::span<const Scalar> y) const
{
Scalar dist = 0;
for (auto [a, b] : blt::in_pairs(x, y))
{
auto d = a - b;
dist += d * d;
}
return std::sqrt(dist);
}
} }

View File

@ -21,9 +21,26 @@ blt::gfx::first_person_camera_2d camera;
blt::size_t som_width = 7; blt::size_t som_width = 7;
blt::size_t som_height = 7; blt::size_t som_height = 7;
blt::size_t max_epochs = 100; blt::size_t max_epochs = 1000;
Scalar initial_learn_rate = 0.1; Scalar initial_learn_rate = 0.1;
int currently_selected_network = 0;
std::vector<std::string> map_files_names;
float neuron_scale = 35;
float draw_width = neuron_scale * static_cast<float>(som_width);
float draw_height = neuron_scale * static_cast<float>(som_height);
void generate_network(int selection)
{
som = std::make_unique<som_t>(files[selection].normalize(), som_width, som_height, max_epochs);
}
const char* get_selection_string(void*, int selection)
{
return map_files_names[selection].c_str();
}
void init(const blt::gfx::window_data&) void init(const blt::gfx::window_data&)
{ {
using namespace blt::gfx; using namespace blt::gfx;
@ -33,15 +50,16 @@ void init(const blt::gfx::window_data&)
resources.load_resources(); resources.load_resources();
renderer_2d.create(); renderer_2d.create();
som = std::make_unique<som_t>( for (const auto& data : files)
*std::find_if(files.begin(), files.end(), [](const data_file_t& v) { return v.data_points.begin()->bins.size() == 32; }), map_files_names.emplace_back(std::to_string(data.data_points.begin()->bins.size()));
som_width, som_height, max_epochs);
generate_network(currently_selected_network);
} }
void update(const blt::gfx::window_data& data) void update(const blt::gfx::window_data& window_data)
{ {
using namespace blt::gfx; using namespace blt::gfx;
global_matrices.update_perspectives(data.width, data.height, 90, 0.1, 2000); global_matrices.update_perspectives(window_data.width, window_data.height, 90, 0.1, 2000);
camera.update(); camera.update();
camera.update_view(global_matrices); camera.update_view(global_matrices);
@ -49,6 +67,10 @@ void update(const blt::gfx::window_data& data)
if (ImGui::Begin("Controls")) if (ImGui::Begin("Controls"))
{ {
ImGui::Text("Network Select");
if (ImGui::ListBox("##Network Select", &currently_selected_network, get_selection_string, nullptr, static_cast<int>(map_files_names.size())))
generate_network(currently_selected_network);
if (ImGui::Button("Run Epoch")) if (ImGui::Button("Run Epoch"))
{ {
static gaussian_function_t func; static gaussian_function_t func;
@ -71,8 +93,8 @@ void update(const blt::gfx::window_data& data)
activations.clear(); activations.clear();
activations.resize(som->get_array().get_map().size()); activations.resize(som->get_array().get_map().size());
auto& meow = *std::find_if(files.begin(), files.end(), [](const data_file_t& v) { return v.data_points.begin()->bins.size() == 32; }); auto current_data_file = files[currently_selected_network].normalize();
for (auto& v : meow.data_points) for (auto& v : current_data_file.data_points)
{ {
auto nearest = som->get_closest_neuron(v.bins); auto nearest = som->get_closest_neuron(v.bins);
activations[nearest] += v.is_bad ? -1 : 1; activations[nearest] += v.is_bad ? -1 : 1;
@ -83,8 +105,6 @@ void update(const blt::gfx::window_data& data)
for (auto [i, v] : blt::enumerate(som->get_array().get_map())) for (auto [i, v] : blt::enumerate(som->get_array().get_map()))
{ {
float scale = 35;
auto activation = activations[i]; auto activation = activations[i];
blt::vec4 color = blt::make_color(1, 1, 1); blt::vec4 color = blt::make_color(1, 1, 1);
@ -93,10 +113,50 @@ void update(const blt::gfx::window_data& data)
else if (activation < 0) else if (activation < 0)
color = blt::make_color(std::abs(static_cast<Scalar>(activation) / static_cast<Scalar>(min)), 0, 0); color = blt::make_color(std::abs(static_cast<Scalar>(activation) / static_cast<Scalar>(min)), 0, 0);
renderer_2d.drawPointInternal(color, point2d_t{v.get_x() * scale + scale, v.get_y() * scale + scale, scale}); renderer_2d.drawPointInternal(color,
point2d_t{v.get_x() * neuron_scale + neuron_scale, v.get_y() * neuron_scale + neuron_scale, neuron_scale});
} }
renderer_2d.render(data.width, data.height); static std::vector<float> closest_type;
closest_type.clear();
closest_type.resize(som->get_array().get_map().size());
for (auto [i, v] : blt::enumerate(som->get_array().get_map()))
{
Scalar lowest_distance = std::numeric_limits<Scalar>::max();
bool is_bad = false;
for (const auto& data : current_data_file.data_points)
{
auto dist = v.dist(data.bins);
if (dist < lowest_distance)
{
lowest_distance = dist;
is_bad = data.is_bad;
}
}
// BLT_TRACE(is_bad ? -lowest_distance : lowest_distance);
closest_type[i] = is_bad ? -lowest_distance : lowest_distance;
}
auto min_dist = *std::min_element(closest_type.begin(), closest_type.end());
auto max_dist = *std::max_element(closest_type.begin(), closest_type.end());
for (auto [i, v] : blt::enumerate(som->get_array().get_map()))
{
auto type = closest_type[i];
blt::vec4 color = blt::make_color(1, 1, 1);
if (type >= 0)
color = blt::make_color(0, 1 - (type / max_dist) + 0.1f, 0);
else if (type < 0)
color = blt::make_color(1 - (type / min_dist) + 0.1f, 0, 0);
renderer_2d.drawPointInternal(color,
point2d_t{draw_width + neuron_scale * 2 + v.get_x() * neuron_scale + neuron_scale,
v.get_y() * neuron_scale + neuron_scale, neuron_scale});
}
renderer_2d.render(window_data.width, window_data.height);
} }
void destroy(const blt::gfx::window_data&) void destroy(const blt::gfx::window_data&)

View File

@ -49,19 +49,13 @@ namespace assign3
Scalar neuron_t::dist(const std::vector<Scalar>& X) const Scalar neuron_t::dist(const std::vector<Scalar>& X) const
{ {
Scalar dist = 0; euclidean_distance_function_t dist_func;
for (auto [v, x] : blt::zip(data, X)) return dist_func.distance(data, X);
{
auto loc = (v - x);
dist += loc * loc;
}
return std::sqrt(dist);
} }
Scalar neuron_t::distance(const neuron_t& n1, const neuron_t& n2) Scalar neuron_t::distance(const neuron_t& n1, const neuron_t& n2)
{ {
auto dx = n1.get_x() - n2.get_x(); euclidean_distance_function_t dist_func;
auto dy = n1.get_y() - n2.get_y(); return dist_func.distance({n1.get_x(), n1.get_y()}, {n2.get_x(), n2.get_y()});
return std::sqrt(dx * dx + dy * dy);
} }
} }