def perfect_features_test():
    from src.env.Amatrix_task import Amatrix

    n = 50
    m = 3
    env = Amatrix(n, m)

    features = env.Amatrix  # perfect features
    weights = np.zeros(n)

    config = Config()
    config.parameter_size = n
    config.ini_stepsize = 0.01
    autostep = AutoStep(config)

    sample_size = 100000
    for i in range(sample_size):
        rand_row = np.random.randint(n)
        target = env.sample_target(rand_row, noisy=True)

        pred_features = features[rand_row, :]
        prediction = np.dot(pred_features, weights)
        error = target - prediction
        gradient, new_stepsize, new_weight_vector = autostep.update_weight_vector(error, pred_features, weights)
        weights = new_weight_vector
        if (i+1) % 10000 ==0:
            print("Sample number: {0}".format(i+1))
            print("\tPrediction error:{0}".format(error))

    print("Theta star:\n{0}".format(env.theta_star))
    print("Estimated theta:\n{0}".format(weights))
    difference = np.sqrt(np.sum(np.square(env.theta_star - weights)))
    print("L2 norm of difference:\n{0}".format(difference))
def imperfect_features_test():
    from src.env.Amatrix_task import Amatrix

    n = 10
    m = 2
    env = Amatrix(n, m)

    features = env.get_approx_A()   # first m features
    weights = np.zeros(m)

    config = Config()
    config.parameter_size = m
    config.ini_stepsize = 0.1
    autostep = AutoStep(config)

    sample_size = 50000
    for i in range(sample_size):
        rand_row = np.random.randint(n)
        target = env.sample_target(rand_row, noisy=True)

        pred_features = features[rand_row, :]
        prediction = np.dot(pred_features, weights)
        error = target - prediction
        gradient, new_stepsize, new_weight_vector = autostep.update_weight_vector(error, pred_features, weights)
        weights = new_weight_vector
        print("Sample number: {0}".format(i + 1))
        print("\tPrediction error:{0}".format(error))

    print("Theta star:\n{0}".format(env.theta_star))
    print("Estimated theta:\n{0}".format(weights))
def adding_good_features_test():
    from src.env.Amatrix_task import Amatrix

    n = 10
    m = 2
    env = Amatrix(n, m)

    features = env.get_approx_A()   # first m features
    weights = np.zeros(m)

    config = Config()
    config.parameter_size = m
    config.ini_stepsize = 0.1
    autostep = AutoStep(config)

    sample_size = 10000
    additional_features = 8
    for k in range(additional_features + 1):
        print("Number of features in the representation: {0}".format(autostep.parameter_size))
        for i in range(sample_size):
            rand_row = np.random.randint(n)
            target = env.sample_target(rand_row, noisy=True)

            pred_features = features[rand_row, :]
            prediction = np.dot(pred_features, weights)
            error = target - prediction
            gradient, new_stepsize, new_weight_vector = autostep.update_weight_vector(error, pred_features, weights)
            weights = new_weight_vector
            if ((i+1) % 100) == 0:
                print("\tSample number: {0}".format(i + 1))
                print("\t\tPrediction error:{0}".format(error))

        print("Theta star:\n{0}".format(env.theta_star))
        print("Estimated theta:\n{0}".format(weights))

        if autostep.parameter_size < n:
            print("Adding new feature...")
            new_feature = env.get_new_good_features(1)
            features = np.hstack((features, new_feature))
            autostep.increase_size(1)

            new_weights = np.zeros(m+1)
            new_weights[:m] = weights
            m += 1
            weights = new_weights