about to start convert
parent
f84919ccb5
commit
73da5ff006
|
@ -0,0 +1,222 @@
|
||||||
|
<?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">{
|
||||||
|
"useNewFormat": 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 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/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/libraries/parallel-hashmap" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/libraries/parallel-hashmap" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/libraries/parallel-hashmap/examples/llil_utils/gen-llil.pl" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/libraries/parallel-hashmap/examples/llil_utils/gen-llil.pl" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/libraries/parallel-hashmap/examples/llil_utils/gen_files" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/libraries/parallel-hashmap/examples/llil_utils/gen_files" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/libraries/parallel-hashmap/examples/llil_utils/run_llil4map" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/libraries/parallel-hashmap/examples/llil_utils/run_llil4map" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/libraries/parallel-hashmap/phmap_lldb.py" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/libraries/parallel-hashmap/phmap_lldb.py" 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">{
|
||||||
|
"associatedIndex": 7
|
||||||
|
}</component>
|
||||||
|
<component name="ProjectId" id="2oG5NNX4GedKhxLJDuzQ5OR5kr5" />
|
||||||
|
<component name="ProjectViewState">
|
||||||
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
|
<option name="showLibraryContents" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PropertiesComponent">{
|
||||||
|
"keyToString": {
|
||||||
|
"CMake Application.COSC-4P80-Assignment-3.executor": "Run",
|
||||||
|
"NIXITCH_NIXPKGS_CONFIG": "/etc/nix/nixpkgs-config.nix",
|
||||||
|
"NIXITCH_NIX_CONF_DIR": "",
|
||||||
|
"NIXITCH_NIX_OTHER_STORES": "",
|
||||||
|
"NIXITCH_NIX_PATH": "/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",
|
||||||
|
"NIXITCH_NIX_PROFILES": "/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",
|
||||||
|
"NIXITCH_NIX_REMOTE": "",
|
||||||
|
"NIXITCH_NIX_USER_PROFILE_DIR": "/nix/var/nix/profiles/per-user/brett",
|
||||||
|
"RunOnceActivity.RadMigrateCodeStyle": "true",
|
||||||
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
|
"RunOnceActivity.cidr.known.project.marker": "true",
|
||||||
|
"RunOnceActivity.readMode.enableVisualFormatting": "true",
|
||||||
|
"SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
||||||
|
"cf.advertisement.text.has.clang-format": "true",
|
||||||
|
"cf.first.check.clang-format": "false",
|
||||||
|
"cidr.known.project.marker": "true",
|
||||||
|
"git-widget-placeholder": "main",
|
||||||
|
"last_opened_file_path": "/home/brett/Documents/Brock/CS 4P80/COSC-4P80-Assignment-3",
|
||||||
|
"node.js.detected.package.eslint": "true",
|
||||||
|
"node.js.detected.package.tslint": "true",
|
||||||
|
"node.js.selected.package.eslint": "(autodetect)",
|
||||||
|
"node.js.selected.package.tslint": "(autodetect)",
|
||||||
|
"nodejs_package_manager_path": "npm",
|
||||||
|
"run.code.analysis.last.selected.profile": "pProject Default",
|
||||||
|
"settings.editor.selected.configurable": "preferences.sourceCode.C/C++",
|
||||||
|
"structure.view.defaults.are.configured": "true",
|
||||||
|
"vue.rearranger.settings.migration": "true"
|
||||||
|
}
|
||||||
|
}</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 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="10825000" />
|
||||||
|
<workItem from="1731969052837" duration="4000" />
|
||||||
|
</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>
|
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
project(COSC-4P80-Assignment-3 VERSION 0.0.20)
|
project(COSC-4P80-Assignment-3 VERSION 0.0.21)
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
|
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
|
||||||
|
|
|
@ -44,8 +44,8 @@ namespace assign3
|
||||||
case shape_t::GRID_OFFSET_WRAP:
|
case shape_t::GRID_OFFSET_WRAP:
|
||||||
for (blt::size_t j = 0; j < height; j++)
|
for (blt::size_t j = 0; j < height; j++)
|
||||||
for (blt::size_t i = 0; i < width; i++)
|
for (blt::size_t i = 0; i < width; i++)
|
||||||
map.emplace_back(dimensions, (j % 2 == 0 ? static_cast<Scalar>(i) : static_cast<Scalar>(i) + 0.5f),
|
map.emplace_back(dimensions, (j % 2 == 0 ? static_cast<Scalar>(i) : static_cast<Scalar>(i) + 0.5f), j);
|
||||||
static_cast<Scalar>(static_cast<double>(j) * (std::sqrt(3) / 2.0)));
|
// static_cast<Scalar>(static_cast<double>(j) * (std::sqrt(3) / 2.0))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,23 @@ namespace assign3
|
||||||
blt::i32 width, height;
|
blt::i32 width, height;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct axial_distance_function_t : public distance_function_t
|
||||||
|
{
|
||||||
|
[[nodiscard]] Scalar distance(blt::span<const Scalar> x, blt::span<const Scalar> y) const final;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct toroidal_axial_distance_function_t : public distance_function_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
toroidal_axial_distance_function_t(blt::i32 width, blt::i32 height): width(width), height(height)
|
||||||
|
{}
|
||||||
|
|
||||||
|
[[nodiscard]] Scalar distance(blt::span<const Scalar> x, blt::span<const Scalar> y) const final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
blt::i32 width, height;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //COSC_4P80_ASSIGNMENT_3_FUNCTIONS_H
|
#endif //COSC_4P80_ASSIGNMENT_3_FUNCTIONS_H
|
||||||
|
|
|
@ -82,10 +82,6 @@ namespace assign3
|
||||||
|
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
|
||||||
std::vector<float> get_neuron_activations(const data_file_t& file);
|
|
||||||
|
|
||||||
static std::vector<float> normalize_data(const std::vector<float>& data);
|
|
||||||
|
|
||||||
void draw_som(neuron_render_info_t info, const std::function<blt::vec4(render_data_t)>& color_func);
|
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 draw_debug(const data_file_t& file);
|
||||||
|
@ -97,19 +93,22 @@ namespace assign3
|
||||||
switch (static_cast<shape_t>(selected_som_mode))
|
switch (static_cast<shape_t>(selected_som_mode))
|
||||||
{
|
{
|
||||||
case shape_t::GRID:
|
case shape_t::GRID:
|
||||||
case shape_t::GRID_OFFSET:
|
|
||||||
distance_function = std::make_unique<euclidean_distance_function_t>();
|
distance_function = std::make_unique<euclidean_distance_function_t>();
|
||||||
break;
|
break;
|
||||||
case shape_t::GRID_OFFSET_WRAP:
|
|
||||||
case shape_t::GRID_WRAP:
|
case shape_t::GRID_WRAP:
|
||||||
distance_function = std::make_unique<toroidal_euclidean_distance_function_t>(som_width, som_height);
|
distance_function = std::make_unique<toroidal_euclidean_distance_function_t>(som_width, som_height);
|
||||||
break;
|
break;
|
||||||
|
case shape_t::GRID_OFFSET:
|
||||||
|
distance_function = std::make_unique<axial_distance_function_t>();
|
||||||
|
break;
|
||||||
|
case shape_t::GRID_OFFSET_WRAP:
|
||||||
|
distance_function = std::make_unique<toroidal_axial_distance_function_t>(som_width, som_height);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
error_plotting.clear();
|
|
||||||
som = std::make_unique<som_t>(motor_data.files[currently_selected_network], som_width, som_height, max_epochs,
|
som = std::make_unique<som_t>(motor_data.files[currently_selected_network], som_width, som_height, max_epochs,
|
||||||
distance_function.get(), static_cast<shape_t>(selected_som_mode),
|
distance_function.get(), topology_function.get(), static_cast<shape_t>(selected_som_mode),
|
||||||
static_cast<init_t>(selected_init_type), normalize_init);
|
static_cast<init_t>(selected_init_type), normalize_init);
|
||||||
error_plotting.push_back(som->topological_error(motor_data.files[currently_selected_network]));
|
som->compute_neuron_activations();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -118,8 +117,6 @@ namespace assign3
|
||||||
std::unique_ptr<topology_function_t> topology_function;
|
std::unique_ptr<topology_function_t> topology_function;
|
||||||
std::unique_ptr<distance_function_t> distance_function;
|
std::unique_ptr<distance_function_t> distance_function;
|
||||||
|
|
||||||
std::vector<Scalar> error_plotting;
|
|
||||||
|
|
||||||
blt::gfx::font_renderer_t fr2d{};
|
blt::gfx::font_renderer_t fr2d{};
|
||||||
blt::gfx::batch_renderer_2d br2d;
|
blt::gfx::batch_renderer_2d br2d;
|
||||||
|
|
||||||
|
|
|
@ -30,17 +30,23 @@ namespace assign3
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
som_t(const data_file_t& file, blt::size_t width, blt::size_t height, blt::size_t max_epochs, distance_function_t* dist_func,
|
som_t(const data_file_t& file, blt::size_t width, blt::size_t height, blt::size_t max_epochs, distance_function_t* dist_func,
|
||||||
shape_t shape, init_t init, bool normalize);
|
topology_function_t* topology_function, shape_t shape, init_t init, bool normalize);
|
||||||
|
|
||||||
blt::size_t get_closest_neuron(const std::vector<Scalar>& data);
|
blt::size_t get_closest_neuron(const std::vector<Scalar>& data);
|
||||||
|
|
||||||
Scalar find_closest_neighbour_distance(blt::size_t v0);
|
Scalar find_closest_neighbour_distance(blt::size_t v0);
|
||||||
|
|
||||||
void train_epoch(Scalar initial_learn_rate, topology_function_t* basis_func);
|
void train_epoch(Scalar initial_learn_rate);
|
||||||
|
|
||||||
blt::vec2 get_topological_position(const std::vector<Scalar>& data);
|
blt::vec2 get_topological_position(const std::vector<Scalar>& data);
|
||||||
|
|
||||||
Scalar topological_error(const data_file_t& data);
|
Scalar topological_error();
|
||||||
|
|
||||||
|
void compute_neuron_activations(Scalar distance = 2, Scalar activation = 0.5);
|
||||||
|
|
||||||
|
void write_activations(std::ostream& out);
|
||||||
|
|
||||||
|
void write_topology_errors(std::ostream& out);
|
||||||
|
|
||||||
[[nodiscard]] const array_t& get_array() const
|
[[nodiscard]] const array_t& get_array() const
|
||||||
{ return array; }
|
{ return array; }
|
||||||
|
@ -51,12 +57,18 @@ namespace assign3
|
||||||
[[nodiscard]] blt::size_t get_max_epochs() const
|
[[nodiscard]] blt::size_t get_max_epochs() const
|
||||||
{ return max_epochs; }
|
{ return max_epochs; }
|
||||||
|
|
||||||
|
[[nodiscard]] const std::vector<Scalar>& get_topological_errors() const
|
||||||
|
{ return topological_errors; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
array_t array;
|
array_t array;
|
||||||
data_file_t file;
|
data_file_t file;
|
||||||
blt::size_t current_epoch = 0;
|
blt::size_t current_epoch = 0;
|
||||||
blt::size_t max_epochs;
|
blt::size_t max_epochs;
|
||||||
distance_function_t* dist_func;
|
distance_function_t* dist_func;
|
||||||
|
topology_function_t* topology_function;
|
||||||
|
|
||||||
|
std::vector<Scalar> topological_errors;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,4 +54,38 @@ namespace assign3
|
||||||
Scalar y_min = std::min(y_diff, static_cast<Scalar>(height) - y_diff);
|
Scalar y_min = std::min(y_diff, static_cast<Scalar>(height) - y_diff);
|
||||||
return std::sqrt(x_min * x_min + y_min * y_min);
|
return std::sqrt(x_min * x_min + y_min * y_min);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Scalar axial_distance_function_t::distance(blt::span<const Scalar> x, blt::span<const Scalar> y) const
|
||||||
|
{
|
||||||
|
static thread_local std::vector<Scalar> distances;
|
||||||
|
distances.clear();
|
||||||
|
Scalar total = 0;
|
||||||
|
for (auto [q, r] : blt::in_pairs(x, y))
|
||||||
|
{
|
||||||
|
distances.push_back(std::abs(q - r));
|
||||||
|
total += distances.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
Scalar min = distances.front();
|
||||||
|
for (auto v : distances)
|
||||||
|
min = std::min(min, v);
|
||||||
|
|
||||||
|
return total - min;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scalar axial_distance(Scalar q1, Scalar r1, Scalar q2, Scalar r2) {
|
||||||
|
return (std::abs(q1 - q2) + std::abs(r1 - r2) + std::abs((q1 + r1) - (q2 + r2))) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scalar toroidal_axial_distance_function_t::distance(blt::span<const Scalar> x, blt::span<const Scalar> y) const
|
||||||
|
{
|
||||||
|
BLT_ASSERT(x.size() == 2 && y.size() == 2);
|
||||||
|
|
||||||
|
Scalar x_diff = std::abs(x[0] - y[0]);
|
||||||
|
Scalar y_diff = std::abs(x[1] - y[1]);
|
||||||
|
Scalar x_min = std::min(x_diff, static_cast<Scalar>(width) - x_diff);
|
||||||
|
Scalar y_min = std::min(y_diff, static_cast<Scalar>(height) - y_diff);
|
||||||
|
Scalar total = x_min + y_min;
|
||||||
|
return total - std::min(x_min, y_min);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,125 @@
|
||||||
|
#include <blt/std/logging.h>
|
||||||
|
#include <blt/parse/argparse.h>
|
||||||
|
#include <blt/gfx/window.h>
|
||||||
|
#include "blt/gfx/renderer/resource_manager.h"
|
||||||
|
#include "blt/gfx/renderer/camera.h"
|
||||||
|
#include "implot.h"
|
||||||
|
#include <assign3/file.h>
|
||||||
|
#include <assign3/manager.h>
|
||||||
|
|
||||||
|
using namespace assign3;
|
||||||
|
|
||||||
|
blt::gfx::matrix_state_manager global_matrices;
|
||||||
|
blt::gfx::resource_manager resources;
|
||||||
|
blt::gfx::first_person_camera_2d camera;
|
||||||
|
assign3::motor_data_t data{};
|
||||||
|
assign3::renderer_t renderer{data, resources, global_matrices};
|
||||||
|
|
||||||
|
void init(const blt::gfx::window_data&)
|
||||||
|
{
|
||||||
|
using namespace blt::gfx;
|
||||||
|
BLT_INFO("Hello World!");
|
||||||
|
|
||||||
|
global_matrices.create_internals();
|
||||||
|
resources.load_resources();
|
||||||
|
renderer.create();
|
||||||
|
|
||||||
|
ImPlot::CreateContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(const blt::gfx::window_data& window_data)
|
||||||
|
{
|
||||||
|
using namespace blt::gfx;
|
||||||
|
global_matrices.update_perspectives(window_data.width, window_data.height, 90, 0.1, 2000);
|
||||||
|
|
||||||
|
camera.update();
|
||||||
|
camera.update_view(global_matrices);
|
||||||
|
global_matrices.update();
|
||||||
|
|
||||||
|
renderer.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy(const blt::gfx::window_data&)
|
||||||
|
{
|
||||||
|
global_matrices.cleanup();
|
||||||
|
resources.cleanup();
|
||||||
|
renderer.cleanup();
|
||||||
|
ImPlot::DestroyContext();
|
||||||
|
blt::gfx::cleanup();
|
||||||
|
BLT_INFO("Goodbye World!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_data_files(const std::string& str)
|
||||||
|
{
|
||||||
|
data.files = assign3::data_file_t::load_data_files_from_path(str);
|
||||||
|
for (auto& v : data.files)
|
||||||
|
v = v.normalize();
|
||||||
|
data.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void action_start_graphics(const std::vector<std::string>& argv_vector)
|
||||||
|
{
|
||||||
|
blt::arg_parse parser{};
|
||||||
|
|
||||||
|
parser.addArgument(blt::arg_builder{"--file", "-f"}
|
||||||
|
.setDefault("../data")
|
||||||
|
.setHelp("Path to data files").build());
|
||||||
|
|
||||||
|
auto args = parser.parse_args(argv_vector);
|
||||||
|
|
||||||
|
load_data_files(args.get<std::string>("file"));
|
||||||
|
|
||||||
|
blt::gfx::init(blt::gfx::window_data{"My Sexy Window", init, update, destroy}.setSyncInterval(1).setMaximized(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
void action_test(const std::vector<std::string>& argv_vector)
|
||||||
|
{
|
||||||
|
blt::arg_parse parser{};
|
||||||
|
|
||||||
|
parser.addArgument(blt::arg_builder{"--file", "-f"}
|
||||||
|
.setDefault("../data")
|
||||||
|
.setHelp("Path to data files").build());
|
||||||
|
|
||||||
|
auto args = parser.parse_args(argv_vector);
|
||||||
|
|
||||||
|
load_data_files(args.get<std::string>("file"));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void action_convert(const std::vector<std::string>& argv_vector)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char** argv)
|
||||||
|
{
|
||||||
|
std::vector<std::string> argv_vector;
|
||||||
|
for (int i = 0; i < argc; i++)
|
||||||
|
argv_vector.emplace_back(argv[i]);
|
||||||
|
|
||||||
|
blt::arg_parse parser{};
|
||||||
|
|
||||||
|
parser.addArgument(blt::arg_builder{"action"}
|
||||||
|
.setAction(blt::arg_action_t::SUBCOMMAND)
|
||||||
|
.setHelp("Action to run. Can be: [graphics, test, convert]").build());
|
||||||
|
|
||||||
|
auto args = parser.parse_args(argv_vector);
|
||||||
|
|
||||||
|
if (!args.contains("action"))
|
||||||
|
{
|
||||||
|
BLT_ERROR("Please provide an action");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
argv_vector.erase(argv_vector.begin() + 1);
|
||||||
|
|
||||||
|
auto action = blt::string::toLowerCase(args.get<std::string>("action"));
|
||||||
|
if (action == "graphics")
|
||||||
|
action_start_graphics(argv_vector);
|
||||||
|
else if (action == "test")
|
||||||
|
action_test(argv_vector);
|
||||||
|
else if (action == "convert")
|
||||||
|
action_convert(argv_vector);
|
||||||
|
|
||||||
|
}
|
80
src/main.cpp
80
src/main.cpp
|
@ -49,18 +49,82 @@ void destroy(const blt::gfx::window_data&)
|
||||||
BLT_INFO("Goodbye World!");
|
BLT_INFO("Goodbye World!");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, const char** argv)
|
void load_data_files(const std::string& str)
|
||||||
{
|
{
|
||||||
blt::arg_parse parser{};
|
data.files = assign3::data_file_t::load_data_files_from_path(str);
|
||||||
|
|
||||||
parser.addArgument(blt::arg_builder{"--file", "-f"}.setDefault("../data").setHelp("Path to data files").build());
|
|
||||||
|
|
||||||
auto args = parser.parse_args(argc, argv);
|
|
||||||
|
|
||||||
data.files = assign3::data_file_t::load_data_files_from_path(args.get<std::string>("file"));
|
|
||||||
for (auto& v : data.files)
|
for (auto& v : data.files)
|
||||||
v = v.normalize();
|
v = v.normalize();
|
||||||
data.update();
|
data.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void action_start_graphics(const std::vector<std::string>& argv_vector)
|
||||||
|
{
|
||||||
|
blt::arg_parse parser{};
|
||||||
|
parser.setHelpExtras("graphics");
|
||||||
|
|
||||||
|
parser.addArgument(blt::arg_builder{"--file", "-f"}
|
||||||
|
.setDefault("../data")
|
||||||
|
.setHelp("Path to data files").build());
|
||||||
|
|
||||||
|
auto args = parser.parse_args(argv_vector);
|
||||||
|
|
||||||
|
load_data_files(args.get<std::string>("file"));
|
||||||
|
|
||||||
blt::gfx::init(blt::gfx::window_data{"My Sexy Window", init, update, destroy}.setSyncInterval(1).setMaximized(true));
|
blt::gfx::init(blt::gfx::window_data{"My Sexy Window", init, update, destroy}.setSyncInterval(1).setMaximized(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void action_test(const std::vector<std::string>& argv_vector)
|
||||||
|
{
|
||||||
|
blt::arg_parse parser{};
|
||||||
|
parser.setHelpExtras("test");
|
||||||
|
|
||||||
|
parser.addArgument(blt::arg_builder{"--file", "-f"}
|
||||||
|
.setDefault("../data")
|
||||||
|
.setHelp("Path to data files").build());
|
||||||
|
|
||||||
|
auto args = parser.parse_args(argv_vector);
|
||||||
|
|
||||||
|
load_data_files(args.get<std::string>("file"));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void action_convert(const std::vector<std::string>& argv_vector)
|
||||||
|
{
|
||||||
|
blt::arg_parse parser{};
|
||||||
|
parser.setHelpExtras("convert");
|
||||||
|
|
||||||
|
auto args = parser.parse_args(argv_vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char** argv)
|
||||||
|
{
|
||||||
|
std::vector<std::string> argv_vector;
|
||||||
|
for (int i = 0; i < argc; i++)
|
||||||
|
argv_vector.emplace_back(argv[i]);
|
||||||
|
|
||||||
|
blt::arg_parse parser{};
|
||||||
|
|
||||||
|
parser.addArgument(blt::arg_builder{"action"}
|
||||||
|
.setAction(blt::arg_action_t::SUBCOMMAND)
|
||||||
|
.setHelp("Action to run. Can be: [graphics, test, convert]").build());
|
||||||
|
|
||||||
|
auto args = parser.parse_args(argv_vector);
|
||||||
|
|
||||||
|
if (!args.contains("action"))
|
||||||
|
{
|
||||||
|
BLT_ERROR("Please provide an action");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// argv_vector.erase(argv_vector.begin() + 1);
|
||||||
|
|
||||||
|
auto action = blt::string::toLowerCase(args.get<std::string>("action"));
|
||||||
|
if (action == "graphics")
|
||||||
|
action_start_graphics(argv_vector);
|
||||||
|
else if (action == "test")
|
||||||
|
action_test(argv_vector);
|
||||||
|
else if (action == "convert")
|
||||||
|
action_convert(argv_vector);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -123,8 +123,8 @@ namespace assign3
|
||||||
{
|
{
|
||||||
using namespace blt::gfx;
|
using namespace blt::gfx;
|
||||||
|
|
||||||
ImGui::ShowDemoWindow();
|
// ImGui::ShowDemoWindow();
|
||||||
ImPlot::ShowDemoWindow();
|
// ImPlot::ShowDemoWindow();
|
||||||
|
|
||||||
if (ImGui::Begin("Controls"))
|
if (ImGui::Begin("Controls"))
|
||||||
{
|
{
|
||||||
|
@ -137,7 +137,10 @@ namespace assign3
|
||||||
regenerate_network();
|
regenerate_network();
|
||||||
|
|
||||||
if (ImGui::Button("Run Epoch"))
|
if (ImGui::Button("Run Epoch"))
|
||||||
som->train_epoch(initial_learn_rate, topology_function.get());
|
{
|
||||||
|
som->train_epoch(initial_learn_rate);
|
||||||
|
som->compute_neuron_activations();
|
||||||
|
}
|
||||||
ImGui::Checkbox("Run to completion", &running);
|
ImGui::Checkbox("Run to completion", &running);
|
||||||
ImGui::Text("Epoch %ld / %ld", som->get_current_epoch(), som->get_max_epochs());
|
ImGui::Text("Epoch %ld / %ld", som->get_current_epoch(), som->get_max_epochs());
|
||||||
}
|
}
|
||||||
|
@ -152,8 +155,9 @@ namespace assign3
|
||||||
if (ImGui::ListBox("##InitType", &selected_init_type, get_selection_string, init_names.data(), static_cast<int>(init_names.size())))
|
if (ImGui::ListBox("##InitType", &selected_init_type, get_selection_string, init_names.data(), static_cast<int>(init_names.size())))
|
||||||
regenerate_network();
|
regenerate_network();
|
||||||
ImGui::TextWrapped("Help: %s", init_helps[selected_init_type].c_str());
|
ImGui::TextWrapped("Help: %s", init_helps[selected_init_type].c_str());
|
||||||
ImGui::Separator();
|
if (ImGui::Checkbox("Normalize Init Data", &normalize_init))
|
||||||
ImGui::Checkbox("Normalize Init Data", &normalize_init);
|
regenerate_network();
|
||||||
|
ImGui::SeparatorText("Som Specifics");
|
||||||
if (ImGui::InputInt("SOM Width", &som_width) || ImGui::InputInt("SOM Height", &som_height) ||
|
if (ImGui::InputInt("SOM Width", &som_width) || ImGui::InputInt("SOM Height", &som_height) ||
|
||||||
ImGui::InputInt("Max Epochs", &max_epochs))
|
ImGui::InputInt("Max Epochs", &max_epochs))
|
||||||
regenerate_network();
|
regenerate_network();
|
||||||
|
@ -187,7 +191,11 @@ namespace assign3
|
||||||
static std::vector<std::string> names;
|
static std::vector<std::string> names;
|
||||||
names.clear();
|
names.clear();
|
||||||
for (blt::size_t i = 0; i < som->get_array().get_map().size(); i++)
|
for (blt::size_t i = 0; i < som->get_array().get_map().size(); i++)
|
||||||
names.push_back("Neuron " + std::to_string(i));
|
{
|
||||||
|
auto pos = som->get_array().from_index(i);
|
||||||
|
names.push_back("Neuron " + std::to_string(i) +
|
||||||
|
" (" + std::to_string(pos.x()) + ", " + std::to_string(pos.y()) + ")");
|
||||||
|
}
|
||||||
ImGui::Text("Select Neuron");
|
ImGui::Text("Select Neuron");
|
||||||
ImGui::ListBox("##SelectNeuron", &selected_neuron, get_selection_string, names.data(), static_cast<int>(names.size()));
|
ImGui::ListBox("##SelectNeuron", &selected_neuron, get_selection_string, names.data(), static_cast<int>(names.size()));
|
||||||
}
|
}
|
||||||
|
@ -199,14 +207,17 @@ namespace assign3
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
auto current_data_file = motor_data.files[currently_selected_network];
|
auto current_data_file = motor_data.files[currently_selected_network];
|
||||||
auto closest_type = get_neuron_activations(current_data_file);
|
|
||||||
|
|
||||||
if (ImGui::Begin("Plots & Data"))
|
if (ImGui::Begin("Plots & Data"))
|
||||||
{
|
{
|
||||||
ImPlot::SetNextAxesLimits(0, som_width, 0, som_height, ImPlotCond_Always);
|
ImPlot::SetNextAxesLimits(0, som_width, 0, som_height, ImPlotCond_Always);
|
||||||
if (ImPlot::BeginPlot("Activations", ImVec2(-1, 0), ImPlotFlags_NoInputs))
|
if (ImPlot::BeginPlot("Activations", ImVec2(-1, 0), ImPlotFlags_NoInputs))
|
||||||
{
|
{
|
||||||
auto rev = rotate90Clockwise(closest_type, som_width, som_height);
|
static std::vector<float> activations;
|
||||||
|
activations.clear();
|
||||||
|
for (const auto& n : som->get_array().get_map())
|
||||||
|
activations.push_back(n.get_activation());
|
||||||
|
auto rev = rotate90Clockwise(activations, som_width, som_height);
|
||||||
// auto rev = closest_type;
|
// auto rev = closest_type;
|
||||||
// std::reverse(rev.begin(), rev.end());
|
// std::reverse(rev.begin(), rev.end());
|
||||||
ImPlot::PlotHeatmap("##data_map", rev.data(), som_height, som_width, 0, 0, "%.1f", ImPlotPoint(0, 0),
|
ImPlot::PlotHeatmap("##data_map", rev.data(), som_height, som_width, 0, 0, "%.1f", ImPlotPoint(0, 0),
|
||||||
|
@ -216,7 +227,7 @@ namespace assign3
|
||||||
ImPlot::SetNextAxesLimits(0, max_epochs, 0, 1, ImPlotCond_Once);
|
ImPlot::SetNextAxesLimits(0, max_epochs, 0, 1, ImPlotCond_Once);
|
||||||
if (ImPlot::BeginPlot("Error"))
|
if (ImPlot::BeginPlot("Error"))
|
||||||
{
|
{
|
||||||
ImPlot::PlotLine("##error", error_plotting.data(), static_cast<int>(error_plotting.size()));
|
ImPlot::PlotLine("##error", som->get_topological_errors().data(), static_cast<int>(som->get_topological_errors().size()));
|
||||||
ImPlot::EndPlot();
|
ImPlot::EndPlot();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,18 +237,17 @@ namespace assign3
|
||||||
{
|
{
|
||||||
if (som->get_current_epoch() < som->get_max_epochs())
|
if (som->get_current_epoch() < som->get_max_epochs())
|
||||||
{
|
{
|
||||||
som->train_epoch(initial_learn_rate, topology_function.get());
|
som->train_epoch(initial_learn_rate);
|
||||||
error_plotting.push_back(som->topological_error(current_data_file));
|
som->compute_neuron_activations();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!debug_mode)
|
if (!debug_mode)
|
||||||
{
|
{
|
||||||
closest_type = normalize_data(closest_type);
|
|
||||||
draw_som(neuron_render_info_t{}.set_base_pos({370, 145}).set_neuron_scale(120).set_neuron_padding({5, 5}),
|
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) {
|
[](render_data_t context) {
|
||||||
auto type = closest_type[context.index];
|
auto type = context.neuron.get_activation();
|
||||||
return type >= 0 ? blt::make_color(0, type, 0) : blt::make_color(-type, 0, 0);
|
return type >= 0 ? blt::make_color(0, type, 0) : blt::make_color(-type, 0, 0);
|
||||||
});
|
});
|
||||||
} else
|
} else
|
||||||
|
@ -247,33 +257,6 @@ namespace assign3
|
||||||
fr2d.render();
|
fr2d.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
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) / at_distance_measurement;
|
|
||||||
// auto sigma = std::sqrt(-(half * half) / (2 * std::log(requested_activation)));
|
|
||||||
// auto r = 1 / (2 * sigma * sigma);
|
|
||||||
//
|
|
||||||
auto scale = topology_function->scale(half, requested_activation);
|
|
||||||
for (const auto& data : file.data_points)
|
|
||||||
{
|
|
||||||
auto ds = topology_function->call(v.dist(data.bins), scale);
|
|
||||||
if (data.is_bad)
|
|
||||||
closest_type[i] -= ds;
|
|
||||||
else
|
|
||||||
closest_type[i] += ds;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return closest_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderer_t::draw_debug(const data_file_t& file)
|
void renderer_t::draw_debug(const data_file_t& file)
|
||||||
{
|
{
|
||||||
switch (static_cast<debug_t>(debug_state))
|
switch (static_cast<debug_t>(debug_state))
|
||||||
|
@ -307,9 +290,8 @@ namespace assign3
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& data_point = file.data_points[selected_data_point];
|
const auto& data_point = file.data_points[selected_data_point];
|
||||||
auto closest_type = normalize_data(get_neuron_activations(file));
|
|
||||||
draw_som(neuron_render_info_t{}.set_base_pos({370, 145}).set_neuron_scale(120).set_neuron_padding({0, 0}),
|
draw_som(neuron_render_info_t{}.set_base_pos({370, 145}).set_neuron_scale(120).set_neuron_padding({0, 0}),
|
||||||
[this, &neuron_positions, &data_point, &closest_type](render_data_t context) {
|
[this, &neuron_positions, &data_point](render_data_t context) {
|
||||||
auto half = som->find_closest_neighbour_distance(context.index) / at_distance_measurement;
|
auto half = som->find_closest_neighbour_distance(context.index) / at_distance_measurement;
|
||||||
auto scale = topology_function->scale(half, requested_activation);
|
auto scale = topology_function->scale(half, requested_activation);
|
||||||
auto ds = topology_function->call(context.neuron.dist(data_point.bins), scale);
|
auto ds = topology_function->call(context.neuron.dist(data_point.bins), scale);
|
||||||
|
@ -321,7 +303,7 @@ namespace assign3
|
||||||
auto text_height = text.getAssociatedText().getTextHeight();
|
auto text_height = text.getAssociatedText().getTextHeight();
|
||||||
text.setPosition(context.neuron_padded - blt::vec2{text_width / 2.0f, text_height / 2.0f}).setZIndex(1);
|
text.setPosition(context.neuron_padded - blt::vec2{text_width / 2.0f, text_height / 2.0f}).setZIndex(1);
|
||||||
|
|
||||||
auto type = closest_type[context.index];
|
auto type = context.neuron.get_activation();
|
||||||
return type >= 0 ? blt::make_color(0, type, 0) : blt::make_color(-type, 0, 0);
|
return type >= 0 ? blt::make_color(0, type, 0) : blt::make_color(-type, 0, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -334,7 +316,6 @@ namespace assign3
|
||||||
break;
|
break;
|
||||||
case debug_t::DISTANCE:
|
case debug_t::DISTANCE:
|
||||||
{
|
{
|
||||||
auto closest_type = normalize_data(get_neuron_activations(file));
|
|
||||||
auto& selected_neuron_ref = som->get_array().get_map()[selected_neuron];
|
auto& selected_neuron_ref = som->get_array().get_map()[selected_neuron];
|
||||||
static std::vector<Scalar> distances_2d;
|
static std::vector<Scalar> distances_2d;
|
||||||
static std::vector<Scalar> distances_nd;
|
static std::vector<Scalar> distances_nd;
|
||||||
|
@ -348,7 +329,7 @@ namespace assign3
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_som(neuron_render_info_t{}.set_base_pos({370, 145}).set_neuron_scale(120).set_neuron_padding({0, 0}),
|
draw_som(neuron_render_info_t{}.set_base_pos({370, 145}).set_neuron_scale(120).set_neuron_padding({0, 0}),
|
||||||
[this, &closest_type](render_data_t context) {
|
[this](render_data_t context) {
|
||||||
auto& text = fr2d.render_text(
|
auto& text = fr2d.render_text(
|
||||||
"2D: " + std::to_string(distances_2d[context.index]) + "\nND: " +
|
"2D: " + std::to_string(distances_2d[context.index]) + "\nND: " +
|
||||||
std::to_string(distances_nd[context.index]), 18).setColor(0.2, 0.2, 0.8);
|
std::to_string(distances_nd[context.index]), 18).setColor(0.2, 0.2, 0.8);
|
||||||
|
@ -357,24 +338,11 @@ namespace assign3
|
||||||
|
|
||||||
if (static_cast<blt::size_t>(selected_neuron) == context.index)
|
if (static_cast<blt::size_t>(selected_neuron) == context.index)
|
||||||
return blt::make_color(0, 0, 1);
|
return blt::make_color(0, 0, 1);
|
||||||
auto type = closest_type[context.index];
|
auto type = context.neuron.get_activation();
|
||||||
return type >= 0 ? blt::make_color(0, type, 0) : blt::make_color(-type, 0, 0);
|
return type >= 0 ? blt::make_color(0, type, 0) : blt::make_color(-type, 0, 0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<float> renderer_t::normalize_data(const std::vector<float>& data)
|
|
||||||
{
|
|
||||||
std::vector<float> return_data;
|
|
||||||
auto min_act = *std::min_element(data.begin(), data.end());
|
|
||||||
auto max_act = *std::max_element(data.begin(), data.end());
|
|
||||||
for (auto& v : data)
|
|
||||||
{
|
|
||||||
auto n = 2 * (v - min_act) / (max_act - min_act) - 1;
|
|
||||||
return_data.push_back(n);
|
|
||||||
}
|
|
||||||
return return_data;
|
|
||||||
}
|
|
||||||
}
|
}
|
66
src/som.cpp
66
src/som.cpp
|
@ -27,14 +27,16 @@ namespace assign3
|
||||||
{
|
{
|
||||||
|
|
||||||
som_t::som_t(const data_file_t& file, blt::size_t width, blt::size_t height, blt::size_t max_epochs, distance_function_t* dist_func,
|
som_t::som_t(const data_file_t& file, blt::size_t width, blt::size_t height, blt::size_t max_epochs, distance_function_t* dist_func,
|
||||||
shape_t shape, init_t init, bool normalize):
|
topology_function_t* topology_function, shape_t shape, init_t init, bool normalize):
|
||||||
array(file.data_points.begin()->bins.size(), width, height, shape), file(file), max_epochs(max_epochs), dist_func(dist_func)
|
array(file.data_points.begin()->bins.size(), width, height, shape), file(file), max_epochs(max_epochs), dist_func(dist_func),
|
||||||
|
topology_function(topology_function)
|
||||||
{
|
{
|
||||||
for (auto& v : array.get_map())
|
for (auto& v : array.get_map())
|
||||||
v.randomize(std::random_device{}(), init, normalize, file);
|
v.randomize(std::random_device{}(), init, normalize, file);
|
||||||
|
topological_errors.push_back(topological_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
void som_t::train_epoch(Scalar initial_learn_rate, topology_function_t* basis_func)
|
void som_t::train_epoch(Scalar initial_learn_rate)
|
||||||
{
|
{
|
||||||
blt::random::random_t rand{std::random_device{}()};
|
blt::random::random_t rand{std::random_device{}()};
|
||||||
std::shuffle(file.data_points.begin(), file.data_points.end(), rand);
|
std::shuffle(file.data_points.begin(), file.data_points.end(), rand);
|
||||||
|
@ -52,18 +54,18 @@ namespace assign3
|
||||||
auto distance_min = find_closest_neighbour_distance(v0_idx);
|
auto distance_min = find_closest_neighbour_distance(v0_idx);
|
||||||
// this will find the required scaling factor to make a point in the middle between v0 and its closest neighbour activate 50%
|
// this will find the required scaling factor to make a point in the middle between v0 and its closest neighbour activate 50%
|
||||||
// from the perspective of the gaussian function
|
// from the perspective of the gaussian function
|
||||||
auto scale = basis_func->scale(distance_min * 0.5f, 0.5);
|
auto scale = topology_function->scale(distance_min * 0.5f, 0.5);
|
||||||
|
|
||||||
for (auto [i, n] : blt::enumerate(array.get_map()))
|
for (auto [i, n] : blt::enumerate(array.get_map()))
|
||||||
{
|
{
|
||||||
if (i == v0_idx)
|
if (i == v0_idx)
|
||||||
continue;
|
continue;
|
||||||
auto dist = basis_func->call(neuron_t::distance(dist_func, v0, n), time_ratio * scale);
|
auto dist = topology_function->call(neuron_t::distance(dist_func, v0, n), time_ratio * scale);
|
||||||
n.update(current_data.bins, dist, eta);
|
n.update(current_data.bins, dist, eta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
current_epoch++;
|
current_epoch++;
|
||||||
|
topological_errors.push_back(topological_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
blt::size_t som_t::get_closest_neuron(const std::vector<Scalar>& data)
|
blt::size_t som_t::get_closest_neuron(const std::vector<Scalar>& data)
|
||||||
|
@ -139,12 +141,12 @@ namespace assign3
|
||||||
return (dp1 * p_1) + (dp2 * p_2) + (dp3 * p_3);
|
return (dp1 * p_1) + (dp2 * p_2) + (dp3 * p_3);
|
||||||
}
|
}
|
||||||
|
|
||||||
Scalar som_t::topological_error(const data_file_t& data)
|
Scalar som_t::topological_error()
|
||||||
{
|
{
|
||||||
Scalar total = 0;
|
Scalar total = 0;
|
||||||
std::vector<std::pair<blt::size_t, Scalar>> distances;
|
std::vector<std::pair<blt::size_t, Scalar>> distances;
|
||||||
|
|
||||||
for (const auto& x : data.data_points)
|
for (const auto& x : file.data_points)
|
||||||
{
|
{
|
||||||
distances.clear();
|
distances.clear();
|
||||||
for (const auto& [i, n] : blt::enumerate(array.get_map()))
|
for (const auto& [i, n] : blt::enumerate(array.get_map()))
|
||||||
|
@ -171,7 +173,53 @@ namespace assign3
|
||||||
total += 1;
|
total += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return total / static_cast<Scalar>(data.data_points.size());
|
return total / static_cast<Scalar>(file.data_points.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void som_t::compute_neuron_activations(Scalar distance, Scalar activation)
|
||||||
|
{
|
||||||
|
for (auto& n : array.get_map())
|
||||||
|
n.set_activation(0);
|
||||||
|
|
||||||
|
Scalar min = std::numeric_limits<Scalar>::max();
|
||||||
|
Scalar max = std::numeric_limits<Scalar>::min();
|
||||||
|
|
||||||
|
for (auto [i, v] : blt::enumerate(array.get_map()))
|
||||||
|
{
|
||||||
|
auto half = find_closest_neighbour_distance(i) / distance;
|
||||||
|
// auto sigma = std::sqrt(-(half * half) / (2 * std::log(requested_activation)));
|
||||||
|
// auto r = 1 / (2 * sigma * sigma);
|
||||||
|
//
|
||||||
|
auto scale = topology_function->scale(half, activation);
|
||||||
|
for (const auto& data : file.data_points)
|
||||||
|
{
|
||||||
|
auto ds = topology_function->call(v.dist(data.bins), scale);
|
||||||
|
if (data.is_bad)
|
||||||
|
v.activate(-ds);
|
||||||
|
else
|
||||||
|
v.activate(ds);
|
||||||
|
}
|
||||||
|
|
||||||
|
min = std::min(min, v.get_activation());
|
||||||
|
max = std::max(max, v.get_activation());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& n : array.get_map())
|
||||||
|
n.set_activation(2 * (n.get_activation() - min) / (max - min) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void som_t::write_activations(std::ostream& out)
|
||||||
|
{
|
||||||
|
out << "x,y,activation\n";
|
||||||
|
for (const auto& v : array.get_map())
|
||||||
|
out << v.get_x() << ',' << v.get_y() << ',' << v.get_activation() << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
void som_t::write_topology_errors(std::ostream& out)
|
||||||
|
{
|
||||||
|
out << "epoch,error\n";
|
||||||
|
for (auto [i, v] : blt::enumerate(topological_errors))
|
||||||
|
out << i << ',' << v << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue