WIP: Implement trace functionality for Hopfield and Hamming networks; update Gemfile.lock and app.rb for new dependencies and features #1

Closed
ada wants to merge 2 commits from feature/formulas into main
5 changed files with 49 additions and 20 deletions
Showing only changes of commit 8f85c0adbc - Show all commits
+21
View File
@@ -0,0 +1,21 @@
name: Build and Push
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Login to registry
run: |
echo "${{ secrets.REGISTRY_PASSWORD }}" | \
docker login git.ada-dev.ru -u ${{ secrets.REGISTRY_USER }} --password-stdin
- name: Build and push
run: |
docker build -t git.ada-dev.ru/ada/${{ gitea.repository }}:latest .
docker push git.ada-dev.ru/ada/${{ gitea.repository }}:latest
+3 -3
View File
@@ -9,7 +9,7 @@ require_relative 'trace'
EPS = 0.01
set :bind, '0.0.0.0'
set :port, 4568
set :port, 4567
set :server, 'webrick'
disable :protection
set :host_authorization, { allow_if: ->(_env) { true } }
@@ -51,7 +51,7 @@ post '/recall_steps' do
MAX_MAXNET_ITER.times do
nxt = maxnet_step(outputs, eps)
hamming_steps << nxt.map { |v| v.round(2) }
break if nxt.count { |v| v > 0 } <= 1
break if nxt.count { |v| v > 1e-9 } <= 1
outputs = nxt
end
@@ -88,7 +88,7 @@ post '/recall_trace' do
MAX_MAXNET_ITER.times do
nxt = maxnet_step(outputs, eps_val)
hamming_steps << nxt.map { |v| v.round(2) }
break if nxt.count { |v| v > 0 } <= 1
break if nxt.count { |v| v > 1e-9 } <= 1
outputs = nxt
end
winner_idx = outputs.each_with_index.max_by { |v, _| v }[1]
+1 -1
View File
@@ -21,7 +21,7 @@ def recall_hamming(pattern_vectors, input_vec)
outputs = hamming_layer(pattern_vectors, input_vec)
MAX_MAXNET_ITER.times do
next_out = maxnet_step(outputs, eps)
return next_out.each_with_index.max_by { |v, _| v }[1] if next_out.count { |v| v > 0 } <= 1
return next_out.each_with_index.max_by { |v, _| v }[1] if next_out.count { |v| v > 1e-9 } <= 1
outputs = next_out
end
+2
View File
@@ -1,4 +1,6 @@
require 'roo'
require 'zip'
Zip.warn_invalid_date = false
def load_patterns(file)
xlsx = Roo::Spreadsheet.open(file)
+22 -16
View File
@@ -401,20 +401,23 @@
const names = data.pattern_names;
const t = data.hamming_trace;
hfFormula(String.raw`\operatorname{net}_i = \sum_{j} W_{ij} \cdot x_j \qquad x_i = \operatorname{sgn}(\operatorname{net}_i)`);
hfFormula(String.raw`s_j(p{+}1) = \sum_{i=0}^{n-1} w_{ij}\,y_i(p)`);
hfFormula(String.raw`y_j(p{+}1) = f\!\left[s_j(p{+}1)\right], \quad f(s)=\begin{cases}1&s\geq0\\-1&s<0\end{cases}`);
data.hopfield_nets.forEach((nd, i) => {
const mark = nd.changed === 0 ? ' ← сошлось' : '';
hfLine(`шаг ${i + 1}: изменено ${nd.changed}/64${mark}`);
hfLine(`p=${i + 1}: изменено ${nd.changed}/64${mark}`);
});
hmFormula(String.raw`y_k = \frac{\mathbf{x} \cdot \mathbf{p}_k + n}{2}`);
hmFormula(String.raw`w_{ik} = \tfrac{x_i^k}{2}, \quad T_k = \tfrac{n}{2}`);
hmFormula(String.raw`y_j^{(1)} = \sum_{i=0}^{n-1} w_{ij}\,x_i + T_j`);
const layer = names.map((n, i) => `${n}\\!=\\!${t.initial_outputs[i]}`).join(',\\;');
hmFormula(String.raw`\text{слой: }\;` + layer);
hmFormula(String.raw`\varepsilon = \tfrac{0.9}{K} = \tfrac{0.9}{${t.k}} = ${t.eps}`);
hmFormula(String.raw`y_i(t{+}1) = \max\!\left(0,\; y_i(t) - \varepsilon\!\sum_{j \neq i} y_j(t)\right)`);
hmFormula(String.raw`y_j^{(2)}(0) = y_j^{(1)}:\;` + layer);
hmFormula(String.raw`0 < \varepsilon < \tfrac{1}{m},\quad \varepsilon = \tfrac{0.9}{${t.k}} = ${t.eps}`);
hmFormula(String.raw`s_j^{(2)}(p{+}1) = y_j^{(2)}(p) - \varepsilon\!\sum_{k \neq j} y_k^{(2)}(p)`);
hmFormula(String.raw`y_j^{(2)}(p{+}1) = f\!\left[s_j^{(2)}(p{+}1)\right]`);
data.hamming_steps.slice(1).forEach((step, i) => {
const vals = names.map((n, j) => `${n}\\!=\\!${step[j]}`).join(',\\;');
hmFormula(`\\text{iter ${i + 1}: }\\;` + vals);
hmFormula(`p=${i + 1}:\\; y^{(2)} = [\\;` + vals + `\\;]`);
});
hmFormula(String.raw`\Rightarrow \text{победитель: } \mathbf{` + data.hamming_winner + `}`);
}
@@ -496,7 +499,8 @@
if (showTrace) {
clearTrace();
document.getElementById('trace-panels').style.display = 'flex';
hfFormula(String.raw`\operatorname{net}_i = \sum_{j} W_{ij} \cdot x_j \qquad x_i = \operatorname{sgn}(\operatorname{net}_i)`);
hfFormula(String.raw`s_j(p{+}1) = \sum_{i=0}^{n-1} w_{ij}\,y_i(p)`);
hfFormula(String.raw`y_j(p{+}1) = f\!\left[s_j(p{+}1)\right], \quad f(s)=\begin{cases}1&s\geq0\\-1&s<0\end{cases}`);
}
renderBars(names, data.hamming_steps[0]);
@@ -513,7 +517,7 @@
if (showTrace && i > 0 && data.hopfield_nets[i - 1]) {
const nd = data.hopfield_nets[i - 1];
const mark = nd.changed === 0 ? ' ← сошлось' : '';
hfLine(`шаг ${i}: изменено ${nd.changed}/64${mark}`);
hfLine(`p=${i}: изменено ${nd.changed}/64${mark}`);
}
}
if (i < hmSteps.length) {
@@ -523,14 +527,16 @@
if (showTrace) {
const t = data.hamming_trace;
if (i === 0) {
hmFormula(String.raw`y_k = \frac{\mathbf{x} \cdot \mathbf{p}_k + n}{2}`);
hmFormula(String.raw`w_{ik} = \tfrac{x_i^k}{2}, \quad T_k = \tfrac{n}{2}`);
hmFormula(String.raw`y_j^{(1)} = \sum_{i=0}^{n-1} w_{ij}\,x_i + T_j`);
const layer = names.map((n, j) => `${n}\\!=\\!${t.initial_outputs[j]}`).join(',\\;');
hmFormula(String.raw`\text{слой: }\;` + layer);
hmFormula(String.raw`\varepsilon = \tfrac{0.9}{${t.k}} = ${t.eps}`);
hmFormula(String.raw`y_i(t{+}1) = \max\!\left(0,\; y_i(t) - \varepsilon\!\sum_{j \neq i} y_j(t)\right)`);
hmFormula(String.raw`y_j^{(2)}(0) = y_j^{(1)}:\;` + layer);
hmFormula(String.raw`0 < \varepsilon < \tfrac{1}{m},\quad \varepsilon = \tfrac{0.9}{${t.k}} = ${t.eps}`);
hmFormula(String.raw`s_j^{(2)}(p{+}1) = y_j^{(2)}(p) - \varepsilon\!\sum_{k \neq j} y_k^{(2)}(p)`);
hmFormula(String.raw`y_j^{(2)}(p{+}1) = f\!\left[s_j^{(2)}(p{+}1)\right]`);
} else {
const vals = names.map((n, j) => `${n}\\!=\\!${hmSteps[i][j]}`).join(',\\;');
hmFormula(`\\text{iter ${i}: }\\;` + vals);
hmFormula(`p=${i}:\\; y^{(2)} = [\\;` + vals + `\\;]`);
}
}
}
@@ -552,7 +558,7 @@
const hmLabel = document.getElementById('hamming-label');
hmLabel.textContent = `Ближайший эталон: ${data.hamming_winner}`;
hmLabel.className = 'status-label yes';
if (showTrace) hmFormula(String.raw`\Rightarrow \text{победитель: } \mathbf{` + data.hamming_winner + `}`);
if (showTrace) hmFormula(String.raw`\Rightarrow \text{победитель (}\,y_j^{(2)}\text{ max):}\;\mathbf{` + data.hamming_winner + `}`);
}
function showResult(data) {
@@ -618,5 +624,5 @@
</body>
<footer style="margin-top:3rem; font-size:0.75rem; color:#666; text-align:center;">
&copy; Develop by Antipenko D.A. for MIAD - 2026
&copy; Created by Antipenko D.A. for MIAD - 2026
</html>