def read_FDIST():
    """
    Reads F and DIST data from the files, and combines them to make F_DIST,
    which gets weighed in the network. Helper to read_data_set().

    Returns:
        torch.Tensor -- F_DIST (combined F and DIST information ready)
    """
    global num_features, is_avi, not_avi_idx, J_avi

    F, is_avi = ad.read_F_file(
        RAND_DATA_FILES['F'] if args.rand else ORIG_DATA_FILES['F'], J
    )
    DIST = ad.read_dist_file(
        RAND_DATA_FILES['DIST'] if args.rand else ORIG_DATA_FILES['DIST'], J
    )

    # process data for the network
    F = ad.normalize(F, along_dim=0, using_max=True)
    DIST = ad.normalize(DIST, using_max=True)
    not_avi_idx = np.nonzero(is_avi - 1)[0]  # Indices of where is_avi is zero

    # combine f and D for the NN
    num_features = len(F[0]) + 1    # extra 1 for the distance element in F_DIST
    J_avi = int(sum(is_avi))
    F_DIST = torch.from_numpy(ad.combine_DIST_F(F, DIST, J, num_features))
    is_avi = torch.from_numpy(is_avi)
    not_avi_idx = torch.from_numpy(not_avi_idx)
    num_features += 1   # extra 1 for reward, that is added later

    return F_DIST
def make_rand_data(X_max=100.0, R_max=100.0):
    """
    Creates random X and R and calculates Y based on random weights. Also
    stores the weights in files before returning.

    Args:
        X_max -- (float) Maximum value of element in X dataset (default=100.0)
        R_max -- (float) Maximum value of element in R dataset (default=100.0)

    Returns:
        3-tuple -- (X, Y, R) (values are normalized)
    """
    global F_DIST, eta_matrix

    # create random X and R and w
    origX = np.floor(np.random.rand(T, J) * X_max).astype(np.float32)
    origR = np.floor(np.random.rand(T, J) * R_max).astype(np.float32)

    # all but last set of weights
    w = [
        torch.randn(J, num_features, num_features)
        for _ in range(N_WEIGHTS - 1)
    ]
    w.append(torch.randn(J, num_features, 1))

    # convert to pytorch tensors, create placeholder for Y
    X = torch.from_numpy(ad.normalize(origX, along_dim=1, using_max=False))
    Y = torch.empty(T, J)
    R = torch.from_numpy(ad.normalize(origR, along_dim=0, using_max=False))
    eta_matrix = args.eta * torch.eye(J)

    if args.cuda:
        # transfer to GPU
        X, Y, R, F_DIST = X.cuda(), Y.cuda(), R.cuda(), F_DIST.cuda()
        w = list(map(lambda wi: wi.cuda(), w))
        eta_matrix = eta_matrix.cuda()

    # build Y
    for t in range(T):
        # build the input by appending testR[t]
        inp = build_input(R[t])
        if args.cuda:
            inp = inp.cuda()

        P = feed_forward(w, inp).t()

        # calculate Y
        Y[t] = P.mv(X[t])

    w[-1].data = w[-1].data.view(
        -1, num_features)  # remove the extra dim in last wi
    save_weights(os.path.splitext(RAND_DATA_FILES['XYR_weights'])[0],
                 w)  # for later verification
    return (X.data.cpu().numpy(), Y.data.cpu().numpy(), R.data.cpu().numpy())
def read_FDIST():
    """
    Reads F and DIST data from the files, and combines them to make F_DIST,
    which gets weighed in the network. Helper to read_data_set().
    """
    global F_DIST, num_features, is_avi

    F, is_avi = ad.read_F_file(
        RAND_DATA_FILES['F'] if args.rand else ORIG_DATA_FILES['F'], J)
    DIST = ad.read_dist_file(
        RAND_DATA_FILES['DIST'] if args.rand else ORIG_DATA_FILES['DIST'], J)

    # process data for the network
    F = ad.normalize(F, along_dim=0, using_max=True)
    DIST = ad.normalize(DIST, using_max=True)

    num_features = len(F[0]) + 1  # extra 1 for the distance element in F_DIST
    F_DIST = torch.from_numpy(ad.combine_DIST_F(F, DIST, J, num_features))
    num_features += 1  # extra 1 for reward, that is added later
def read_X():
    """
    Reads X data from files. Helper to read_data_set().
    """
    global X

    X, _, _ = ad.read_XYR_file(
        RAND_DATA_FILES['XYR'] if args.rand else ORIG_DATA_FILES['XYR'], J, T
    )

    # condense X along T into a single vector and normalize
    X = ad.normalize(X.sum(axis=0), using_max=False)

    X = torch.from_numpy(X)
def read_XYR():
    """
    Reads X, Y, R data from the files, and splits them into train and test sets
    as pytorch tensors, after reordering them etc. Helper to read_data_set().
    """
    global data_set

    tmp = {'X': [], 'Y': [], 'R': [], 'u': []}
    if args.rand:
        if not os.path.isfile(RAND_DATA_FILES['XYR']):
            # file doesn't exist, make random data, write to file
            X, Y, R = make_rand_data()
            ad.save_rand_XYR(RAND_DATA_FILES['XYR'], X, Y, R, J, T)

    tmp['X'], tmp['Y'], tmp['R'] = ad.read_XYR_file(
        RAND_DATA_FILES['XYR'] if args.rand else ORIG_DATA_FILES['XYR'], J, T)

    # u weights for differently weighing locations when calculating losses
    tmp['u'] = np.sum(tmp['Y'], axis=1)

    # normalize X, Y, R using sum along rows
    for k in ('X', 'Y'):  # R not normalized
        tmp[k] = ad.normalize(tmp[k], along_dim=1, using_max=False)

    # split XYR data into train, validation, and test sets
    # shuffle the data
    shuffle_order = np.random.permutation(T)
    tmp = {k: v[shuffle_order] for k, v in tmp.items()}

    # split the data
    for k, mat in tmp.items():
        data_set['train'][k], data_set['valid'][k], data_set['test'][
            k] = np.split(mat, [NUM_TRAIN, NUM_TRAIN + NUM_VALID], axis=0)
        for data_t in data_set:
            # change these np arrays to pytorch tensors
            data_set[data_t][k] = torch.from_numpy(data_set[data_t][k])
        w['except_first'] = [wi.cuda() for wi in w['except_first']]
        is_avi = is_avi.cuda()
        not_avi_idx = not_avi_idx.cuda()
        eta_matrix = eta_matrix.cuda()
        file_pre_gpu = "gpu, "
    else:
        file_pre_gpu = "cpu, "
    transfer_time = time.time() - transfer_time
    total_time = transfer_time

    if args.test:
        # secondary function of the script -- calculate loss value for the
        # supplied data
        rewards = np.loadtxt(args.test, delimiter=" ", dtype=NP_DTYPE)[:J]
        R_TOTAL = float(np.sum(rewards))
        rewards = torch.from_numpy(ad.normalize(rewards, using_max=False))
        if args.cuda:
            rewards = rewards.cuda()
        net.R.data = rewards        # substitute manual rewards
        forward_time = go_forward(net)
        # save results
        fname = 'testing "' + args.test[args.test.rfind("/") + 1:] + '" ' + str(time.time())
        save_log("./stats/find_rewards/test_rewards_results/" + fname,
                 loss.data, l2_loss.data, forward_time)
        sys.exit(0)

    # optimizer = optim.SGD(net.parameters(), lr=args.lr, momentum=args.momentum)
    optimizer = optim.Adam(net.parameters(), lr=args.lr)

    # refer to the report and Algorithm for Pricing Problem to understand the
    # logic flow: forward -> loop [backpropagate -> update -> constrain -> forward]