saving neurons

main
Brett 2024-11-15 17:08:54 -05:00
parent 88e28c05b5
commit 7179be26e3
8 changed files with 198 additions and 370 deletions

View File

@ -1,229 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AnalysisUIOptions">
<option name="ANALYZE_INJECTED_CODE" value="false" />
<option name="SCOPE_TYPE" value="3" />
</component>
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="BackendCodeEditorMiscSettings">
<option name="/Default/RiderDebugger/RiderRestoreDecompile/RestoreDecompileSetting/@EntryValue" value="false" type="bool" />
<option name="/Default/Housekeeping/GlobalSettingsUpgraded/IsUpgraded/@EntryValue" value="true" type="bool" />
<option name="/Default/Housekeeping/FeatureSuggestion/FeatureSuggestionManager/DisabledSuggesters/=SwitchToGoToActionSuggester/@EntryIndexedValue" value="true" type="bool" />
<option name="/Default/Housekeeping/FeatureSuggestion/FeatureSuggestionManager/DisabledSuggesters/=SwitchToGoToActionSuggester/@EntryIndexRemoved" />
<option name="/Default/Environment/Hierarchy/GeneratedFilesCacheKey/Timestamp/@EntryValue" value="14" type="long" />
<option name="/Default/Housekeeping/OptionsDialog/SelectedPageId/@EntryValue" value="CppFormatterOtherPage" type="string" />
</component>
<component name="CMakePresetLoader">{
&quot;useNewFormat&quot;: true
}</component>
<component name="CMakeProjectFlavorService">
<option name="flavorId" value="CMakePlainProjectFlavor" />
</component>
<component name="CMakeReloadState">
<option name="reloaded" value="true" />
</component>
<component name="CMakeRunConfigurationManager">
<generated>
<config projectName="COSC-4P80-Assignment-3" targetName="BLT_WITH_GRAPHICS" />
<config projectName="COSC-4P80-Assignment-3" targetName="freetype" />
<config projectName="COSC-4P80-Assignment-3" targetName="BLT" />
<config projectName="COSC-4P80-Assignment-3" targetName="COSC-4P80-Assignment-3" />
</generated>
</component>
<component name="CMakeSettings">
<configurations>
<configuration PROFILE_NAME="Debug" ENABLED="true" CONFIG_NAME="Debug" />
<configuration PROFILE_NAME="Release" ENABLED="true" CONFIG_NAME="Release" />
<configuration PROFILE_NAME="RelWithDebInfo" ENABLED="true" CONFIG_NAME="RelWithDebInfo" />
<configuration PROFILE_NAME="RelWithDebInfo Addrsan" ENABLED="true" CONFIG_NAME="RelWithDebInfo" GENERATION_OPTIONS="-DENABLE_ADDRSAN=ON -DENABLE_UBSAN=ON" />
<configuration PROFILE_NAME="RelWithDebInfo ubsan" ENABLED="true" CONFIG_NAME="RelWithDebInfo" GENERATION_OPTIONS="-DENABLE_UBSAN=ON" />
<configuration PROFILE_NAME="Debug Addrsan" ENABLED="true" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DENABLE_ADDRSAN=ON" />
</configurations>
</component>
<component name="ChangeListManager">
<list default="true" id="df4fb81f-8c9e-43af-9712-6ff8baeb587a" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/.idea/codeStyles/codeStyleConfig.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/editor.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/include/blt/gfx/renderer/font_renderer.h" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/include/blt/gfx/renderer/font_renderer.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/cloc.sh" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/cloc.sh" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/commit.py.save" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/commit.py.save" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/py_commit_helper.sh" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/py_commit_helper.sh" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/src/blt/gfx/renderer/font_renderer.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/src/blt/gfx/renderer/font_renderer.cpp" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/src/main.cpp" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ClangdSettings">
<option name="formatViaClangd" value="false" />
<option name="indexerUseModules" value="false" />
</component>
<component name="ExecutionTargetManager" SELECTED_TARGET="CMakeBuildProfile:RelWithDebInfo" />
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="HighlightingSettingsPerFile">
<setting file="file://$PROJECT_DIR$/include/assign3/array.h" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/include/assign3/file.h" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/include/assign3/functions.h" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/include/assign3/neuron.h" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/include/assign3/som.h" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/include/assign3/ui.h" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/lib/blt-with-graphics/include/blt/gfx/font/font_awesome_defines.h" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/lib/blt-with-graphics/include/blt/gfx/renderer/font_renderer.h" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/include/blt/std/ranges.h" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/src/array.cpp" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/src/file.cpp" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/src/functions.cpp" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/src/main.cpp" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/src/neuron.cpp" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/src/som.cpp" root0="FORCE_HIGHLIGHTING" />
</component>
<component name="ProblemsViewState">
<option name="selectedTabId" value="CurrentFile" />
</component>
<component name="ProjectApplicationVersion">
<option name="ide" value="CLion" />
<option name="majorVersion" value="2024" />
<option name="minorVersion" value="1.3" />
<option name="productBranch" value="Classic" />
</component>
<component name="ProjectColorInfo">{
&quot;associatedIndex&quot;: 7
}</component>
<component name="ProjectId" id="2oG5NNX4GedKhxLJDuzQ5OR5kr5" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;CMake Application.COSC-4P80-Assignment-3.executor&quot;: &quot;Run&quot;,
&quot;NIXITCH_NIXPKGS_CONFIG&quot;: &quot;/etc/nix/nixpkgs-config.nix&quot;,
&quot;NIXITCH_NIX_CONF_DIR&quot;: &quot;&quot;,
&quot;NIXITCH_NIX_OTHER_STORES&quot;: &quot;&quot;,
&quot;NIXITCH_NIX_PATH&quot;: &quot;/home/brett/.nix-defexpr/channels:nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos:nixos-config=/etc/nixos/configuration.nix:/nix/var/nix/profiles/per-user/root/channels&quot;,
&quot;NIXITCH_NIX_PROFILES&quot;: &quot;/run/current-system/sw /nix/var/nix/profiles/default /etc/profiles/per-user/brett /home/brett/.local/state/nix/profile /nix/profile /home/brett/.nix-profile&quot;,
&quot;NIXITCH_NIX_REMOTE&quot;: &quot;&quot;,
&quot;NIXITCH_NIX_USER_PROFILE_DIR&quot;: &quot;/nix/var/nix/profiles/per-user/brett&quot;,
&quot;RunOnceActivity.RadMigrateCodeStyle&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.cidr.known.project.marker&quot;: &quot;true&quot;,
&quot;RunOnceActivity.readMode.enableVisualFormatting&quot;: &quot;true&quot;,
&quot;SHARE_PROJECT_CONFIGURATION_FILES&quot;: &quot;true&quot;,
&quot;cf.advertisement.text.has.clang-format&quot;: &quot;true&quot;,
&quot;cf.first.check.clang-format&quot;: &quot;false&quot;,
&quot;cidr.known.project.marker&quot;: &quot;true&quot;,
&quot;git-widget-placeholder&quot;: &quot;main&quot;,
&quot;last_opened_file_path&quot;: &quot;/home/brett/Documents/Brock/CS 4P80/COSC-4P80-Assignment-3&quot;,
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
&quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
&quot;run.code.analysis.last.selected.profile&quot;: &quot;pProject Default&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;preferences.sourceCode.C/C++&quot;,
&quot;structure.view.defaults.are.configured&quot;: &quot;true&quot;,
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
}
}</component>
<component name="RecentsManager">
<key name="MoveFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/lib/blt-with-graphics/include/blt/gfx/font" />
</key>
</component>
<component name="RunManager" selected="CMake Application.COSC-4P80-Assignment-3">
<configuration name="BLT" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="COSC-4P80-Assignment-3" TARGET_NAME="BLT" CONFIG_NAME="Debug">
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
<configuration name="BLT_WITH_GRAPHICS" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="COSC-4P80-Assignment-3" TARGET_NAME="BLT_WITH_GRAPHICS" CONFIG_NAME="Debug">
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
<configuration name="COSC-4P80-Assignment-3" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="COSC-4P80-Assignment-3" TARGET_NAME="COSC-4P80-Assignment-3" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="COSC-4P80-Assignment-3" RUN_TARGET_NAME="COSC-4P80-Assignment-3">
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
<configuration default="true" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true">
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
<configuration name="freetype" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="COSC-4P80-Assignment-3" TARGET_NAME="freetype" CONFIG_NAME="Debug">
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
<configuration name="msdfgen-core" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="COSC-4P80-Assignment-3" TARGET_NAME="msdfgen-core" CONFIG_NAME="Debug">
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
<list>
<item itemvalue="CMake Application.BLT_WITH_GRAPHICS" />
<item itemvalue="CMake Application.BLT" />
<item itemvalue="CMake Application.COSC-4P80-Assignment-3" />
<item itemvalue="CMake Application.freetype" />
<item itemvalue="CMake Application.msdfgen-core" />
</list>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="df4fb81f-8c9e-43af-9712-6ff8baeb587a" name="Changes" comment="" />
<created>1730483030448</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1730483030448</updated>
<workItem from="1730483031471" duration="57000" />
<workItem from="1730483139508" duration="22719000" />
<workItem from="1730760265254" duration="6300000" />
<workItem from="1730932443628" duration="1866000" />
<workItem from="1731098529771" duration="11456000" />
<workItem from="1731298352794" duration="46000" />
<workItem from="1731298462144" duration="20154000" />
<workItem from="1731370094158" duration="776000" />
<workItem from="1731430940789" duration="18816000" />
<workItem from="1731607891598" duration="688000" />
<workItem from="1731608714255" duration="241000" />
<workItem from="1731609005148" duration="269000" />
<workItem from="1731609278663" duration="148000" />
<workItem from="1731609433368" duration="774000" />
<workItem from="1731610215063" duration="7410000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="VCPKGProject">
<isAutomaticCheckingOnLaunch value="false" />
<isAutomaticFoundErrors value="true" />
<isAutomaticReloadCMake value="true" />
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State />
</value>
</entry>
</map>
</option>
</component>
<component name="XSLT-Support.FileAssociations.UIState">
<expand />
<select />
</component>
</project>

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.15) project(COSC-4P80-Assignment-3 VERSION 0.0.16)
include(FetchContent) include(FetchContent)
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF) option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)

View File

@ -21,6 +21,7 @@
#include <assign3/fwdecl.h> #include <assign3/fwdecl.h>
#include <assign3/neuron.h> #include <assign3/neuron.h>
#include <blt/math/vectors.h>
namespace assign3 namespace assign3
{ {
@ -36,7 +37,7 @@ namespace assign3
map.emplace_back(dimensions, (j % 2 == 0 ? static_cast<Scalar>(i) : static_cast<Scalar>(i) + 0.5f), j); map.emplace_back(dimensions, (j % 2 == 0 ? static_cast<Scalar>(i) : static_cast<Scalar>(i) + 0.5f), j);
} }
[[nodiscard]] std::pair<blt::size_t, blt::size_t> from_index(blt::size_t index) const [[nodiscard]] blt::vec2ul from_index(blt::size_t index) const
{ {
return {index % width, index / width}; return {index % width, index / width};
} }

View File

@ -20,6 +20,8 @@
#define COSC_4P80_ASSIGNMENT_3_FWDECL_H #define COSC_4P80_ASSIGNMENT_3_FWDECL_H
#include <blt/std/types.h> #include <blt/std/types.h>
#include <blt/std/hashmap.h>
#include <array>
namespace assign3 namespace assign3
{ {
@ -38,6 +40,17 @@ namespace assign3
TOROIDAL = RENDER_3D, TOROIDAL = RENDER_3D,
CYLINDER = RENDER_3D CYLINDER = RENDER_3D
}; };
enum class debug_type
{
DATA_POINT,
DISTANCE
};
inline std::array<std::string, 2> debug_names {
"Distance to Datapoint",
"Distance to Neighbours"
};
} }
#endif //COSC_4P80_ASSIGNMENT_3_FWDECL_H #endif //COSC_4P80_ASSIGNMENT_3_FWDECL_H

View File

@ -30,16 +30,19 @@ namespace assign3
{ {
class renderer_t; class renderer_t;
struct render_info_t struct neuron_render_info_t
{ {
blt::vec2 base_pos; blt::vec2 base_pos;
blt::vec2 neuron_padding; blt::vec2 neuron_padding;
float neuron_scale = 0; float neuron_scale = 0;
static render_info_t fill_screen(renderer_t& renderer, float neuron_scale = 35, float x_padding = 250, float y_padding = 50, float w_padding = 50, float h_padding = 50); static neuron_render_info_t fill_screen(renderer_t& renderer, float neuron_scale = 35, float x_padding = 250, float y_padding = 50,
float w_padding = 50, float h_padding = 50);
BLT_LVALUE_SETTER(blt::vec2, base_pos); BLT_LVALUE_SETTER(blt::vec2, base_pos);
BLT_LVALUE_SETTER(blt::vec2, neuron_padding); BLT_LVALUE_SETTER(blt::vec2, neuron_padding);
BLT_PRVALUE_SETTER(float, neuron_scale); BLT_PRVALUE_SETTER(float, neuron_scale);
}; };
@ -52,11 +55,24 @@ namespace assign3
void update(); void update();
}; };
struct render_data_t
{
blt::size_t index;
const neuron_t& neuron;
blt::vec2 neuron_scaled;
blt::vec2 neuron_offset;
blt::vec2 neuron_padded;
render_data_t(size_t index, const neuron_t& neuron, const blt::vec2& neuronScaled, const blt::vec2& neuronOffset,
const blt::vec2& neuronPadded):
index(index), neuron(neuron), neuron_scaled(neuronScaled), neuron_offset(neuronOffset), neuron_padded(neuronPadded)
{}
};
class renderer_t class renderer_t
{ {
friend motor_data_t; friend motor_data_t;
friend render_info_t; friend neuron_render_info_t;
public: public:
explicit renderer_t(motor_data_t& data, blt::gfx::resource_manager& resources, blt::gfx::matrix_state_manager& state): explicit renderer_t(motor_data_t& data, blt::gfx::resource_manager& resources, blt::gfx::matrix_state_manager& state):
motor_data(data), br2d{resources, state} motor_data(data), br2d{resources, state}
@ -66,7 +82,11 @@ namespace assign3
void cleanup(); void cleanup();
void draw_som(const std::function<blt::vec4(neuron_t&)>& color_func, bool debug); std::vector<float> get_neuron_activations(const data_file_t& file);
void draw_som(neuron_render_info_t info, const std::function<blt::vec4(render_data_t)>& color_func);
void draw_debug(const data_file_t& file);
void render(); void render();
@ -95,6 +115,10 @@ namespace assign3
Scalar initial_learn_rate = 0.1; Scalar initial_learn_rate = 0.1;
int currently_selected_network = 0; int currently_selected_network = 0;
bool debug_mode = false;
bool running = false;
int debug_state = 0;
int selected_data_point = 0;
}; };
} }

@ -1 +1 @@
Subproject commit 0a0b87fc5566211cb7375d9c1b361ba3e91a3545 Subproject commit 361083780325a2a73c9467320dcd5c7ced51e754

View File

@ -3,6 +3,7 @@
#include <blt/gfx/window.h> #include <blt/gfx/window.h>
#include "blt/gfx/renderer/resource_manager.h" #include "blt/gfx/renderer/resource_manager.h"
#include "blt/gfx/renderer/camera.h" #include "blt/gfx/renderer/camera.h"
#include "implot.h"
#include <assign3/file.h> #include <assign3/file.h>
#include <assign3/manager.h> #include <assign3/manager.h>
@ -22,6 +23,8 @@ void init(const blt::gfx::window_data&)
global_matrices.create_internals(); global_matrices.create_internals();
resources.load_resources(); resources.load_resources();
renderer.create(); renderer.create();
ImPlot::CreateContext();
} }
void update(const blt::gfx::window_data& window_data) void update(const blt::gfx::window_data& window_data)
@ -41,6 +44,7 @@ void destroy(const blt::gfx::window_data&)
global_matrices.cleanup(); global_matrices.cleanup();
resources.cleanup(); resources.cleanup();
renderer.cleanup(); renderer.cleanup();
ImPlot::DestroyContext();
blt::gfx::cleanup(); blt::gfx::cleanup();
BLT_INFO("Goodbye World!"); BLT_INFO("Goodbye World!");
} }

View File

@ -17,21 +17,35 @@
*/ */
#include <assign3/manager.h> #include <assign3/manager.h>
#include <blt/gfx/window.h> #include <blt/gfx/window.h>
#include <blt/math/log_util.h>
#include <imgui.h> #include <imgui.h>
#include <implot.h> #include <implot.h>
static void HelpMarker(const std::string& desc)
{
ImGui::TextDisabled("(?)");
if (ImGui::BeginItemTooltip())
{
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(desc.c_str());
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
}
const char* get_selection_string(void* user_data, int selection) const char* get_selection_string(void* user_data, int selection)
{ {
return (*reinterpret_cast<std::vector<std::string>*>(user_data))[selection].c_str(); return (reinterpret_cast<std::string*>(user_data))[selection].c_str();
} }
namespace assign3 namespace assign3
{ {
render_info_t render_info_t::fill_screen(renderer_t& renderer, float neuron_scale, float x_padding, float y_padding, float w_padding, neuron_render_info_t neuron_render_info_t::fill_screen(renderer_t& renderer, float neuron_scale, float x_padding, float y_padding,
float h_padding) float w_padding,
float h_padding)
{ {
render_info_t info; neuron_render_info_t info;
info.set_neuron_scale(neuron_scale); info.set_neuron_scale(neuron_scale);
info.set_base_pos({x_padding, y_padding}); info.set_base_pos({x_padding, y_padding});
@ -44,7 +58,9 @@ namespace assign3
float remain_width = screen_width - neuron_width; float remain_width = screen_width - neuron_width;
float remain_height = screen_height - neuron_height; float remain_height = screen_height - neuron_height;
info.set_neuron_padding({remain_width / static_cast<float>(renderer.som_width), remain_height / static_cast<float>(renderer.som_height)}); float remain = std::min(remain_width, remain_height);
info.set_neuron_padding({remain / static_cast<float>(renderer.som_width), remain / static_cast<float>(renderer.som_height)});
return info; return info;
} }
@ -57,9 +73,11 @@ namespace assign3
void renderer_t::create() void renderer_t::create()
{ {
fr2d.create(250, 2048); fr2d.create_default(250, 2048);
br2d.create(); br2d.create();
topology_function = std::make_unique<gaussian_function_t>();
generate_network(currently_selected_network); generate_network(currently_selected_network);
update_graphics(); update_graphics();
} }
@ -70,150 +88,90 @@ namespace assign3
br2d.cleanup(); br2d.cleanup();
} }
void renderer_t::draw_som(const std::function<blt::vec4(neuron_t&)>& color_func, bool debug) void renderer_t::draw_som(neuron_render_info_t info, const std::function<blt::vec4(render_data_t)>& color_func)
{ {
for (const auto& [i, neuron] : blt::enumerate(som->get_array().get_map()))
{
blt::vec2 neuron_pos = {neuron.get_x(), neuron.get_y()};
auto neuron_scaled = neuron_pos * info.neuron_scale;
auto neuron_offset = neuron_scaled + info.base_pos;
auto neuron_padded = neuron_offset + neuron_pos * info.neuron_padding;
auto color = color_func({i, neuron, neuron_scaled, neuron_offset, neuron_padded});
br2d.drawPointInternal(color, blt::gfx::point2d_t{neuron_padded, info.neuron_scale});
}
} }
void renderer_t::render() void renderer_t::render()
{ {
using namespace blt::gfx; using namespace blt::gfx;
ImGui::ShowDemoWindow();
ImPlot::ShowDemoWindow();
if (ImGui::Begin("Controls")) if (ImGui::Begin("Controls"))
{ {
ImGui::Text("Network Select"); ImGui::SetNextItemOpen(true, ImGuiCond_Appearing);
if (ImGui::ListBox("##Network Select", &currently_selected_network, get_selection_string, &motor_data.map_files_names, if (ImGui::CollapsingHeader("SOM Control"))
static_cast<int>(motor_data.map_files_names.size()))) {
generate_network(currently_selected_network); ImGui::Text("Network Select");
if (ImGui::ListBox("##Network Select", &currently_selected_network, get_selection_string, motor_data.map_files_names.data(),
static_cast<int>(motor_data.map_files_names.size())))
generate_network(currently_selected_network);
if (ImGui::Button("Run Epoch")) if (ImGui::Button("Run Epoch"))
{
som->train_epoch(initial_learn_rate, topology_function.get());
}
static bool run;
ImGui::Checkbox("Run to completion", &run);
if (run)
{
if (som->get_current_epoch() < som->get_max_epochs())
som->train_epoch(initial_learn_rate, topology_function.get()); som->train_epoch(initial_learn_rate, topology_function.get());
ImGui::Checkbox("Run to completion", &running);
ImGui::Text("Epoch %ld / %ld", som->get_current_epoch(), som->get_max_epochs());
}
if (ImGui::CollapsingHeader("Debug"))
{
ImGui::Checkbox("Debug Visuals", &debug_mode);
if (debug_mode)
{
ImGui::ListBox("##DebugStateSelect", &debug_state, get_selection_string, debug_names.data(), debug_names.size());
switch (static_cast<debug_type>(debug_state))
{
case debug_type::DATA_POINT:
{
auto current_data_file = motor_data.files[currently_selected_network].normalize();
std::vector<std::string> names;
for (const auto& [i, v] : blt::enumerate(current_data_file.data_points))
names.push_back("#" + std::to_string(i) + " (" + (v.is_bad ? "Bad)" : "Good)"));
ImGui::Text("Select Data Point");
ImGui::ListBox("##SelectDataPoint", &selected_data_point, get_selection_string, names.data(),
static_cast<int>(names.size()));
}
break;
case debug_type::DISTANCE:
break;
}
}
} }
ImGui::Text("Epoch %ld / %ld", som->get_current_epoch(), som->get_max_epochs());
} }
ImGui::End(); ImGui::End();
static std::vector<blt::i64> activations; if (running)
{
activations.clear(); if (som->get_current_epoch() < som->get_max_epochs())
activations.resize(som->get_array().get_map().size()); som->train_epoch(initial_learn_rate, topology_function.get());
}
auto current_data_file = motor_data.files[currently_selected_network].normalize(); auto current_data_file = motor_data.files[currently_selected_network].normalize();
for (auto& v : current_data_file.data_points)
if (!debug_mode)
{ {
const auto nearest = som->get_closest_neuron(v.bins); auto closest_type = get_neuron_activations(current_data_file);
activations[nearest] += v.is_bad ? -1 : 1; draw_som(neuron_render_info_t{}.set_base_pos({370, 145}).set_neuron_scale(120).set_neuron_padding({5, 5}),
} [&closest_type](render_data_t context) {
auto type = closest_type[context.index];
return type >= 0 ? blt::make_color(0, type, 0) : blt::make_color(-type, 0, 0);
});
} else
draw_debug(current_data_file);
const blt::i64 max = *std::max_element(activations.begin(), activations.end()); br2d.render(0, 0);
const blt::i64 min = *std::min_element(activations.begin(), activations.end());
for (auto [i, v] : blt::enumerate(som->get_array().get_map()))
{
const auto activation = activations[i];
blt::vec4 color = blt::make_color(1, 1, 1);
if (activation > 0)
color = blt::make_color(0, static_cast<Scalar>(activation) / static_cast<Scalar>(max), 0);
else if (activation < 0)
color = blt::make_color(std::abs(static_cast<Scalar>(activation) / static_cast<Scalar>(min)), 0, 0);
br2d.drawPointInternal(color, point2d_t{v.get_x() * neuron_scale + neuron_scale, v.get_y() * neuron_scale + neuron_scale, neuron_scale});
}
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& [is_bins_bad, bins] : current_data_file.data_points)
{
if (const auto dist = v.dist(bins); dist < lowest_distance)
{
lowest_distance = dist;
is_bad = is_bins_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);
br2d.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
});
}
closest_type.clear();
closest_type.resize(som->get_array().get_map().size());
for (auto [i, v] : blt::enumerate(som->get_array().get_map()))
{
auto half = som->find_closest_neighbour_distance(i);
auto scale = topology_function->scale(half * 0.5f, 0.5);
for (const auto& data : current_data_file.data_points)
{
auto dist = v.dist(data.bins);
auto ds = topology_function->call(dist, scale);
// BLT_TRACE("%f, %f, %f", ds, dist, scale);
if (data.is_bad)
closest_type[i] -= ds;
else
closest_type[i] += ds;
}
}
auto min_act = *std::min_element(closest_type.begin(), closest_type.end());
auto max_act = *std::max_element(closest_type.begin(), closest_type.end());
for (auto& v : closest_type)
{
auto n = 2 * (v - min_act) / (max_act - min_act) - 1;
v = n;
}
// BLT_TRACE("Min %f Max %f", min_act, max_act);
for (auto [i, v] : blt::enumerate(som->get_array().get_map()))
{
auto type = closest_type[i];
blt::vec4 color;
if (type >= 0)
color = blt::make_color(0, type, 0);
else
color = blt::make_color(-type, 0, 0);
br2d.drawPointInternal(color,
point2d_t{
draw_width + neuron_scale * 2 + v.get_x() * neuron_scale + neuron_scale,
draw_height + neuron_scale * 2 + v.get_y() * neuron_scale + neuron_scale, neuron_scale
});
}
br2d.render(0,0);
fr2d.render(); fr2d.render();
} }
@ -231,9 +189,66 @@ namespace assign3
auto max_x = std::max_element(som_neurons.begin(), som_neurons.end(), x_comparator)->get_x(); auto max_x = std::max_element(som_neurons.begin(), som_neurons.end(), x_comparator)->get_x();
auto min_y = std::min_element(som_neurons.begin(), som_neurons.end(), y_comparator)->get_y(); auto min_y = std::min_element(som_neurons.begin(), som_neurons.end(), y_comparator)->get_y();
auto max_y = std::max_element(som_neurons.begin(), som_neurons.end(), y_comparator)->get_y(); auto max_y = std::max_element(som_neurons.begin(), som_neurons.end(), y_comparator)->get_y();
draw_width = (max_x - min_x) * neuron_scale; draw_width = (max_x - min_x);
draw_height = (max_y - min_y) * neuron_scale; draw_height = (max_y - min_y);
}
topology_function = std::make_unique<gaussian_function_t>(); std::vector<float> renderer_t::get_neuron_activations(const data_file_t& file)
{
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()))
{
auto half = som->find_closest_neighbour_distance(i);
auto scale = topology_function->scale(half * 0.5f, 0.5);
for (const auto& data : file.data_points)
{
auto dist = v.dist(data.bins);
auto ds = topology_function->call(dist, scale);
if (data.is_bad)
closest_type[i] -= ds;
else
closest_type[i] += ds;
}
}
auto min_act = *std::min_element(closest_type.begin(), closest_type.end());
auto max_act = *std::max_element(closest_type.begin(), closest_type.end());
for (auto& v : closest_type)
{
auto n = 2 * (v - min_act) / (max_act - min_act) - 1;
v = n;
}
return closest_type;
}
void renderer_t::draw_debug(const data_file_t& file)
{
switch (static_cast<debug_type>(debug_state))
{
case debug_type::DATA_POINT:
{
const auto& data_point = file.data_points[selected_data_point];
auto closest_type = get_neuron_activations(file);
draw_som(neuron_render_info_t{}.set_base_pos({370, 145}).set_neuron_scale(120).set_neuron_padding({50, 50}),
[this, &closest_type](render_data_t context) {
auto& text = fr2d.render_text(std::to_string(closest_type[context.index]), 13);
auto text_width = text.getAssociatedText().getTextWidth();
auto text_height = text.getAssociatedText().getTextHeight();
text.setPosition(context.neuron_padded - blt::vec2{text_width / 2.0f, text_height / 2.0f}).setZIndex(1);
auto type = closest_type[context.index];
return type >= 0 ? blt::make_color(0, type, 0) : blt::make_color(-type, 0, 0);
});
}
break;
case debug_type::DISTANCE:
{
}
break;
}
} }
} }