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, 4568 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 > 0 } <= 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 > 0 } <= 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