예제 #1
0
    data1 = sampleSub.readlines()
    sampleSub.close()

    subData = h.makeTable(data1, 1)
    lastScore = INFINITE
    count = -1

    lastStageScore = 0

    # 01 while True:
    while True:
        count += 1

        # 02 현재 상태에 대한 score를 계산하여 출력한다. (feasible하지 않으면 무한대)
        ocA = h.getOccupancy(famData, subData)  # occupancy array
        score = h.getScoreFeasible(famData, subData, ocA)

        # 지난 단계의 score와 같으면 더 이상 업데이트가 되지 않으므로 랜덤하게 5개 변경 (미구현)
        converged = False
        if lastStageScore == score: converged = True

        # 지난 단계(while문 loop)의 score를 업데이트
        lastStageScore = score

        # 03 For 모든 families
        for i in range(FAMILIES):

            if (count == 0 and i % 50 == 0) or (count > 0 and i % 200 == 0):
                print(
                    str(count) + ' ' + str(i) + ' / score: ' + str(score) +
                    ' / checksum: ' + str(sum(ocA)) + ' ' + str(max(ocA)) +
예제 #2
0
def findBestOption(subData, famData, options, ocA, ci, i, prevScore):

    # condition = (ci == 17 and i >= 0 and i < 5)
    condition = False

    # 04 각 option에 따른 score의 변화량을 저장한 배열을 초기화한다.
    scoreChange = []
    for j in range(len(options)):
        scoreChange.append(None)

    befores = [
    ]  # value of 'before' for each option: [opt0:[o0b0, o0b1], opt1:[o1b0, o1b1, o1b2, o1b3], ...]
    afters = [
    ]  # value of 'after' for each option:  [opt0:[o0a0, o0a1], opt1:[o1a0, o1a1, o1a2, o1a3], ...]
    isFeasible = []

    # 05 For 모든 options (0, 1, 2, ..., and 9)
    for j in range(len(options)):

        if condition == True: print('\n' + str(j))

        thisOption = options[
            j]  # 변경사항: [[famK0, optK0], [famK1, optK1], ..., [famKA, optKA]]
        if condition == True: print('[**] thisOption = ' + str(thisOption))

        # 06 ocA 및 subData를 복사한 배열을 만든다.
        ocA_copy = []
        for k in range(len(ocA)):
            ocA_copy.append(ocA[k])

        if len(thisOption) >= 2:
            subData_copy = []
            for k in range(len(subData)):
                subData_copy.append([subData[k][0], subData[k][1]])

        before_ = [
        ]  # 'before' values of option j : for example [o0b0, o0b1, o0b2]
        after_ = [
        ]  # 'after' values of option j : for example [o0a0, o0a1, o0a2]

        isFeasible = True  # ocA >= 125 and ocA <= 300

        scoreChangeSum = 0  # sum of score change

        # 각 option에 대하여 (famK0, famK1, ..., famKA에 대하여 변경)
        # 처음의 p0, A0, B0 값과 마지막 p1, A1, B1 값만을 이용 (단일 변경의 경우 처음과 마지막이 같으므로 모두 이용)
        for k in range(len(thisOption)):
            if condition == True: print('[00] k = ' + str(k))

            famID = thisOption[k][0]  # option의 변경사항 k에 대한 family ID
            toChange = thisOption[k][
                1]  # option의 변경사항 k에 대한 change to this option (0, 1, ..., or 9)
            if condition == True:
                print('[01] famID: ' + str(famID) + ', toChange: ' +
                      str(toChange))

            if len(thisOption) >= 2:
                before = subData_copy[famID][1]  # 변경 전 date (option)
            else:
                before = subData[famID][1]  # 변경 전 date (option)

            if toChange < 10:
                after = famData[famID][toChange + 1]  # 변경 후 date (option)
            else:
                after = toChange - 100  # 변경 후 date (option) - toChange가 10 이상(101~200)이면 100을 뺀 값으로 지정

            if condition == True:
                print('[02] before: ' + str(before) + ', after: ' + str(after))

            before_.append(before)
            after_.append(after)
            if condition == True:
                print('[03] before_: ' + str(before_) + ', after_: ' +
                      str(after_))

            members = famData[famID][11]

            # 07 p0 = 해당 family에 대한 prefCost를 계산한다.
            #    p0 : 해당 family에 대한 date 변경 전 prefCost
            p0 = prefCostForThisFamily(famData[famID], [famID, before])
            if condition == True:
                print('[04] p0: ' + str(p0) + ' / famID=' + str(famID) +
                      ', famData[famID]=' + str(famData[famID]) + ', before=' +
                      str(before))

            # before와 after가 서로 같으면 변화가 없는 것이므로 건너뛰기
            if before == after: continue

            # 08 B0 = 변경전 day가 before일 때 day (before-5) ~ day (before+5) 부분을 추출하여 account penalty를 계산한다.
            #    B0 : 변경 전 date의 ocA 변경 전 account penalty
            beforeOCA = [None] * max(6 - before, 0) + ocA_copy[max(
                before - 5, 1):min(before + 6, 101)] + [ocA_copy[100]] * max(
                    0, before - 95)

            if before == 100: B0 = accountPenaltyFor100(beforeOCA)
            else: B0 = accountPenalty(beforeOCA)
            if condition == True:
                print('[05] B0: ' + str(B0) + ' / beforeOCA=' + str(beforeOCA))

            # 09 A0 = 변경후 day가 after일 때 day (after-5) ~ day (after+5) 부분을 추출하여 account penalty를 계산한다.
            #    A0 : 변경 후 date의 ocA 변경 전 account penalty
            afterOCA = [None] * max(6 - after, 0) + ocA_copy[
                max(after - 5, 1):min(after + 6, 101)] + [ocA_copy[100]] * max(
                    0, after - 95)

            if after == 100: A0 = accountPenaltyFor100(afterOCA)
            else: A0 = accountPenalty(afterOCA)
            if condition == True:
                print('[06] A0: ' + str(A0) + ' / afterOCA=' + str(afterOCA))

            # 10 [IMPORTANT] ocA 배열 갱신: ocA_copy[before] -= people; ocA_copy[after] += people;
            if condition == True:
                print(
                    str(before) + '->' + str(after) + ' ( members: ' +
                    str(members) + ' ) :' + ' ocA_copy[' + str(before) +
                    '] = ' + str(ocA_copy[before]) + ', ocA_copy[' +
                    str(after) + '] = ' + str(ocA_copy[after]))

            for x in range(len(ocA_copy)):
                if x == before and x != after: ocA_copy[x] -= members
                elif x != before and x == after: ocA_copy[x] += members
                else: continue

            if condition == True:
                print(
                    str(before) + '->' + str(after) + ' ( members: ' +
                    str(members) + ' ) :' + ' ocA_copy[' + str(before) +
                    '] = ' + str(ocA_copy[before]) + ', ocA_copy[' +
                    str(after) + '] = ' + str(ocA_copy[after]))

            # 11 B1 = 변경전 day가 before일 때 day (before-5) ~ day (before+5) 부분을 추출하여 account penalty를 계산한다.
            #    B1 : 변경 전 date의 ocA 변경 후 account penalty
            beforeOCA_copy = [None] * max(6 - before, 0) + ocA_copy[max(
                before - 5, 1):min(before + 6, 101)] + [ocA_copy[100]] * max(
                    0, before - 95)

            if before == 100: B1 = accountPenaltyFor100(beforeOCA_copy)
            else: B1 = accountPenalty(beforeOCA_copy)
            if condition == True:
                print('[10] B1: ' + str(B1) + ' / beforeOCA_copy=' +
                      str(beforeOCA_copy))

            # 12 A1 = 변경후 day가 after일 때 day (after-5) ~ day (after+5) 부분을 추출하여 account penalty를 계산한다.
            #    A1 : 변경 후 date의 ocA 변경 후 account penalty
            afterOCA_copy = [None] * max(6 - after, 0) + ocA_copy[
                max(after - 5, 1):min(after + 6, 101)] + [ocA_copy[100]] * max(
                    0, after - 95)

            if after == 100: A1 = accountPenaltyFor100(afterOCA_copy)
            else: A1 = accountPenalty(afterOCA_copy)
            if condition == True:
                print('[11] A1: ' + str(A1) + ' / afterOCA_copy=' +
                      str(afterOCA_copy))

            # 15 p1 = 해당 family에 대한 변경된 prefCost를 계산한다.
            #    p1 : 해당 family에 대한 date 변경 후 prefCost
            p1 = prefCostForThisFamily(famData[famID], [famID, after])
            if condition == True:
                print('[12] p1: ' + str(p1) + ' / famID=' + str(famID) +
                      ', famData[famID]=' + str(famData[famID]) + ', after=' +
                      str(after))

            # 16 해당 option에 대한 account penalty의 변화량 [(A1s+B1s)-(A0s+B0s)],
            # prefCost의 변화량 (p1s-p0s)을 이용하여 score의 변화량 (B1s+A1s+p1s)-(B0s+A0s+p0s)을 계산한다.
            thisScoreChange = (A1 + B1 + p1) - (A0 + B0 + p0)
            scoreChangeSum += thisScoreChange
            if condition == True:
                print('< score change of ' + str(j) + ' > 1[all/aA/aB/p]: ' +
                      str(round(A1 + B1 + p1, 1)) + '\t' + str(round(A1, 1)) +
                      '\t' + str(round(B1, 1)) + '\t' + str(round(p1, 1)) +
                      ',\t0[all/bA/bB/p]: ' + str(round(A0 + B0 + p0, 1)) +
                      '\t' + str(round(A0, 1)) + '\t' + str(round(B0, 1)) +
                      '\t' + str(round(p0, 1)) + ',\tdif: ' +
                      str(round(thisScoreChange, 1)))

            # change copy of subData
            if len(thisOption) >= 2:
                subData_copy[famID] = [subData_copy[famID][0], after]

        # before_, after_를 각각 befores, afters에 추가
        befores.append(before_)
        afters.append(after_)

        if condition == True:
            print('[13] befores: ' + str(befores))
            print('[14] afters : ' + str(afters))

        # Feasible하지 않으면 (max>300 or min<125) 해당 option 건너뛰기
        if max(ocA_copy) > 300 or min(ocA_copy[1:]) < 125:
            scoreChange[j] = None
            continue
        else:
            scoreChange[j] = scoreChangeSum

    if condition == True:
        print('[15] scoreChange: ' + str(scoreChange))

    # scoreChange가 모두 None이면 건너뛰기
    allNone = []
    for j in range(len(options)):
        allNone.append(None)
    if scoreChange == allNone: return prevScore

    # if ci == 17: print('min score = ' + str(minNone(scoreChange)[0]))

    # 17 기존 option에 대한 score보다 낮은 score인 option이 있으면 (즉 score의 변화량 < 0)
    if minNone(scoreChange)[0] < 0:

        if condition == True: roundPrint(scoreChange, 3)

        # 18 score(의 변화량)가 가장 작은 (음수 중에서는 절댓값이 가장 큰) option을 찾아서 실행한다.
        minBefore = []  # 가장 작은 option의 before 값들의 집합
        minAfter = []  # 가장 작은 option의 after 값들의 집합
        minFamIDs = []  # 가장 작은 option의 family ID의 집합
        minChoiceSC = 0  # 가장 작은 option의 score의 변화량
        minChoices = []  # 가장 작은 option의 option 번호(0~9)의 집합
        minK = -1  # 가장 작은 option에 대한 k 값

        for k in range(len(scoreChange)):
            if scoreChange[k] == None: continue
            if scoreChange[k] < minChoiceSC:
                minChoiceSC = scoreChange[k]
                minK = k

                # 해당 option의 family ID 및 option 번호 추출
                thisOption = options[k]

                minBefore = []  # in the form of [oKb0, oKb1, ...]
                minAfter = []  # in the form of [oKa0, oKa1, ...]
                minFamIDs = []  # in the form of [famK0, famK1, ...]
                minChoices = []  # in the form of [optK0, optK1, ...]

                # 해당 option에 대한 before 및 after 값 추출
                # befores : [opt0:[o0b0, o0b1], opt1:[o1b0, o1b1, o1b2, o1b3], ...]
                # afters  : [opt0:[o0a0, o0a1], opt1:[o1a0, o1a1, o1a2, o1a3], ...]
                for x in range(len(thisOption)):
                    minFamIDs.append(thisOption[x][0])
                    minChoices.append(thisOption[x][1])
                    minBefore.append(befores[k][x])
                    minAfter.append(afters[k][x])

        if condition == True:
            print('[15] minFamIDs : ' + str(minFamIDs))
            print('[16] minChoices : ' + str(minChoices))
            print('[17] minBefore : ' + str(minBefore))
            print('[18] minAfter : ' + str(minAfter))

        # subData 변경
        for k in range(len(thisOption)):
            if minChoices[k] < 10:  # 가장 작은 choice의 옵션의 번호가 10 미만이면
                subData[minFamIDs[k]][1] = famData[minFamIDs[k]][minChoices[k]
                                                                 + 1]
            else:  # 10 이상이면 100을 뺀 값으로 지정 (즉 101 <= minChoices[k] <= 200)
                subData[minFamIDs[k]][1] = minChoices[k] - 100

            # minFamIDs[k]에 해당하는 members
            members = famData[minFamIDs[k]][11]

            if condition == True:
                print('< minK = ' + str(minK) + ' > minChoices: ' +
                      str(minChoices))
                print('[19] minFamIDs[k]             : ' + str(minFamIDs[k]))
                print('[20] subData[minFamIDs[k]][1] : ' +
                      str(subData[minFamIDs[k]][1]))
                print('[21] minChoices[k]            : ' + str(minChoices[k]))
                print('[22] ocA[minBefore[k]] BEFORE : ' +
                      str(ocA[minBefore[k]]))
                print('[23] ocA[minAfter[k]]  BEFORE : ' +
                      str(ocA[minAfter[k]]))

            # 19 occupancy array를 업데이트한다. (ocA[before of minChoice] -= people; ocA[after of minChoice] += people;)
            ocA[minBefore[k]] -= members
            ocA[minAfter[k]] += members

            if condition == True:
                print('[22] minBefore[k]            : ' + str(minBefore[k]))
                print('[23] minAfter[k]             : ' + str(minAfter[k]))
                print('[24] ocA[minBefore[k]] AFTER : ' +
                      str(ocA[minBefore[k]]))
                print('[25] ocA[minAfter[k]]  AFTER : ' +
                      str(ocA[minAfter[k]]))
                print('[26] k = ' + str(k) + ', members = ' + str(members))

        score = h.getScoreFeasible(famData, subData, ocA)

        if condition == True:
            print('minChoSC : ' + str(minChoiceSC) + ' -> ' + str(score) +
                  '\n')  # temp

        return score

    # 가장 작은 변화량이 0 초과이면 변화가 없으므로 이전 값을 반환
    return prevScore
예제 #3
0
    # read sample submission data
    sampleSub = open('sample_submission.csv', 'r')
    data1 = sampleSub.readlines()
    sampleSub.close()

    subData = h.makeTable(data1, 1)
    lastScore = 2147483647

    # initialize each row of submission data as choice_0
    for i in range(FAMILIES):
        subData[i][1] = famData[i][1]

    ocA = h.getOccupancy(famData, subData)
    print(h.prefCost(famData, subData, ocA))
    print(h.accountPenalty(famData, subData, ocA))
    lastScore = h.getScoreFeasible(famData, subData, ocA)
    print(lastScore)
    print(ocA)

    # make feasible
    print('times 1')
    options = []
    for i in range(len(subData)):
        options.append(0)

    while True:
        ocA = h.getOccupancy(famData, subData)

        maxVal = -1
        minVal = 9999
        maxIndex = -1