Compare commits

...

21 Commits
v13.5 ... main

Author SHA1 Message Date
Brett 4420d537aa silly 2024-10-07 22:07:02 -04:00
Brett b58bb4c695 more silly 2024-10-07 19:29:03 -04:00
Brett 1a8f828975 stats 2024-10-07 16:28:39 -04:00
Brett e3ef31ffc2 silly 2024-10-07 02:06:15 -04:00
Brett 8921671966 working output 2024-10-05 18:17:47 -04:00
Brett 9c4314e4d7 meow 2024-10-04 18:03:30 -04:00
Brett 573c3d7e43 hello! 2024-10-04 13:56:04 -04:00
Brett a713ea1778 working on refactor 2024-10-03 19:56:11 -04:00
Brett 6a06c17b10 Merge remote-tracking branch 'refs/remotes/origin/main' 2024-10-01 14:45:56 -04:00
Brett 3326551353 enable s 2024-10-01 14:45:24 -04:00
Brett 6543129c80 silly 2024-09-28 16:50:44 -04:00
Brett ac7e44ec18 i am in hell 2024-09-27 18:17:57 -04:00
Brett 25f6348323 silly 2024-09-27 15:12:28 -04:00
Brett 31b91e2a1c test minor merge again 2024-09-27 13:56:47 -04:00
Brett 5a541c50c4 test patch merge 2024-09-27 13:56:35 -04:00
Brett dd92b2bbcc test minor merge 2024-09-27 13:56:25 -04:00
Brett 89c98c5196 testing major release 2024-09-27 13:52:05 -04:00
Brett 6992be4e56 moving minor branch 2024-09-27 13:51:54 -04:00
Brett de0c52cfe0 test patch branch merge gain 2024-09-27 13:51:25 -04:00
Brett a069e33c59 testing patch merge to branch 2024-09-27 13:50:41 -04:00
Brett 7e50ac4f06 testing disable release 2024-09-27 13:16:59 -04:00
7 changed files with 769 additions and 204 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25)
project(COSC-4P80-Assignment-1 VERSION 13.5.0)
project(COSC-4P80-Assignment-1 VERSION 0.0.24)
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)

4
build.sh Normal file
View File

@ -0,0 +1,4 @@
#!/bin/sh
mkdir build
cmake -DCMAKE_BUILD_TYPE=Release -S ./ -B ./build
cmake --build ./build -j 32

View File

@ -56,6 +56,8 @@ class Config:
j = json.load(f)
obj = Config()
[setattr(obj, key, val) for key, val in j.items() if hasattr(obj, key)]
if obj.branch_on_minor:
obj.branch_on_major = True
return obj
def from_file(file):
@ -169,6 +171,12 @@ def make_branch(config: Config, name):
subprocess.call(["git", "checkout", "-b", name])
subprocess.call(["git", "merge", config.main_branch])
subprocess.call(["git", "checkout", config.main_branch])
def sync_branch(config: Config, version_parts, args):
if config.branch_on_major:
# Branch will be created.
if args.minor:
return;
def make_release(env: EnvData, name):
print(f"Making new release {name}")
@ -269,20 +277,39 @@ def main():
cmake_text = load_cmake()
version_parts = split_version(cmake_text)[0]
if not args.no_branch and args.major:
if args.major:
if config.branch_on_major:
make_branch(config, "v" + str(version_parts[0]))
if not args.no_branch and args.minor:
if not args.no_branch:
make_branch(config, "v" + str(version_parts[0]))
if args.minor:
if config.branch_on_minor:
make_branch(config, "v" + str(version_parts[0]) + "." + str(version_parts[1]))
if not args.no_branch:
make_branch(config, "v" + str(version_parts[0]) + "." + str(version_parts[1]))
elif config.branch_on_major:
subprocess.call(["git", "checkout", "v" + str(version_parts[0])])
subprocess.call(["git", "rebase", config.main_branch])
subprocess.call(["git", "checkout", config.main_branch])
if args.patch:
if config.branch_on_minor:
subprocess.call(["git", "checkout", "v" + str(version_parts[0]) + "." + str(version_parts[1])])
subprocess.call(["git", "rebase", config.main_branch])
subprocess.call(["git", "checkout", config.main_branch])
elif config.branch_on_major:
subprocess.call(["git", "checkout", "v" + str(version_parts[0])])
subprocess.call(["git", "rebase", config.main_branch])
subprocess.call(["git", "checkout", config.main_branch])
sync_branch(config=config, version_parts=version_parts, args=args)
subprocess.call(["sh", "-c", "git remote | xargs -L1 git push --all"])
if not args.no_release and args.major:
if config.release_on_major:
if args.major:
if not args.no_release and config.release_on_major:
make_release(env, "v" + str(version_parts[0]))
if not args.no_release and args.minor:
if config.release_on_minor:
if args.minor:
if not args.no_release and config.release_on_minor:
make_release(env, "v" + str(version_parts[0]) + "." + str(version_parts[1]))
if __name__ == "__main__":

View File

@ -22,14 +22,20 @@
#include <blt/std/logging.h>
#include <blt/math/matrix.h>
#include <blt/math/log_util.h>
#include <algorithm>
#include <numeric>
#include <vector>
namespace a1
{
template<blt::size_t rows, blt::size_t columns>
using matrix_t = blt::generalized_matrix<float, rows, columns>;
void test_math()
{
blt::generalized_matrix<float, 1, 4> input{1, -1, -1, 1};
blt::generalized_matrix<float, 1, 3> output{1, 1, 1};
blt::generalized_matrix<float, 4, 3> expected{
matrix_t<1, 4> input{1, -1, -1, 1};
matrix_t<1, 3> output{1, 1, 1};
matrix_t<4, 3> expected{
blt::vec4{1, -1, -1, 1},
blt::vec4{1, -1, -1, 1},
blt::vec4{1, -1, -1, 1}
@ -41,78 +47,46 @@ namespace a1
blt::vec4 one{5, 1, 3, 0};
blt::vec4 two{9, -5, -8, 3};
blt::generalized_matrix<float, 1, 4> g1{5, 1, 3, 0};
blt::generalized_matrix<float, 1, 4> g2{9, -5, -8, 3};
matrix_t<1, 4> g1{5, 1, 3, 0};
matrix_t<1, 4> g2{9, -5, -8, 3};
BLT_ASSERT(g1 * g2.transpose() == blt::vec4::dot(one, two) && "MATH DOT FAILURE");
}
template<typename input_t>
float crosstalk(const input_t& i, const input_t& j)
template<typename T, blt::u32 size>
struct vec_formatter
{
return i * j.transpose();
}
template<typename T, blt::u32 rows, blt::u32 columns>
blt::generalized_matrix<T, rows, columns> threshold(const blt::generalized_matrix<T, rows, columns>& y,
const blt::generalized_matrix<T, rows, columns>& base)
{
blt::generalized_matrix<T, rows, columns> result;
for (blt::u32 i = 0; i < columns; i++)
{
for (blt::u32 j = 0; j < rows; j++)
result[i][j] = y[i][j] > 1 ? 1 : (y[i][j] < -1 ? -1 : base[i][j]);
}
return result;
}
template<typename T, blt::size_t size>
blt::size_t difference(const std::array<T, size>& a, const std::array<T, size>& b)
{
blt::size_t count = 0;
for (const auto& [a_val, b_val] : blt::in_pairs(a, b))
{
if (a_val != b_val)
count++;
}
return count;
}
template<typename T, blt::size_t size>
bool equal(const std::array<T, size>& a, const std::array<T, size>& b)
{
return difference(a, b) == 0;
}
template<typename weight_t, typename input_t, typename output_t>
std::pair<input_t, output_t> run_step(const weight_t& associated_weights, const input_t& input, const output_t& output)
{
output_t output_recall = input * associated_weights;
input_t input_recall = output_recall * associated_weights.transpose();
// BLT_DEBUG_STREAM << "Input: " << input.vec_from_column_row() << "\nOutput: " << output.vec_from_column_row() << '\n';
// BLT_DEBUG_STREAM << "Recalled Input: " << a1::threshold(input_recall, input).vec_from_column_row() << "\nRecalled Output: "
// << a1::threshold(output_recall, output).vec_from_column_row() << '\n';
public:
explicit vec_formatter(const blt::vec<T, size>& data): data(data)
{}
template<typename Arr>
std::string format(const Arr& has_index_changed)
{
using namespace blt::logging;
std::string os;
for (auto [index, value] : blt::enumerate(data))
{
if (value >= 0)
os += ' ';
if (has_index_changed[index])
os += ansi::make_color(ansi::UNDERLINE);
os += blt::logging::to_string_stream(value);
if (has_index_changed[index])
os += ansi::make_color(ansi::RESET_UNDERLINE);
if (index != size - 1)
os += ", ";
}
return os;
}
return std::pair{a1::threshold(input_recall, input), a1::threshold(output_recall, output)};
}
private:
blt::vec<T, size> data;
};
template<typename weight_t, typename T, typename G, blt::size_t size>
void check_recall(const weight_t& weights, const std::array<G, size>& inputs, const std::array<T, size>& outputs)
{
for (const auto& [index, val] : blt::enumerate(inputs))
{
auto result = run_step(weights, val, outputs[index]);
if (result.first != val)
BLT_ERROR("Recall of input #%ld failed", index + 1);
else
BLT_INFO("Recall of input #%ld passed", index + 1);
if (result.second != outputs[index])
BLT_ERROR("Recall of output #%ld failed", index + 1);
else
BLT_INFO("recall of output #%ld passed", index + 1);
}
}
template<typename T, blt::u32 size>
vec_formatter(const blt::vec<T, size>& data) -> vec_formatter<T, size>;
}
#endif //COSC_4P80_ASSIGNMENT_1_A1_H

@ -1 +1 @@
Subproject commit 0d13e9738f6f666faec827940948337cef644aba
Subproject commit 3003e424e17a5c639a8b89d5c721c94c47f3402a

2
run.sh Normal file
View File

@ -0,0 +1,2 @@
#!/bin/sh
./build/COSC-4P80-Assignment-1

View File

@ -1,19 +1,512 @@
#include <iostream>
#include <utility>
#include <blt/math/matrix.h>
#include <blt/math/log_util.h>
#include "blt/std/assert.h"
#include <blt/std/assert.h>
#include <blt/std/random.h>
#include <blt/format/boxing.h>
#include <blt/std/iterator.h>
#include <blt/iterator/iterator.h>
#include <blt/parse/argparse.h>
#include <a1.h>
constexpr blt::u32 num_values = 4;
constexpr blt::u32 input_count = 5;
constexpr blt::u32 output_count = 4;
constexpr blt::u32 input_vec_size = 5;
constexpr blt::u32 output_vec_size = 4;
using input_t = blt::generalized_matrix<float, 1, input_count>;
using output_t = blt::generalized_matrix<float, 1, output_count>;
bool print_latex = false;
using input_t = a1::matrix_t<1, input_vec_size>;
using output_t = a1::matrix_t<1, output_vec_size>;
using weight_t = decltype(std::declval<input_t>().transpose() * std::declval<output_t>());
using crosstalk_t = blt::generalized_matrix<float, output_count, num_values>;
template<typename Os, typename T, blt::u32 size>
Os& print_vec_square(Os& o, const blt::vec<T, size>& v)
{
o << "[";
for (auto [i, f] : blt::enumerate(v))
{
o << f;
if (i != size - 1)
o << ", ";
}
o << "]";
return o;
}
struct correctness_t
{
blt::size_t correct_input = 0;
blt::size_t correct_output = 0;
blt::size_t incorrect_input = 0;
blt::size_t incorrect_output = 0;
};
class ping_pong
{
public:
ping_pong(weight_t weights, input_t input, output_t output): weights(std::move(weights)), input(std::move(input)), output(std::move(output))
{}
[[nodiscard]] ping_pong run_step_from_inputs() const
{
auto out = (input * weights);
return {weights, (out * weights.transpose()).bipolar(), out.bipolar()};
}
[[nodiscard]] ping_pong run_step_from_outputs() const
{
auto in = (output * weights.transpose());
return {weights, in.bipolar(), (in * weights).bipolar()};
}
[[nodiscard]] const input_t& get_input() const
{
return input;
}
[[nodiscard]] const output_t& get_output() const
{
return output;
}
friend bool operator==(const ping_pong& a, const ping_pong& b)
{
return a.input == b.input && a.output == b.output;
}
friend bool operator!=(const ping_pong& a, const ping_pong& b)
{
return a.input != b.input || a.output != b.output;
}
private:
weight_t weights;
input_t input;
output_t output;
};
class executor
{
public:
executor(const std::vector<input_t>& inputs, const std::vector<output_t>& outputs): weights(), inputs(inputs), outputs(outputs)
{
generate_weights();
}
void add_pattern(input_t input, output_t output)
{
inputs.push_back(std::move(input));
outputs.push_back(std::move(output));
}
void generate_weights()
{
for (auto [in, out] : blt::in_pairs(inputs, outputs))
weights += in.transpose() * out;
}
void print_weights() const
{
BLT_TRACE_STREAM << "Weight Matrix: \n" << weights << "\n";
}
[[nodiscard]] std::vector<output_t> crosstalk() const
{
std::vector<output_t> crosstalk_data;
crosstalk_data.resize(outputs.size());
std::cout << "\\begin{tabular}{||c|c|c|c|c||}\n\\hline\n";
for (auto [i, c] : blt::enumerate(crosstalk_data))
{
if (print_latex)
{
if (i == 0)
std::cout << "Input " << i + 1 << " & & Cos & Output Vector & Crosstalk Vector \\\\\n\\hline\\hline\n";
else
std::cout << "Input " << i + 1 << " & & & & \\\\\n\\hline\\hline\n";
}
for (auto [k, data] : blt::in_pairs(inputs, outputs).enumerate())
{
if (i == k)
continue;
auto [a, b] = data;
auto cos = a.normalize() * inputs[i].normalize().transpose();
auto this_talk = b * cos;
c += this_talk;
if (print_latex)
{
std::cout << "& Input " << k + 1 << " & " << cos << " & ";
print_vec_square(std::cout, b.vec_from_column_row());
std::cout << " & ";
print_vec_square(std::cout, this_talk.vec_from_column_row());
std::cout << "\\\\\n\\hline\n";
}
}
if (print_latex)
{
std::cout << "\\hline\n\\multicolumn{5}{|c|}{Total Vector: ";
print_vec_square(std::cout, c.vec_from_column_row());
std::cout << "}\\\\\n\\multicolumn{5}{|c|}{Total Crosstalk: " << c.magnitude() << "} \\\\\n\\hline\\hline\n";
}
}
std::cout << "\\end{tabular}\n";
return crosstalk_data;
}
void print_crosstalk() const
{
auto talk = crosstalk();
float total_talk = 0;
for (auto [i, c] : blt::enumerate(talk))
{
BLT_TRACE_STREAM << "Input " << i << " [" << inputs[i].vec_from_column_row() << "] has crosstalk magnitude: " << c.magnitude()
<< "\n";
total_talk += c.magnitude();
}
BLT_TRACE("Total Crosstalk: %f", total_talk);
}
void execute_input()
{
steps.clear();
std::vector<ping_pong> initial_pings;
initial_pings.reserve(inputs.size());
for (auto [input, output] : blt::in_pairs(inputs, outputs))
initial_pings.emplace_back(weights, input, output);
steps.emplace_back(std::move(initial_pings));
// execute while the entries don't equal each other (no stability in the system)
do
{
auto& prev = steps.rbegin()[0];
std::vector<ping_pong> next_pongs;
next_pongs.reserve(prev.size());
for (auto& ping : prev)
next_pongs.emplace_back(ping.run_step_from_inputs());
steps.emplace_back(std::move(next_pongs));
} while (steps.rbegin()[0] != steps.rbegin()[1]);
}
void execute_output()
{
steps.clear();
std::vector<ping_pong> initial_pings;
initial_pings.reserve(outputs.size());
for (auto [input, output] : blt::in_pairs(inputs, outputs))
initial_pings.emplace_back(weights, input, output);
steps.emplace_back(std::move(initial_pings));
// execute while the entries don't equal each other (no stability in the system)
do
{
auto& prev = steps.rbegin()[0];
std::vector<ping_pong> next_pongs;
next_pongs.reserve(prev.size());
for (auto& ping : prev)
next_pongs.emplace_back(ping.run_step_from_outputs());
steps.emplace_back(std::move(next_pongs));
} while (steps.rbegin()[0] != steps.rbegin()[1]);
}
[[nodiscard]] input_t correct(const input_t& v) const
{
// outputs here do not matter.
ping_pong current{weights, v, outputs.front()};
ping_pong next{weights, v, outputs.front()};
do
{
current = next;
next = current.run_step_from_inputs();
// run until stability
} while (current != next);
return next.get_input();
}
[[nodiscard]] correctness_t correctness() const
{
correctness_t results;
for (auto [i, data] : blt::zip(inputs, outputs, steps.back()).enumerate())
{
auto& [input_data, output_data, ping_ping] = data;
if (input_data == ping_ping.get_input())
results.correct_input++;
else
results.incorrect_input++;
if (output_data == ping_ping.get_output())
results.correct_output++;
else
results.incorrect_output++;
}
return results;
}
void print_correctness() const
{
auto data = correctness();
BLT_TRACE("Correct inputs %ld Incorrect inputs %ld | (%lf%%)", data.correct_input, data.incorrect_input,
static_cast<double>(data.correct_input * 100) / static_cast<double>(data.incorrect_input + data.correct_input));
BLT_TRACE("Correct outputs %ld Incorrect outputs %ld | (%lf%%)", data.correct_output, data.incorrect_output,
static_cast<double>(data.correct_output * 100) / static_cast<double>(data.incorrect_output + data.correct_output));
BLT_TRACE("Total correct %ld Total incorrect %ld | (%lf%%)", data.correct_input + data.correct_output,
data.incorrect_input + data.incorrect_output,
static_cast<double>(data.correct_input + data.correct_output) * 100 /
static_cast<double>(data.correct_input + data.correct_output + data.incorrect_input + data.incorrect_output));
}
void print_execution_results_latex_no_intermediates()
{
std::cout << "\\begin{longtable}{||";
for (blt::size_t i = 0; i < 4; i++)
std::cout << "c|";
std::cout << "|}\n\t\\hline\n";
std::cout << "\tType & Input Vectors & Result Vectors & Result\\\\\n\t\\hline\\hline\n";
std::vector<std::string> input_lines;
std::vector<std::string> output_lines;
input_lines.resize(inputs.size());
output_lines.resize(outputs.size());
for (auto [i, is] : blt::enumerate(input_lines))
(is += "Input ") += std::to_string(i + 1);
for (auto [i, os] : blt::enumerate(output_lines))
(os += "Output ") += std::to_string(i + 1);
for (const auto& [step_idx, step] : blt::enumerate(steps))
{
for (auto [idx, pong] : blt::enumerate(step))
{
if (!(step_idx == 0 || step_idx == steps.size()-1))
break;
auto& is = input_lines[idx];
auto& os = output_lines[idx];
is += " & ";
os += " & ";
std::stringstream stream;
print_vec_square(stream, pong.get_input().vec_from_column_row());
is += stream.str();
stream = {};
print_vec_square(stream, pong.get_output().vec_from_column_row());
os += stream.str();
}
}
auto result = steps.back();
for (auto [idx, ping] : blt::zip(result, inputs, outputs).enumerate())
{
auto [pong, input, output] = ping;
auto& is = input_lines[idx];
auto& os = output_lines[idx];
is += " & ";
os += " & ";
if (pong.get_input() == input)
is += "Correct";
else
is += "Incorrect";
if (pong.get_output() == output)
os += "Correct";
else
os += "Incorrect";
}
for (auto [is, os] : blt::in_pairs(input_lines, output_lines))
{
std::cout << '\t' << is << " \\\\\n\t\\hline\n";
std::cout << '\t' << os << " \\\\\n\t\\hline\n";
}
std::cout << "\t\\caption{}\n";
std::cout << "\t\\label{tbl:}\n";
std::cout << "\\end{longtable}\n";
}
void print_execution_results_latex()
{
std::cout << "\\begin{longtable}{||";
for (blt::size_t i = 0; i < steps.size() + 3; i++)
std::cout << "c|";
std::cout << "|}\n\t\\hline\n";
std::cout << "\tType & Input Vectors & \\multicolumn{" << steps.size() - 2
<< "}{|c|}{Intermediate Vectors} & Result Vectors & Result\\\\\n\t\\hline\\hline\n";
std::vector<std::string> input_lines;
std::vector<std::string> output_lines;
input_lines.resize(inputs.size());
output_lines.resize(outputs.size());
for (auto [i, is] : blt::enumerate(input_lines))
(is += "Input ") += std::to_string(i + 1);
for (auto [i, os] : blt::enumerate(output_lines))
(os += "Output ") += std::to_string(i + 1);
for (const auto& step : steps)
{
for (auto [idx, pong] : blt::enumerate(step))
{
auto& is = input_lines[idx];
auto& os = output_lines[idx];
is += " & ";
os += " & ";
std::stringstream stream;
print_vec_square(stream, pong.get_input().vec_from_column_row());
is += stream.str();
stream = {};
print_vec_square(stream, pong.get_output().vec_from_column_row());
os += stream.str();
}
}
auto result = steps.back();
for (auto [idx, ping] : blt::zip(result, inputs, outputs).enumerate())
{
auto [pong, input, output] = ping;
auto& is = input_lines[idx];
auto& os = output_lines[idx];
is += " & ";
os += " & ";
if (pong.get_input() == input)
is += "Correct";
else
is += "Incorrect";
if (pong.get_output() == output)
os += "Correct";
else
os += "Incorrect";
}
for (auto [is, os] : blt::in_pairs(input_lines, output_lines))
{
std::cout << '\t' << is << " \\\\\n\t\\hline\n";
std::cout << '\t' << os << " \\\\\n\t\\hline\n";
}
std::cout << "\t\\caption{}\n";
std::cout << "\t\\label{tbl:}\n";
std::cout << "\\end{longtable}\n";
}
void print_execution_results()
{
using namespace blt::logging;
std::vector<std::string> input_lines;
std::vector<std::string> output_lines;
input_lines.resize(inputs.size());
output_lines.resize(outputs.size());
BLT_ASSERT(input_lines.size() == output_lines.size());
for (auto [i, data] : blt::in_pairs(input_lines, output_lines).enumerate())
{
auto& [is, os] = data;
auto ping_ping = steps.back()[i];
auto& input_data = inputs[i];
auto& output_data = outputs[i];
((((is += input_data == ping_ping.get_input() ? ansi::make_color(ansi::GREEN) : ansi::make_color(
ansi::RED)) += "[Input ") += std::to_string(i)) += "]: ") += ansi::RESET;
((((os += output_data == ping_ping.get_output() ? ansi::make_color(ansi::GREEN) : ansi::make_color(
ansi::RED)) += "[Output ") += std::to_string(i)) += "]: ") += ansi::RESET;
}
for (auto [step_index, step_data] : blt::enumerate(steps))
{
for (auto [data_index, current_data] : blt::enumerate(step_data))
{
auto current_input = current_data.get_input().vec_from_column_row();
auto current_output = current_data.get_output().vec_from_column_row();
std::array<bool, decltype(current_input)::data_size> has_input_changed{};
std::array<bool, decltype(current_output)::data_size> has_output_changed{};
if (step_index > 0)
{
auto& previous_data = steps[step_index - 1][data_index];
auto previous_input = previous_data.get_input().vec_from_column_row();
auto previous_output = previous_data.get_output().vec_from_column_row();
for (auto [vec_index, data] : blt::zip(current_input, previous_input).enumerate())
has_input_changed[vec_index] = std::get<0>(data) != std::get<1>(data);
for (auto [vec_index, data] : blt::zip(current_output, previous_output).enumerate())
has_output_changed[vec_index] = std::get<0>(data) != std::get<1>(data);
}
auto& is = input_lines[data_index];
auto& os = output_lines[data_index];
((is += "Vec") += blt::logging::to_string_stream(decltype(current_input)::data_size)) += "(";
((os += "Vec") += blt::logging::to_string_stream(decltype(current_output)::data_size)) += "(";
is += a1::vec_formatter(current_input).format(has_input_changed);
os += a1::vec_formatter(current_output).format(has_output_changed);
is += ")";
os += ")";
auto diff_o = (static_cast<blt::i32>(decltype(current_input)::data_size)
- static_cast<blt::i32>(decltype(current_output)::data_size)) * 4;
auto diff_i = (static_cast<blt::i32>(decltype(current_output)::data_size)
- static_cast<blt::i32>(decltype(current_input)::data_size)) * 4;
for (blt::i32 j = 0; j < diff_i; j++)
is += ' ';
for (blt::i32 j = 0; j < diff_o; j++)
os += ' ';
if (step_index != steps.size() - 1)
{
is += " => ";
os += " => ";
} else
{
is += " || ";
os += " || ";
}
}
}
for (auto [index, ping_ping] : blt::enumerate(steps.back()))
{
auto& is = input_lines[index];
auto& os = output_lines[index];
auto& input_data = inputs[index];
auto& output_data = outputs[index];
if (input_data != ping_ping.get_input())
((is += ansi::make_color(ansi::RED)) += "[Failed]") += ansi::RESET;
else
((is += ansi::make_color(ansi::GREEN)) += "[Passed]") += ansi::RESET;
if (output_data != ping_ping.get_output())
((os += ansi::make_color(ansi::RED)) += "[Failed]") += ansi::RESET;
else
((os += ansi::make_color(ansi::GREEN)) += "[Passed]") += ansi::RESET;
}
BLT_TRACE("Changes between ping-pong steps are underlined.");
for (auto [is, os] : blt::in_pairs(input_lines, output_lines))
{
BLT_TRACE_STREAM << is << "\n";
BLT_TRACE_STREAM << os << "\n";
}
}
std::vector<ping_pong>& get_results()
{
return steps.back();
}
private:
weight_t weights;
std::vector<input_t> inputs;
std::vector<output_t> outputs;
std::vector<std::vector<ping_pong>> steps;
};
// part a
input_t input_1{-1, 1, 1, 1, -1};
@ -37,129 +530,194 @@ output_t output_5{1, 1, 1, 1};
output_t output_6{1, -1, -1, 1};
output_t output_7{1, 1, 1, -1};
const weight_t weight_1 = input_1.transpose() * output_1;
const weight_t weight_2 = input_2.transpose() * output_2;
const weight_t weight_3 = input_3.transpose() * output_3;
const weight_t weight_4 = input_4.transpose() * output_4;
const weight_t weight_5 = input_5.transpose() * output_5;
const weight_t weight_6 = input_6.transpose() * output_6;
const weight_t weight_7 = input_7.transpose() * output_7;
auto part_a_inputs = std::vector{input_1, input_2, input_3};
auto part_a_outputs = std::vector{output_1, output_2, output_3};
auto part_a_inputs = std::array{input_1, input_2, input_3};
auto part_a_outputs = std::array{output_1, output_2, output_3};
auto part_c_1_inputs = std::vector{input_1, input_2, input_3, input_4};
auto part_c_1_outputs = std::vector{output_1, output_2, output_3, output_4};
auto part_c_1_inputs = std::array{input_1, input_2, input_3, input_4};
auto part_c_1_outputs = std::array{output_1, output_2, output_3, output_4};
auto part_c_2_inputs = std::vector{input_1, input_2, input_3, input_4, input_5, input_6, input_7};
auto part_c_2_outputs = std::vector{output_1, output_2, output_3, output_4, output_5, output_6, output_7};
auto part_c_2_inputs = std::array{input_1, input_2, input_3, input_4, input_5, input_6, input_7};
auto part_c_2_outputs = std::array{output_1, output_2, output_3, output_4, output_5, output_6, output_7};
const auto weight_total_a = weight_1 + weight_2 + weight_3;
const auto weight_total_c = weight_total_a + weight_4;
const auto weight_total_c_2 = weight_total_c + weight_5 + weight_6 + weight_7;
crosstalk_t crosstalk_values{};
//template<typename Weights, typename Inputs, typename Outputs>
//void execute_BAM(const Weights& weights, const Inputs& input, const Outputs& output)
//{
// auto current_inputs = input;
// auto current_outputs = output;
// auto next_inputs = current_inputs;
// auto next_outputs = current_outputs;
// blt::size_t iterations = 0;
// constexpr blt::size_t max_iterations = 5;
//
// do
// {
// current_inputs = next_inputs;
// current_outputs = next_outputs;
// ++iterations;
// for (const auto& [index, val] : blt::enumerate(current_inputs))
// {
// auto next = a1::run_step(weights, val, current_outputs[index]);
// next_inputs[index] = next.first;
// next_outputs[index] = next.second;
// }
// // loop until no changes or we hit the iteration limit
// } while ((!a1::equal(current_inputs, next_inputs) || !a1::equal(current_outputs, next_outputs)) && iterations < max_iterations);
//
// BLT_DEBUG("Tracked after %ld iterations", iterations);
// a1::check_recall(weights, next_inputs, next_outputs);
//}
//
//void part_a()
//{
// blt::log_box_t box(BLT_TRACE_STREAM, "Part A", 8);
//
// execute_BAM(weight_total_a, part_a_inputs, part_a_outputs);
//}
//
//void part_b()
//{
// blt::log_box_t box(BLT_TRACE_STREAM, "Part B", 8);
// for (blt::u32 i = 0; i < num_values; i++)
// {
// blt::generalized_matrix<float, 1, output_count> accum;
// for (blt::u32 k = 0; k < num_values; k++)
// {
// if (i == k)
// continue;
// accum += (part_a_outputs[k] * a1::crosstalk(part_a_inputs[k].normalize(), part_a_inputs[i].normalize()));
// }
// crosstalk_values.assign_to_column_from_column_rows(accum, i);
// }
// for (blt::u32 i = 0; i < num_values; i++)
// {
// BLT_DEBUG_STREAM << crosstalk_values[i] << " Mag: " << crosstalk_values[i].magnitude() << "\n";
// }
//}
//
//void part_c()
//{
// blt::log_box_t box(BLT_TRACE_STREAM, "Part C", 8);
// execute_BAM(weight_total_c, part_c_1_inputs, part_c_1_outputs);
// BLT_TRACE("--- { Part C with 3 extra pairs } ---");
// execute_BAM(weight_total_c_2, part_c_2_inputs, part_c_2_outputs);
//}
int main()
void part_a()
{
blt::logging::setLogOutputFormat("\033[94m[${{TIME}}]${{RC}} \033[35m(${{FILE}}:${{LINE}})${{RC}} ${{LF}}${{CNR}}${{STR}}${{RC}}\n");
// a1::test_math();
blt::log_box_t box(BLT_TRACE_STREAM, "Part A", 8);
for (const auto& [index, value] : blt::enumerate(part_c_2_inputs))
BLT_TRACE_STREAM << index << " : " << value.vec_from_column_row() << '\n';
executor cute(part_a_inputs, part_a_outputs);
cute.print_weights();
std::cout << "\n";
BLT_TRACE("");
for (const auto& [index, value] : blt::enumerate(part_c_2_inputs).rev())
BLT_TRACE_STREAM << index << " : " << value.vec_from_column_row() << '\n';
BLT_TRACE("Running from inputs:");
cute.execute_input();
cute.print_execution_results();
cute.print_correctness();
if (print_latex)
cute.print_execution_results_latex();
BLT_TRACE("");
for (const auto& [index, value] : blt::enumerate(part_c_2_inputs).skip(3))
BLT_TRACE_STREAM << index << " : " << value.vec_from_column_row() << '\n';
BLT_TRACE("");
for (const auto& [index, value] : blt::enumerate(part_c_2_inputs).skip(3).rev())
BLT_TRACE_STREAM << index << " : " << value.vec_from_column_row() << '\n';
BLT_TRACE("");
for (const auto& [index, value] : blt::enumerate(part_c_2_inputs).rev().skip(3).rev())
BLT_TRACE_STREAM << index << " : " << value.vec_from_column_row() << '\n';
BLT_TRACE("");
for (const auto& [index, value] : blt::enumerate(part_c_2_inputs).skip(2).take(3))
BLT_TRACE_STREAM << index << " : " << value.vec_from_column_row() << '\n';
// BLT_TRACE("%s", blt::type_string<blt::meta::lowest_iterator_category<std::bidirectional_iterator_tag, std::random_access_iterator_tag, std::input_iterator_tag>::type>().c_str());
// part_a();
// part_b();
// part_c();
std::cout << "\n";
BLT_TRACE("Running from outputs:");
cute.execute_output();
cute.print_execution_results();
cute.print_correctness();
if (print_latex)
cute.print_execution_results_latex();
}
void part_b()
{
blt::log_box_t box(BLT_TRACE_STREAM, "Part B", 8);
executor cute(part_a_inputs, part_a_outputs);
cute.print_crosstalk();
// cute.print_crosstalk_table();
}
void part_c()
{
blt::log_box_t box(BLT_TRACE_STREAM, "Part C", 8);
executor cute(part_c_1_inputs, part_c_1_outputs);
cute.execute_input();
cute.print_execution_results();
cute.print_correctness();
cute.print_crosstalk();
if (print_latex)
cute.print_execution_results_latex_no_intermediates();
cute.execute_output();
cute.print_execution_results();
cute.print_correctness();
if (print_latex)
cute.print_execution_results_latex_no_intermediates();
BLT_TRACE("--- { Part C with 3 extra pairs } ---");
executor cute2(part_c_2_inputs, part_c_2_outputs);
cute2.execute_input();
cute2.print_execution_results();
cute2.print_correctness();
cute2.print_crosstalk();
if (print_latex)
cute2.print_execution_results_latex_no_intermediates();
cute2.execute_output();
cute2.print_execution_results();
cute2.print_correctness();
if (print_latex)
cute2.print_execution_results_latex_no_intermediates();
}
blt::size_t hdist(const input_t& a, const input_t& b)
{
blt::size_t diff = 0;
for (auto [av, bv] : blt::in_pairs(a.vec_from_column_row(), b.vec_from_column_row()))
diff += (av != bv ? 1 : 0);
return diff;
}
void part_d()
{
blt::log_box_t box(BLT_TRACE_STREAM, "Part D", 8);
blt::random::random_t random(std::random_device{}());
executor cute(part_a_inputs, part_a_outputs);
constexpr blt::size_t number_of_runs = 80;
std::vector<blt::size_t> mutations;
std::vector<blt::size_t> corrections;
blt::size_t total_corrections = 0;
blt::size_t total_mutations = 0;
blt::size_t min_corrections = std::numeric_limits<blt::size_t>::max();
blt::size_t max_corrections = 0;
blt::size_t min_mutations = std::numeric_limits<blt::size_t>::max();
blt::size_t max_mutations = 0;
for (blt::size_t run = 0; run < number_of_runs; run++)
{
auto pos = random.get_size_t(0, part_a_inputs.size());
auto original = part_a_inputs[pos];
auto modified = original;
for (blt::size_t i = 0; i < std::remove_reference_t<decltype(modified)>::data_columns; i++)
{
if (random.choice(0.2))
{
// flip value of this location
auto& d = modified[i][0];
if (d >= 0)
d = -1;
else
d = 1;
}
}
auto corrected = cute.correct(modified);
auto dist_o_m = hdist(original, modified);
auto dist_o_c = hdist(original, corrected);
corrections.push_back(dist_o_c);
mutations.push_back(dist_o_m);
total_corrections += dist_o_c;
total_mutations += dist_o_m;
min_corrections = std::min(dist_o_c, min_corrections);
max_corrections = std::max(dist_o_c, max_corrections);
min_mutations = std::min(dist_o_m, min_mutations);
max_mutations = std::max(dist_o_m, max_mutations);
if (print_latex)
{
std::cout << run + 1 << " & ";
print_vec_square(std::cout, original.vec_from_column_row()) << " & ";
print_vec_square(std::cout, modified.vec_from_column_row()) << " & ";
std::cout << dist_o_m << " & ";
print_vec_square(std::cout, corrected.vec_from_column_row()) << " & ";
std::cout << dist_o_c << " \\\\ \n\\hline\n";
} else
{
BLT_TRACE_STREAM << "Run " << run << " " << original.vec_from_column_row() << " || mutated " << modified.vec_from_column_row()
<< " difference: " << dist_o_m << " || corrected " << corrected.vec_from_column_row() << " || difference: " << dist_o_c
<< "\n";
}
}
double mean_corrections = static_cast<double>(total_corrections) / number_of_runs;
double mean_mutations = static_cast<double>(total_mutations) / number_of_runs;
double stddev_corrections = 0;
double stddev_mutations = 0;
for (const auto& v : corrections)
{
auto x = (static_cast<double>(v) - mean_corrections);
stddev_corrections += x * x;
}
for (const auto& v : mutations)
{
auto x = (static_cast<double>(v) - mean_mutations);
stddev_mutations += x * x;
}
stddev_corrections /= number_of_runs;
stddev_mutations /= number_of_runs;
stddev_corrections = std::sqrt(stddev_corrections);
stddev_mutations = std::sqrt(stddev_mutations);
std::cout << "Mean Distance Corrections: " << mean_corrections << " Stddev: " << stddev_corrections << " Min: " << min_corrections << " Max: "
<< max_corrections << '\n';
std::cout << "Mean Distance Mutations: " << mean_mutations << " Stddev: " << stddev_mutations << " Min: " << min_mutations << " Max: "
<< max_mutations << '\n';
}
int main(int argc, const char** argv)
{
blt::arg_parse parser;
parser.addArgument(blt::arg_builder{"--latex", "-l"}.setAction(blt::arg_action_t::STORE_TRUE).setDefault(false).build());
auto args = parser.parse_args(argc, argv);
print_latex = blt::arg_parse::get<bool>(args["latex"]);
blt::logging::setLogOutputFormat("\033[94m[${{TIME}}]${{RC}} \033[35m(${{FILE}}:${{LINE}})${{RC}} ${{LF}}${{CNR}}${{STR}}${{RC}}\n");
a1::test_math();
part_a();
part_b();
part_c();
part_d();
std::vector<input_t> test{input_t{1, -1, -1, -1, -1}, input_t{-1, 1, -1, -1, -1}, input_t{-1, -1, 1, -1, -1}};
executor cute{test, part_a_outputs};
cute.print_crosstalk();
}