Example #1
0
def test_networks(datasetname, statesonly, expanded, name, batchsize=20000):
    """
    Measure the accuracy and the legality of a triplet of networks
    
    Loads three networks and a dataset and than measure how accurate are the
    networks predictions with respect to the dataset and if their choices are
    legal. If the dataset is made only by states (therefore no moves), the
    accuracy test is not performed.

    Parameters
    ----------
    datasetname : string
        The name of the dataset file.
    statesonly : boolean
        True if the dataset has doesn't contains informations about the moves.
    expanded : boolean
        True if the dataset has been already expanded through symmetries.
    name : string
        The name of the network configuration to load
    """

    print("Testing " + name)
    print("Loading networks...")
    print("\tloading " + name + "_TO")
    TOnet = load_net(name + "_TO")
    print("\tloading " + name + "_FROM")
    FROMnet = load_net(name + "_FROM")

    print("\tloading " + name + "_REMOVE")
    REMOVEnet = load_net(name + "_REMOVE")
    print("\tNetworks loaded!")

    data_format = TOnet[3]
    print(str(data_format))

    orderc = ['X', 'X', 'X']
    orderc[TOnet[2]] = 'T'
    orderc[FROMnet[2]] = 'F'
    orderc[REMOVEnet[2]] = 'R'
    order = "" + orderc[0] + orderc[1] + orderc[2]
    print("\tOrder: " + order)

    print("Loading data...")

    if statesonly:
        if (expanded):
            A, B = load_expanded_states_dataset(datasetname)
        else:
            A, B = load_states_dataset(datasetname)
    else:
        if expanded:
            A, B = load_expanded_dataset(datasetname)
        else:
            A, B = load_dataset(datasetname)

    print("\tData loaded! Loaded: " + str(len(B)) + " data")

    print("Processing data and getting choices")
    X_TO_set = []
    X_FROM_set = []
    X_REMOVE_set = []

    TO_choice_set = []
    FROM_choice_set = []
    REMOVE_choice_set = []

    y_TO_set = []
    y_FROM_set = []
    y_REMOVE_set = []

    numbatch = int(len(A) / batchsize) + 1

    for i in range(1, numbatch + 1):
        print("\t" + str(i * batchsize * 100.0 / len(A)) + "%")

        if (i * batchsize <= len(A)):
            Ai = A[(i - 1) * batchsize:i * batchsize]
            Bi = B[(i - 1) * batchsize:i * batchsize]

        else:
            Ai = A[(i - 1) * batchsize:]
            Bi = B[(i - 1) * batchsize:]

        y_TO = process_move_onlyTO(Bi)
        y_FROM = process_move_onlyFROM(Bi)
        y_REMOVE = process_move_onlyREMOVE(Bi)

        init_state = process_state_binary(Ai, data_format)

        if order == "FTR":
            X_FROM = init_state
            FROM_choice = get_choices(FROMnet, X_FROM)

            X_TO = add_CHOICE_binary_raw(X_FROM, FROM_choice)
            TO_choice = get_choices(TOnet, X_TO)

            X_REMOVE = add_CHOICE_binary_raw(X_TO, TO_choice)
            REMOVE_choice = get_choices(REMOVEnet, X_REMOVE)
        elif order == "RFT":
            X_REMOVE = init_state
            REMOVE_choice = get_choices(REMOVEnet, X_REMOVE)

            X_FROM = add_CHOICE_binary_raw(X_REMOVE, REMOVE_choice)
            FROM_choice = get_choices(FROMnet, X_FROM)

            X_TO = add_CHOICE_binary_raw(X_FROM, FROM_choice)
            TO_choice = get_choices(TOnet, X_TO)
        elif order == "FRT":
            X_FROM = init_state
            FROM_choice = get_choices(FROMnet, X_FROM)

            X_REMOVE = add_CHOICE_binary_raw(X_FROM, FROM_choice)
            REMOVE_choice = get_choices(REMOVEnet, X_REMOVE)

            X_TO = add_CHOICE_binary_raw(X_REMOVE, REMOVE_choice)
            TO_choice = get_choices(TOnet, X_TO)
        elif order == "RTF":
            X_REMOVE = init_state
            REMOVE_choice = get_choices(REMOVEnet, X_REMOVE)

            X_TO = add_CHOICE_binary_raw(X_REMOVE, REMOVE_choice)

            TO_choice = get_choices(TOnet, X_TO)

            X_FROM = add_CHOICE_binary_raw(X_TO, TO_choice)

            FROM_choice = get_choices(FROMnet, X_FROM)
        elif order == "TRF":
            X_TO = init_state
            TO_choice = get_choices(TOnet, X_TO)

            X_REMOVE = add_CHOICE_binary_raw(X_TO, TO_choice)
            REMOVE_choice = get_choices(REMOVEnet, X_REMOVE)

            X_FROM = add_CHOICE_binary_raw(X_REMOVE, REMOVE_choice)
            FROM_choice = get_choices(FROMnet, X_FROM)
        elif order == "TFR":
            X_TO = init_state
            TO_choice = get_choices(TOnet, X_TO)

            #print("\tGot TO choices")

            X_FROM = add_CHOICE_binary_raw(X_TO, TO_choice)

            FROM_choice = get_choices(FROMnet, X_FROM)

            #print("\tGot FROM choices")

            X_REMOVE = add_CHOICE_binary_raw(X_FROM, FROM_choice)

            REMOVE_choice = get_choices(REMOVEnet, X_REMOVE)
        else:
            print("Unknown configuration. Using TFR")
            X_TO = init_state
            TO_choice = get_choices(TOnet, X_TO)

            #print("\tGot TO choices")

            X_FROM = add_CHOICE_binary_raw(X_TO, TO_choice)

            FROM_choice = get_choices(FROMnet, X_FROM)

            #print("\tGot FROM choices")

            X_REMOVE = add_CHOICE_binary_raw(X_FROM, FROM_choice)

            REMOVE_choice = get_choices(REMOVEnet, X_REMOVE)

        for j in range(len(X_TO)):
            X_TO_set.append(X_TO[j])
            X_FROM_set.append(X_FROM[j])
            X_REMOVE_set.append(X_REMOVE[j])

            TO_choice_set.append(TO_choice[j])
            FROM_choice_set.append(FROM_choice[j])
            REMOVE_choice_set.append(REMOVE_choice[j])

            y_TO_set.append(y_TO[j])
            y_FROM_set.append(y_FROM[j])
            y_REMOVE_set.append(y_REMOVE[j])

        #print("\tGot REMOVE choices")

    # variable renaming
    X_TO = X_TO_set
    X_FROM = X_FROM_set
    X_REMOVE = X_REMOVE_set

    TO_choice = TO_choice_set
    FROM_choice = FROM_choice_set
    REMOVE_choice = REMOVE_choice_set

    y_TO = y_TO_set
    y_FROM = y_FROM_set
    y_REMOVE = y_REMOVE_set

    print("Testing legality")

    legalities = get_legalities(TO_choice, FROM_choice, REMOVE_choice,
                                X_REMOVE, data_format)

    print("\ttesting the legality of " + str(len(legalities[0])) + " data\n")

    TO_self_leg = legalities[0]
    FROM_self_leg = legalities[1]
    REMOVE_self_leg = legalities[2]
    FROM_leg = legalities[3]
    REMOVE_leg = legalities[4]
    wholeFROM = legalities[5]
    wholeREMOVE = legalities[6]
    wholeMOVE = legalities[7]

    fileT = open(name + "_testing.txt", 'a')

    leg = ("Legality response on " + datasetname + ":" + "\n\tOnly TO leg:\t" +
           str(numpy.mean(TO_self_leg) * 100) + "\n\tOnly FROM leg:\t" +
           str(numpy.mean(FROM_self_leg) * 100) + "\n\tOnly REMOVE leg:\t" +
           str(numpy.mean(REMOVE_self_leg) * 100) + "\n\tOnly FROM-TO leg:\t" +
           str(numpy.mean(FROM_leg) * 100) + "\n\tOnly REMOVE-FROM-TO leg:\t" +
           str(numpy.mean(REMOVE_leg) * 100) + "\n\tWhole FROM leg:\t" +
           str(numpy.mean(wholeFROM) * 100) + "\n\tWhole REMOVE leg:\t" +
           str(numpy.mean(wholeREMOVE) * 100) + "\n\tWhole MOVE leg:\t" +
           str(numpy.mean(wholeMOVE) * 100))

    print(leg)
    fileT.write(leg)

    print("\nTesting accuracy and special cases\n")

    # accuracy valutation and legality evaluation for some particular cases:
    # the FROM move in phase 2 and the REMOVE when is not 0
    correctTO = 0
    correctFROM = 0
    correctREMOVE = 0
    correctWHOLE = 0

    # legality for FROM in phase 2
    legalFROM2 = 0
    f2 = 0

    # legality for REMOVE != 0 for the network
    legalREMOVEeat = 0
    re = 0

    # accuracy when REMOVE != 0 in dataset
    correctREMOVEyes = 0
    ry = 0

    # accuracy when FROM != 0 in dataset
    correctFROMyes = 0
    fy = 0

    # accuracy for the different phases
    correctWHOLE1 = 0
    p1 = 0
    correctWHOLE2 = 0
    p2 = 0
    correctWHOLE3 = 0
    p3 = 0

    size = len(TO_choice)

    print("\tTesting the accuracy of " + str(size) + " data")

    for i in range(size):

        # TO DECISION
        if TO_choice[i] == y_TO[i]:
            correctTO += 1

        # legal FROM decision in phase 2
        if (is_phase_2(X_REMOVE[i], data_format)):
            f2 += 1
            # legality
            l = get_legalities(TO_choice[i:i + 1], FROM_choice[i:i + 1],
                               REMOVE_choice[i:i + 1], X_REMOVE[i:i + 1],
                               data_format)
            if (l[5] == 1):
                legalFROM2 += 1

        # FROM decision is different from 0
        if y_FROM[i] != 0:
            fy += 1

        # FROM decision
        if FROM_choice[i] == y_FROM[i]:
            correctFROM += 1
            # correct FROM decision if different from 0
            if y_FROM[i] != 0:
                correctFROMyes += 1

        # REMOVE decision when present
        if y_REMOVE[i] != 0:
            ry += 1

        if REMOVE_choice[i] != 0:
            re += 1
            # legality
            l = get_legalities(TO_choice[i:i + 1], FROM_choice[i:i + 1],
                               REMOVE_choice[i:i + 1], X_REMOVE[i:i + 1],
                               data_format)
            if (l[6] == 1):
                legalREMOVEeat += 1

        # REMOVE decision
        if REMOVE_choice[i] == y_REMOVE[i]:
            correctREMOVE += 1
            if (y_REMOVE[i] != 0):
                correctREMOVEyes += 1

        if is_phase_1(X_REMOVE[i], data_format):
            p1 += 1
        elif is_phase_3(X_REMOVE[i], data_format):
            p3 += 1
        else:
            p2 += 1

        # WHOLE move (in different phases of game)
        if (TO_choice[i] == y_TO[i] and FROM_choice[i] == y_FROM[i]
                and REMOVE_choice[i] == y_REMOVE[i]):
            correctWHOLE += 1

            if is_phase_1(X_REMOVE[i], data_format):
                correctWHOLE1 += 1
            elif is_phase_3(X_REMOVE[i], data_format):
                correctWHOLE3 += 1
            else:
                correctWHOLE2 += 1

    if (size > 0):
        correctTO = correctTO * 100.0 / size
        correctFROM = correctFROM * 100.0 / size
        correctREMOVE = correctREMOVE * 100.0 / size
        correctWHOLE = correctWHOLE * 100.0 / size
    else:
        correctTO = -1
        correctFROM = -1
        correctREMOVE = -1
        correctWHOLE = -1

    if (f2 > 0):
        legalFROM2 = legalFROM2 * 100.0 / f2
    else:
        legalFROM2 = -1

    if (re > 0):
        legalREMOVEeat = (legalREMOVEeat * 100.0) / re
    else:
        legalREMOVEeat = -1

    if (ry > 0):
        correctREMOVEyes = correctREMOVEyes * 100.0 / ry
    else:
        correctREMOVEyes = -1

    if (fy > 0):
        correctFROMyes = correctFROMyes * 100.0 / fy
    else:
        correctFROMyes = -1

    if (p1 > 0):
        correctWHOLE1 = correctWHOLE1 * 100.0 / p1
    else:
        correctWHOLE1 = -1

    if (p2 > 0):
        correctWHOLE2 = correctWHOLE2 * 100.0 / p2
    else:
        correctWHOLE2 = -1

    if (p3 > 0):
        correctWHOLE3 = correctWHOLE3 * 100.0 / p3
    else:
        correctWHOLE3 = -1

    leg = ("\n\tFROM phase 2 leg:\t" + str(legalFROM2) +
           "\n\tREMOVE when chosen leg:\t" + str(legalREMOVEeat))

    if (not statesonly):
        leg += ("\n--------------------\n\nAccuracy response on " +
                datasetname + ":" + "\n\tTO accuracy:\t" + str(correctTO) +
                "\n\tFROM accuracy:\t" + str(correctFROM) +
                "\n\tREMOVE accuracy:\t" + str(correctREMOVE) +
                "\n\tWhole MOVE accuracy:\t" + str(correctWHOLE) +
                "\n\n\tWhole MOVE accuracy in phase 1:\t" +
                str(correctWHOLE1) + "\n\tWhole MOVE accuracy in phase 2:\t" +
                str(correctWHOLE2) + "\n\tWhole MOVE accuracy in phase 3:\t" +
                str(correctWHOLE3) + "\n\n\tFROM not 0 accuracy:\t" +
                str(correctFROMyes) + "\n\tREMOVE not 0 accuracy:\t" +
                str(correctREMOVEyes) + "\n\n\n")

    print(leg)
    fileT.write(leg)

    fileT.close()
Example #2
0
def choose(TOnet, FROMnet, REMOVEnet, state, data_format):

    orderc = ['X', 'X', 'X']
    orderc[TOnet[1]] = 'T'
    orderc[FROMnet[1]] = 'F'
    orderc[REMOVEnet[1]] = 'R'
    order = "" + orderc[0] + orderc[1] + orderc[2]
    print(("\tOrder: " + order))

    nets = ['X', 'X', 'X']
    nets[TOnet[1]] = TOnet
    nets[FROMnet[1]] = FROMnet
    nets[REMOVEnet[1]] = REMOVEnet

    FIRSTpred_fn = nets[0][0]
    SECONDpred_fn = nets[1][0]
    THIRDpred_fn = nets[2][0]

    global illegalTO
    global illegalFROM
    global illegalREMOVE

    illegal = ['X', 'X', 'X']
    illegal[TOnet[1]] = illegalTO
    illegal[FROMnet[1]] = illegalFROM
    illegal[REMOVEnet[1]] = illegalREMOVE

    print("Choosing best move: ")
    print("\tchoosing FIRST position...")

    # TO choice
    states = [state]
    FIRSTstate = process_state_binary(states, data_format)
    print(data_format)
    FIRSTprob = FIRSTpred_fn(FIRSTstate)

    correct = False
    FIRSTchoice = 0
    while not correct:
        propchoice = numpy.argmax(FIRSTprob[0])
        if FIRSTprob[0][propchoice] >= 0:
            FIRSTchoice = [propchoice]
        else:
            print("No legal option aviable")
            sys.exit()
        print(("\t\tTOchoice: " + str(FIRSTchoice[0])))

        vec_4_leg = [FIRSTchoice, None, None]

        legalities = get_legalities(vec_4_leg[TOnet[1]], vec_4_leg[FROMnet[1]],
                                    vec_4_leg[REMOVEnet[1]], FIRSTstate,
                                    data_format)

        if orderc[0] == 'T':
            legalities = legalities[0]
        elif orderc[0] == 'F':
            legalities = legalities[1]
        elif orderc[0] == 'R':
            legalities = legalities[2]

        if (legalities[0] == 0):
            FIRSTprob[0][FIRSTchoice[0]] = -1
            print("\t\t\tIllegal FIRST choice, retry")
            illegal[0] += 1
        else:
            correct = True

    print(orderc)
    print("\tchoosing SECOND position...")
    # SECOND choice
    SECONDstate = add_CHOICE_binary_raw(FIRSTstate, FIRSTchoice)
    SECONDprob = SECONDpred_fn(SECONDstate)
    correct = False
    SECONDchoice = 0
    while not correct:
        propchoice = numpy.argmax(SECONDprob[0])
        if SECONDprob[0][propchoice] >= 0:
            SECONDchoice = [propchoice]
        else:
            print("No legal option aviable")
            sys.exit()
        print(("\t\tSECONDchoice: " + str(SECONDchoice[0])))

        vec_4_leg = [FIRSTchoice, SECONDchoice, None]

        legalities = get_legalities(vec_4_leg[TOnet[1]], vec_4_leg[FROMnet[1]],
                                    vec_4_leg[REMOVEnet[1]], SECONDstate,
                                    data_format)

        if orderc[2] == 'T':
            legal = legalities[9]
        elif orderc[2] == 'F':
            legal = legalities[8]
        elif orderc[2] == 'R':
            legal = legalities[5]

        if (legal[0] == 0):
            SECONDprob[0][SECONDchoice[0]] = -1
            print("\t\t\tIllegal FROM choice, retry")
            illegal[1] += 1
        else:
            correct = True

    print("\tchoosing THIRD position...")
    # REMOVE choice
    THIRDstate = add_CHOICE_binary_raw(SECONDstate, SECONDchoice)
    THIRDprob = THIRDpred_fn(THIRDstate)
    correct = False
    THIRDchoice = 0
    while not correct:
        propchoice = numpy.argmax(THIRDprob[0])
        if THIRDprob[0][propchoice] >= 0:
            THIRDchoice = [propchoice]
        else:
            print("No legal option aviable")
            sys.exit()
        print(("\t\tTHIRDchoice: " + str(THIRDchoice[0])))

        vec_4_leg = [FIRSTchoice, SECONDchoice, THIRDchoice]

        legalities = get_legalities(vec_4_leg[TOnet[1]], vec_4_leg[FROMnet[1]],
                                    vec_4_leg[REMOVEnet[1]], SECONDstate,
                                    data_format)[7]

        if (legalities[0] == 0):
            THIRDprob[0][THIRDchoice[0]] = -1
            print("\t\t\tIllegal REMOVE choice, retry")
            illegal[2] += 1
        else:
            correct = True

    choices = [FIRSTchoice, SECONDchoice, THIRDchoice]

    return (choices[TOnet[1]][0], choices[FROMnet[1]][0],
            choices[REMOVEnet[1]][0])
Example #3
0
def find_legal_moves(state, bin_state, data_format):
    """
    Compute all the legal partial and complete moves for the given state

    

    Parameters
    ----------
    state : State
        The game state.
    bin_state : int[]
        The game state represented as an array
    data_format : string
        The representation format of the bin_state
    
    Returns
    -------
    set
        A set of strings with all the legal partial and complete moves
    """

    moves = set()

    # build 3 set: empty positions, positions with enemy checkers and
    # positions with owned checkers
    enemy_pos = []
    mine_pos = []
    empty_pos = []
    for position in range(24):
        checker = state.positions[position]
        if checker == 'M':
            mine_pos.append(position)
        elif checker == 'E':
            enemy_pos.append(position)
        elif checker == 'O':
            empty_pos.append(position)

    Tpart = -1
    Fpart = -1
    Rpart = -1

    if (state.my_phase == 1):

        # the only legal FROM is 0
        Fpart = 0

        # the legal TO positions are the empty ones
        for TO_position in empty_pos:
            Tpart = TO_position + 1

            # verify if the option of no remove is legal
            Rpart = 0

            legality = get_legalities([Tpart], [Fpart], [Rpart], [bin_state],
                                      data_format)
            if (legality[7][0] == 1):
                moves.add("T" + str(Tpart) + "F" + str(Fpart) + "R" +
                          str(Rpart))
                moves.add("T" + str(Tpart) + "R" + str(Rpart))
                moves.add("F" + str(Fpart) + "R" + str(Rpart))
                moves.add("T" + str(Tpart) + "F" + str(Fpart))
                moves.add("T" + str(Tpart))
                moves.add("F" + str(Fpart))
                moves.add("R" + str(Rpart))

            # if one remove is necessary, all the enemy positions are
            # candidates
            else:
                for REMOVE_position in enemy_pos:
                    Rpart = REMOVE_position + 1
                    legality = get_legalities([Tpart], [Fpart], [Rpart],
                                              [bin_state], data_format)
                    if (legality[7][0] == 1):
                        moves.add("T" + str(Tpart) + "F" + str(Fpart) + "R" +
                                  str(Rpart))
                        moves.add("T" + str(Tpart) + "R" + str(Rpart))
                        moves.add("F" + str(Fpart) + "R" + str(Rpart))
                        moves.add("T" + str(Tpart) + "F" + str(Fpart))
                        moves.add("T" + str(Tpart))
                        moves.add("F" + str(Fpart))
                        moves.add("R" + str(Rpart))

    elif (state.my_phase == 2):
        # each checker is a legal from position
        for FROM_position in mine_pos:
            Fpart = FROM_position + 1

            # find the positions which are adjacents to the FROM one
            adjacent_parts = []

            for part in range(len(near[Fpart])):
                if (near[Fpart][part] == 1):
                    adjacent_parts.append(part)

            for Tpart in adjacent_parts:
                TO_position = Tpart - 1

                # verify if the option of no remove is legal
                Rpart = 0

                legality = get_legalities([Tpart], [Fpart], [Rpart],
                                          [bin_state], data_format)
                if (legality[7][0] == 1):
                    moves.add("T" + str(Tpart) + "F" + str(Fpart) + "R" +
                              str(Rpart))
                    moves.add("T" + str(Tpart) + "R" + str(Rpart))
                    moves.add("F" + str(Fpart) + "R" + str(Rpart))
                    moves.add("T" + str(Tpart) + "F" + str(Fpart))
                    moves.add("T" + str(Tpart))
                    moves.add("F" + str(Fpart))
                    moves.add("R" + str(Rpart))

                # if the the legality of the FT couple is confirmed,
                # one remove is necessary, all the enemy positions are
                # candidates
                elif (legality[3][0] == 1):
                    for REMOVE_position in enemy_pos:
                        Rpart = REMOVE_position + 1
                        legality = get_legalities([Tpart], [Fpart], [Rpart],
                                                  [bin_state], data_format)
                        if (legality[7][0] == 1):
                            moves.add("T" + str(Tpart) + "F" + str(Fpart) +
                                      "R" + str(Rpart))
                            moves.add("T" + str(Tpart) + "R" + str(Rpart))
                            moves.add("F" + str(Fpart) + "R" + str(Rpart))
                            moves.add("T" + str(Tpart) + "F" + str(Fpart))
                            moves.add("T" + str(Tpart))
                            moves.add("F" + str(Fpart))
                            moves.add("R" + str(Rpart))

    elif (state.my_phase == 3):
        # each empty position is legal
        for TO_position in empty_pos:
            Tpart = TO_position + 1
            # each checker is a legal from position
            for FROM_position in mine_pos:
                Fpart = FROM_position + 1

                # verify if the option of no remove is legal
                Rpart = 0

                legality = get_legalities([Tpart], [Fpart], [Rpart],
                                          [bin_state], data_format)
                if (legality[7][0] == 1):
                    moves.add("T" + str(Tpart) + "F" + str(Fpart) + "R" +
                              str(Rpart))
                    moves.add("T" + str(Tpart) + "R" + str(Rpart))
                    moves.add("F" + str(Fpart) + "R" + str(Rpart))
                    moves.add("T" + str(Tpart) + "F" + str(Fpart))
                    moves.add("T" + str(Tpart))
                    moves.add("F" + str(Fpart))
                    moves.add("R" + str(Rpart))

                # if one remove is necessary, all the enemy positions are
                # candidates
                else:
                    for REMOVE_position in enemy_pos:
                        Rpart = REMOVE_position + 1
                        legality = get_legalities([Tpart], [Fpart], [Rpart],
                                                  [bin_state], data_format)
                        if (legality[7][0] == 1):
                            moves.add("T" + str(Tpart) + "F" + str(Fpart) +
                                      "R" + str(Rpart))
                            moves.add("T" + str(Tpart) + "R" + str(Rpart))
                            moves.add("F" + str(Fpart) + "R" + str(Rpart))
                            moves.add("T" + str(Tpart) + "F" + str(Fpart))
                            moves.add("T" + str(Tpart))
                            moves.add("F" + str(Fpart))
                            moves.add("R" + str(Rpart))

    return moves
Example #4
0
def main(
    datasetname='DATASET.mock.txt',
    expanded=False,
):
    """
    Computes statistics relative to a dataset legality.
    
    Loads a dataset and measures the mean number of legal moves possible in
    each state and thenumber of states in which a particular move is legal.

    Parameters
    ----------
    datasetname : string
        The name of the dataset file.
    expanded : boolean
        True if the dataset has been already expanded through symmetries.
    """

    print("Testing " + datasetname + "\nexpanded = " + str(expanded))

    print("Testing legality characteristics of " + datasetname +
          "\nLoading data...")

    if (expanded):
        A, B = load_expanded_states_dataset(datasetname)
    else:
        A, B = load_states_dataset(datasetname)

    data_format = "binary raw"
    X_train = process_state_binary(A, data_format)

    n_states = len(A)

    TO_moves = range(1, 25)
    FROM_moves = range(0, 25)
    REMOVE_moves = range(0, 25)

    n_moves = len(TO_moves) * len(FROM_moves) * len(REMOVE_moves)

    # counter of number of legal moves for each states
    count_states = [0] * n_states

    # counter of states in which this move is legal
    count_moves = [0] * n_moves

    print(
        str(n_states) + " data loaded. " + str(n_moves) + " moves considered")

    fileStates = open(datasetname + "_legmeas_states.txt", 'w')
    fileMoves = open(datasetname + "_legmeas_moves.txt", 'w')
    fileRecap = open(datasetname + "_legmeas.txt", 'w')

    fileStates.write("Testing legality characteristics of " + datasetname +
                     "\n")
    fileMoves.write("Testing legality characteristics of " + datasetname +
                    "\n")
    fileMoves.write("T\tF\tR\n")
    fileRecap.write("Testing legality characteristics of " + datasetname +
                    "\n")

    perc = 1
    start_time = time.time()
    print("Starting the test...")

    for i in range(n_states):
        bin_state = X_train[i]
        state = A[i]

        # build 3 set: empty positions, positions with enemy checkers and
        # positions with owned checkers
        enemy_pos = []
        mine_pos = []
        empty_pos = []
        for position in range(24):
            checker = state.positions[position]
            if checker == 'M':
                mine_pos.append(position)
            elif checker == 'E':
                enemy_pos.append(position)
            elif checker == 'O':
                empty_pos.append(position)

        Tpart = -1
        Fpart = -1
        Rpart = -1

        if (state.my_phase == 1):

            # the only legal FROM is 0
            Fpart = 0

            # the legal TO positions are the empty ones
            for TO_position in empty_pos:
                Tpart = TO_position + 1

                # verify if the option of no remove is legal
                Rpart = 0

                legality = get_legalities([Tpart], [Fpart], [Rpart],
                                          [bin_state], data_format)
                if (legality[7][0] == 1):
                    count_states[i] += 1
                    index = (((TO_position) * len(REMOVE_moves) + Fpart) *
                             len(FROM_moves) + Rpart)
                    count_moves[index] += 1

                # if one remove is necessary, all the enemy positions are
                # candidates
                else:
                    for REMOVE_position in enemy_pos:
                        Rpart = REMOVE_position + 1
                        legality = get_legalities([Tpart], [Fpart], [Rpart],
                                                  [bin_state], data_format)
                        if (legality[7][0] == 1):
                            count_states[i] += 1
                            index = ((
                                (TO_position) * len(REMOVE_moves) + Fpart) *
                                     len(FROM_moves) + Rpart)
                            count_moves[index] += 1

        elif (state.my_phase == 2):
            # each checker is a legal from position
            for FROM_position in mine_pos:
                Fpart = FROM_position + 1

                # find the positions which are adjacents to the FROM one
                adjacent_parts = []

                for part in range(len(near[Fpart])):
                    if (near[Fpart][part] == 1):
                        adjacent_parts.append(part)

                for Tpart in adjacent_parts:
                    TO_position = Tpart - 1

                    # verify if the option of no remove is legal
                    Rpart = 0

                    legality = get_legalities([Tpart], [Fpart], [Rpart],
                                              [bin_state], data_format)
                    if (legality[7][0] == 1):
                        count_states[i] += 1
                        index = (((TO_position) * len(REMOVE_moves) + Fpart) *
                                 len(FROM_moves) + Rpart)
                        count_moves[index] += 1

                    # if the the legality of the FT couple is confirmed,
                    # one remove is necessary, all the enemy positions are
                    # candidates
                    elif (legality[3][0] == 1):
                        for REMOVE_position in enemy_pos:
                            Rpart = REMOVE_position + 1
                            legality = get_legalities([Tpart], [Fpart],
                                                      [Rpart], [bin_state],
                                                      data_format)
                            if (legality[7][0] == 1):
                                count_states[i] += 1
                                index = (((TO_position) * len(REMOVE_moves) +
                                          Fpart) * len(FROM_moves) + Rpart)
                                count_moves[index] += 1

        elif (state.my_phase == 3):
            # each empty position is legal
            for TO_position in empty_pos:
                Tpart = TO_position + 1
                # each checker is a legal from position
                for FROM_position in mine_pos:
                    Fpart = FROM_position + 1

                    # verify if the option of no remove is legal
                    Rpart = 0

                    legality = get_legalities([Tpart], [Fpart], [Rpart],
                                              [bin_state], data_format)
                    if (legality[7][0] == 1):
                        count_states[i] += 1
                        index = (((TO_position) * len(REMOVE_moves) + Fpart) *
                                 len(FROM_moves) + Rpart)
                        count_moves[index] += 1

                    # if one remove is necessary, all the enemy positions are
                    # candidates
                    else:
                        for REMOVE_position in enemy_pos:
                            Rpart = REMOVE_position + 1
                            legality = get_legalities([Tpart], [Fpart],
                                                      [Rpart], [bin_state],
                                                      data_format)
                            if (legality[7][0] == 1):
                                count_states[i] += 1
                                index = (((TO_position) * len(REMOVE_moves) +
                                          Fpart) * len(FROM_moves) + Rpart)
                                count_moves[index] += 1

        fileStates.write(str(A[i]) + "\t-\t" + str(count_states[i]) + "\n")

        act_time = time.time()
        percentage = i * 100 / (n_states * 1.0)
        # gives feedback about the amount of data processed
        while (percentage > perc):
            perc += 1
        print(
            str(round(percentage, 2)) + "%\t" + str(i) +
            " data processed\ttime passed: " + str(act_time - start_time))
        fileStates.flush()

    act_time = time.time()
    print("Data processed. Seconds passed: " + str(act_time - start_time))

    fileStates.close()

    for TO_opt in TO_moves:
        for FROM_opt in FROM_moves:
            for REMOVE_opt in REMOVE_moves:
                index = ((TO_opt - 1) * len(FROM_moves) * len(REMOVE_moves) +
                         FROM_opt * len(REMOVE_moves) + REMOVE_opt)
                num = count_moves[index]
                fileMoves.write(
                    str(TO_opt) + "\t" + str(FROM_opt) + "\t" +
                    str(REMOVE_opt) + "\t-\t" + str(num) + "\n")

    fileMoves.close()

    meanStates = numpy.mean(count_states)
    meanMoves = numpy.mean(count_moves)
    fileRecap.write("Mean legal moves per state:\t" + str(meanStates) + "\n")
    fileRecap.write("Mean states in which the move is legal:\t" +
                    str(meanMoves) + "\n\n")

    table = {}
    for count in count_states:
        # count the number of moves as a percentage of the total
        percentage = count
        if percentage in table.keys():
            table[percentage] += 1
        else:
            table[percentage] = 1

    for percentage in table.keys():
        fileRecap.write(str(percentage) + "\t" + str(table[percentage]) + "\n")

    fileRecap.close()