Files
lr_miad_nn/app.rb
T

118 lines
3.3 KiB
Ruby

require 'sinatra'
require 'json'
require_relative 'loader'
require_relative 'functions'
require_relative 'hopfield'
require_relative 'hamming'
require_relative 'trace'
EPS = 0.01
set :bind, '0.0.0.0'
set :port, 4567
set :server, 'webrick'
disable :protection
set :host_authorization, { allow_if: ->(_env) { true } }
PATTERNS = load_patterns('patterns.xlsx')
PATTERN_VECTORS = PATTERNS.map { |_, m| to_vector(m) }
PATTERN_NAMES = PATTERNS.keys.map(&:to_s)
WEIGHTS = load_weights_cache('patterns.xlsx') || begin
puts 'Обучение модели...'
w = train_hopfield(PATTERN_VECTORS)
save_weights_cache(w, 'patterns.xlsx')
puts 'Веса сохранены в кэш.'
w
end
get '/' do
@patterns = PATTERNS.transform_values { |m| to_vector(m) }
erb :index
end
post '/recall_steps' do
content_type :json
noisy = JSON.parse(request.body.read)['vector'].map(&:to_f)
# Хопфилд: собираем каждый шаг
hopfield_steps = [noisy.map { |v| v.to_i }]
current = noisy.dup
MAX_HOPFIELD_ITER.times do
nxt = step_hopfield(WEIGHTS, current)
hopfield_steps << nxt
break if vectors_equal?(current, nxt)
current = nxt
end
# Хэмминг: собираем состояния MAXNET
eps = 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)
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,
hamming_steps: hamming_steps,
pattern_names: PATTERN_NAMES,
hamming_winner: PATTERN_NAMES[winner_idx]
}.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)
hopfield_result = recall_hopfield(WEIGHTS, noisy)
hamming_idx = recall_hamming(PATTERN_VECTORS, noisy)
{
hopfield: hopfield_result,
hamming: PATTERN_NAMES[hamming_idx]
}.to_json
end