results = performance(np.array([1,1]), a)

"""
Explanation: Reconstructions in the two bit system

I would expect (and hope) for all possible hidden configurations when the visible in in state [1,1] the reconstructions produced would be either v_a = [1,0] v_b = [0,1] or visa versa.
End of explanation
"""


def plot_avg_results_for_visible_pattern(v, sampler):
    results = performance(v, sampler)
    
    avgd_results = {}
    for key in results:
        results[key]
        for inner_key in results[key]:
            if inner_key not in avgd_results:
                avgd_results[inner_key] = results[key][inner_key]
            else:
                avgd_results[inner_key] += results[key][inner_key]
                
    keys = []
    vals = []
    for key in avgd_results:
        keys.append(key)
        vals.append(avgd_results[key])

    plt.title("Avg reconstruction given v:{}".format(v))
    plt.bar(range(len(vals)), vals, align='center')
    plt.xticks(range(len(keys)), keys, rotation='vertical')
    plt.show()
    
def plot_avg_results_for_hidden_pattern(h_a, h_b, v, sampler):
    results = {}
    base_key = "v_a{} v_b{}"
    for count in range(100):
        v_a, v_b = sampler.v_to_v(h_a, h_b, v, num_gibbs= 1000)
        inner_key = base_key.format(v_a, v_b)
        if inner_key not in results:
            results[inner_key] = 1
        else:
            results[inner_key] = results[inner_key] + 1
    
    avgd_results = {}
    for inner_key in results:
        if inner_key not in avgd_results:
            avgd_results[inner_key] = results[inner_key]
        else:
            avgd_results[inner_key] += results[inner_key]

    keys = []
    vals = []
    for key in avgd_results:
        keys.append(key)
        vals.append(avgd_results[key])

    plt.title("Avg reconstruction given v:{}".format(v))
    plt.bar(range(len(vals)), vals, align='center')
    plt.xticks(range(len(keys)), keys, rotation='vertical')
    plt.show()


plot_avg_results_for_visible_pattern(np.array([1,1]), a)
plot_avg_results_for_visible_pattern(np.array([1,1]), WrappedVanillaSampler(dot))

"""
Explanation: Excellent!##
In all case it falls into a stable visible configuration and successfully separates the visibles.
End of explanation
"""


plot_avg_results_for_visible_pattern(np.array([1,0]), a)
plot_avg_results_for_visible_pattern(np.array([0,1]), a)

plot_avg_results_for_visible_pattern(np.array([1,0]), WrappedVanillaSampler(dot))
plot_avg_results_for_visible_pattern(np.array([0,1]), WrappedVanillaSampler(dot))

"""
Explanation: Yussssssssss
This is perfect, over all cases for the visible pattern it can separate it. Creating excellent reconstructions the majority of the time. We already know the vanilla RBM will fail to do this. Still i graphed the output of on of the visible reconstructions of the vanilla.
End of explanation
"""


training_set = np.eye(2)
dot = RBM(3,2,1)
s = VanillaSampler(dot)
t = VanillaTrainier(dot, s)
t.train(10000, training_set)
h_a = np.array([1,0,0])
h_b = np.array([0,1,0])
v = np.array([1,1])
plot_avg_results_for_hidden_pattern(h_a, h_b,np.array([1,1]) , ApproximatedSampler(dot.weights,dot.weights,0,0))
plot_avg_results_for_hidden_pattern(h_a, h_b,np.array([1,0]) , ApproximatedSampler(dot.weights,dot.weights,0,0))
plot_avg_results_for_hidden_pattern(h_a, h_b,np.array([0,1]) , ApproximatedSampler(dot.weights,dot.weights,0,0))
plot_avg_results_for_hidden_pattern(h_a, h_b,np.array([0,0]) , ApproximatedSampler(dot.weights,dot.weights,0,0))

training_set = np.eye(3)

dot = RBM(2,3,1)
s = VanillaSampler(dot)
t = VanillaTrainier(dot, s)
t.train(10000, training_set)


plot_avg_results_for_visible_pattern(np.array([1,1]), a)
plot_avg_results_for_visible_pattern(np.array([1,1]), WrappedVanillaSampler(dot))

"""
Explanation: Below
In this cell below I check the code still holds together given more hidden nodes. Than visibles. It does.
End of explanation
"""


