diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..5256d23 --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -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 \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index 07c22c4..acc9dd9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,7 +6,6 @@ GEM logger (1.7.0) multi_json (1.21.1) mustermann (3.1.1) - nio4r (2.7.5) nokogiri (1.19.3-aarch64-linux-gnu) racc (~> 1.4) nokogiri (1.19.3-aarch64-linux-musl) @@ -23,8 +22,6 @@ GEM racc (~> 1.4) nokogiri (1.19.3-x86_64-linux-musl) racc (~> 1.4) - puma (8.0.1) - nio4r (~> 2.0) racc (1.8.1) rack (3.2.6) rack-protection (4.2.1) @@ -60,6 +57,7 @@ GEM sinatra (= 4.2.1) tilt (~> 2.0) tilt (2.7.0) + webrick (1.9.2) PLATFORMS aarch64-linux-gnu @@ -72,12 +70,12 @@ PLATFORMS x86_64-linux-musl DEPENDENCIES - puma rackup roo rubyXL sinatra sinatra-contrib + webrick BUNDLED WITH 2.5.3 diff --git a/app.rb b/app.rb index c7bb231..107af7e 100644 --- a/app.rb +++ b/app.rb @@ -4,6 +4,7 @@ require_relative 'loader' require_relative 'functions' require_relative 'hopfield' require_relative 'hamming' +require_relative 'trace' EPS = 0.01 @@ -50,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 @@ -64,6 +65,44 @@ post '/recall_steps' do }.to_json end +post '/recall_trace' do + content_type :json + noisy = JSON.parse(request.body.read)['vector'].map(&:to_f) + + hopfield_steps = [noisy.map(&:to_i)] + hopfield_nets = [] + current = noisy.dup + MAX_HOPFIELD_ITER.times do + net = trace_hopfield_step(WEIGHTS, current) + nxt = net.map { |v| v >= 0 ? 1 : -1 } + changed = current.each_with_index.count { |v, i| v.to_i != nxt[i] } + hopfield_nets << { net: net.map { |v| v.round(3) }, changed: changed } + hopfield_steps << nxt + break if vectors_equal?(current, nxt) + current = nxt + end + + eps_val = 0.9 / PATTERN_VECTORS.length + outputs = hamming_layer(PATTERN_VECTORS, noisy) + hamming_steps = [outputs.map { |v| v.round(2) }] + 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 > 1e-9 } <= 1 + outputs = nxt + end + winner_idx = outputs.each_with_index.max_by { |v, _| v }[1] + + { + hopfield_steps: hopfield_steps, + hopfield_nets: hopfield_nets, + hamming_steps: hamming_steps, + pattern_names: PATTERN_NAMES, + hamming_winner: PATTERN_NAMES[winner_idx], + hamming_trace: hamming_trace(PATTERN_VECTORS, noisy) + }.to_json +end + post '/recall' do content_type :json noisy = JSON.parse(request.body.read)['vector'].map(&:to_f) diff --git a/hamming.rb b/hamming.rb index 18544ff..1545e3d 100644 --- a/hamming.rb +++ b/hamming.rb @@ -13,7 +13,7 @@ def maxnet_step(outputs, eps) end end -MAX_MAXNET_ITER = 500 +MAX_MAXNET_ITER = 100 def recall_hamming(pattern_vectors, input_vec) eps = 0.9 / pattern_vectors.length @@ -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 diff --git a/loader.rb b/loader.rb index 045e88e..da71b29 100644 --- a/loader.rb +++ b/loader.rb @@ -1,4 +1,6 @@ require 'roo' +require 'zip' +Zip.warn_invalid_date = false def load_patterns(file) xlsx = Roo::Spreadsheet.open(file) diff --git a/trace.rb b/trace.rb new file mode 100644 index 0000000..43e356f --- /dev/null +++ b/trace.rb @@ -0,0 +1,18 @@ +def trace_hopfield_step(weights, vector) + n = vector.length + Array.new(n) { |i| n.times.sum { |j| weights[i][j] * vector[j] } } +end + +def hamming_trace(pattern_vectors, input_vec) + n = input_vec.length + k = pattern_vectors.length + dots = pattern_vectors.map { |pv| pv.zip(input_vec).sum { |a, b| a * b } } + initial = dots.map { |dot| (dot.to_f + n) / 2.0 } + { + eps: (0.9 / k).round(6), + k: k, + n: n, + dot_products: dots, + initial_outputs: initial.map { |v| v.round(2) } + } +end diff --git a/views/index.erb b/views/index.erb index 238a580..f1e0311 100644 --- a/views/index.erb +++ b/views/index.erb @@ -3,6 +3,8 @@