Python 索引器:在图/映射着色的约束满足问题(CSP)中,列表索引超出范围

Python 索引器:在图/映射着色的约束满足问题(CSP)中,列表索引超出范围,python,backtracking,index-error,graph-coloring,constraint-satisfaction,Python,Backtracking,Index Error,Graph Coloring,Constraint Satisfaction,我在运行代码时遇到以下错误。该错误通常不会发生,因为代码对于一个“相邻状态”txt文件运行良好。但对于另一个“相邻状态”txt文件,它给出了这个索引器。我被卡住了,因为我看不出队伍中有任何错误 neighbors[lst[0]] = lst[1:] IndexError: list index out of range “相邻州”txt文件如下所示: Argentina Bolivia Brazil Chile Paraguay Uruguay Bolivia Argentina Brazil

我在运行代码时遇到以下错误。该错误通常不会发生,因为代码对于一个“相邻状态”txt文件运行良好。但对于另一个“相邻状态”txt文件,它给出了这个索引器。我被卡住了,因为我看不出队伍中有任何错误

neighbors[lst[0]] = lst[1:]
IndexError: list index out of range
“相邻州”txt文件如下所示:

Argentina Bolivia Brazil Chile Paraguay Uruguay
Bolivia Argentina Brazil Chile Paraguay Peru
Brazil Argentina Bolivia Colombia Guyana Paraguay Peru Suriname Uruguay Venezuela
Chile Argentina Bolivia Peru
Colombia Brazil Ecuador Peru Venezuela
Ecuador Colombia Peru
Falkland_Islands
Guyana Brazil Suriname Venezuela 
Paraguay Argentina Bolivia Brazil
Peru Bolivia Brazil Chile Colombia Ecuador
Suriname Brazil Guyana
Uruguay Argentina Brazil
Venezuela Brazil Colombia Guyana
import sys
import os
import queue
import time

start = time.time()

neighbors = {}
frequency = {}

def load_data():
    global neighbors,frequency
    with open('adjacent-states', 'r') as file:
        for line in file:
            lst = line.split()
            neighbors[lst[0]] = lst[1:]
    filename = sys.argv[0] 
    with open(filename , 'r') as file:
        try:
            for line in file:
                (city, freq) = line.split()
                frequency[city]=[freq]
        except ValueError:
            frequency = {}
    for key in neighbors:
        if key not in frequency and neighbors[key] != []:   # If a state has no neighbor, We can give any values to it and save the 
            frequency[key] = ['A','B','C','D']      # time in backtracking
        elif key not in frequency:
            frequency[key] = ['A']

# function mrv provides the next state whose frequency should be assigned by the backtracking function. 
# It first checks which state has minimum number of available frequency and in case of tie which has most neighbouring states. 

def mrv(assignment,frequency):
    global neighbors
    len_domain={}
    for key in frequency:
        if key not in assignment:
            len_domain[key]=len(frequency[key])
    val = sorted(len_domain.items(), key=lambda x: x[1])
    min_val = val[0][1]
    highest = 0
    mrv_state = val[0][0]
    for k in val:
        if k[1] > min_val:
            break
        (state,curr) = k
        if len(neighbors[state]) > highest:
            highest = len(neighbors[state])
            mrv_state = state
    return mrv_state

# function lcv returns a list of possible values for a state by ordering values such that value causes least conflict
# comes first in the list

def lcv(state,assignment,frequency):
    choices = frequency[state]
    conflict_queue =queue.PriorityQueue()
    lcv_lst=[]
    for choice in choices:
        value = count_conflicts(state,choice,frequency,assignment)
        conflict_queue.put((value,(choice,)))
    while conflict_queue.empty() is not True:
        (value,(choice,)) = conflict_queue.get()
        lcv_lst.append(choice)
    return lcv_lst



# Temporary assign the value to a state. Remove the rest of the frequency from state's domain,append it to a list and return the list
def temp_assign(state,value,frequency):
    remove_freq = []
    for k in frequency[state]:
        if k != value:
            remove_freq.append((state,k))
    frequency[state]= [value]
    return remove_freq



# Count the number of future conflicts caused by the possible assignment of the frequency to the state.
def count_conflicts(state,choice,frequency,assignment):
    global neighbors
    count = 0
    con_queue = queue.Queue()
    for neighbor in neighbors[state]:
        if neighbor not in assignment:
            con_queue.put((neighbor,choice))
    while not con_queue.empty():
        (state,mychoice) = con_queue.get()
        if len(frequency[state]) == 1 and [choice] == frequency[state] :
            count += 10
        if mychoice in frequency[state]:
            count += 1
    return count
    
# Check whether frequency assignment caused any violation of constraint or not and return the result.
def arc_consistent(assignment,frequency,state=None,remove_lst=None):
    global neighbors
    myqueue = queue.Queue()
    if state == None:
        for state in neighbors:
            for neighbor in neighbors[state]:
                myqueue.put((state,neighbor))
    else:
        for neighbor in neighbors[state]:
            myqueue.put((neighbor,state))
    while not myqueue.empty():
        (state,neighbor) = myqueue.get()
        if remove_inconsistent(state,neighbor,remove_lst):
            if len(frequency[state]) == 0:
                return False
            for new_neigh in neighbors[state]:
                myqueue.put((new_neigh,state))
    return True

# Remove all the frequency from the domain of a state that violates the constraint.
def remove_inconsistent(state,neighbor,remove_lst):
    removed = False
    for freq in frequency[state]:
        if len(frequency[neighbor]) == 1 and [freq] == frequency[neighbor] :
            if remove_lst != None:
                remove_lst.append((state,freq))
            frequency[state].remove(freq)
            removed = True
    return removed

# To count the number of bactracks in the program
def myfunc():
    myfunc.counter += 1
    
        

# Main backtracking function that assigns values to a state and checks whether this assignment violates the constraint or not.
# If an assignment violates the constraints, function removes the assignment and backtrack to try another assignment. This function
# is same as given in textbook and ucb's video lecture. 
def assign(assignment,frequency):
    global neighbors
    myfunc.counter = 0
    if len(assignment) == len(frequency):
        return assignment
    state = mrv(assignment, frequency)
    choices = lcv(state,assignment,frequency)
    invalid = False
    for freq in choices:
        for neighbor in neighbors[state]:
            if neighbor in assignment and assignment[neighbor] == freq:
                invalid = True
            if invalid == False:
                assignment[state] = freq
                removal_lst = temp_assign(state,freq,frequency)
                if arc_consistent(assignment,frequency,state,removal_lst) == True:
                    if (assign(assignment,frequency)) != None:
                        return True
                for k in remove_lst:
                    (state,val) = k
                    frequency[state].append(val)
    myfunc()
    if state in assignment:
        del assignment[state] 
    return None

# with given constraints, this function search for the solution and report if it does not exist.
def search_solution(frequency):
    assignment = {}
    for state in frequency:                 # Here all those states, which has just one frequency in their domain, have 
        if len(frequency[state])== 1:           # been assigned to the assignment dictionary and then checking it's consistency
            value = (frequency[state])[0]       
            assignment[state] = value
    if arc_consistent(assignment,frequency) == False:   # If legacy_constraints provides such values that no assignment is feasible
        print (" No Solution is Feasible")       # satisfying the constraints, then no solution can be predicted at this stage

    
    if assign(assignment,frequency) == None :
        print (" No assignment is valid")
    else:   
        with open("results.txt","w") as file:
            for key in assignment:
                file.write( str(key) + " :    " + str(assignment[key]))
                file.write("\n")
        file.close()

if __name__ == "__main__":
    load_data()
    search_solution(frequency)  
    end = time.time()
    print (" Total Elapses time:  " + str(end - start))
    print ("\n")
    print ("Number of backtracks:  " + str(myfunc.counter))
代码如下:

Argentina Bolivia Brazil Chile Paraguay Uruguay
Bolivia Argentina Brazil Chile Paraguay Peru
Brazil Argentina Bolivia Colombia Guyana Paraguay Peru Suriname Uruguay Venezuela
Chile Argentina Bolivia Peru
Colombia Brazil Ecuador Peru Venezuela
Ecuador Colombia Peru
Falkland_Islands
Guyana Brazil Suriname Venezuela 
Paraguay Argentina Bolivia Brazil
Peru Bolivia Brazil Chile Colombia Ecuador
Suriname Brazil Guyana
Uruguay Argentina Brazil
Venezuela Brazil Colombia Guyana
import sys
import os
import queue
import time

start = time.time()

neighbors = {}
frequency = {}

def load_data():
    global neighbors,frequency
    with open('adjacent-states', 'r') as file:
        for line in file:
            lst = line.split()
            neighbors[lst[0]] = lst[1:]
    filename = sys.argv[0] 
    with open(filename , 'r') as file:
        try:
            for line in file:
                (city, freq) = line.split()
                frequency[city]=[freq]
        except ValueError:
            frequency = {}
    for key in neighbors:
        if key not in frequency and neighbors[key] != []:   # If a state has no neighbor, We can give any values to it and save the 
            frequency[key] = ['A','B','C','D']      # time in backtracking
        elif key not in frequency:
            frequency[key] = ['A']

# function mrv provides the next state whose frequency should be assigned by the backtracking function. 
# It first checks which state has minimum number of available frequency and in case of tie which has most neighbouring states. 

def mrv(assignment,frequency):
    global neighbors
    len_domain={}
    for key in frequency:
        if key not in assignment:
            len_domain[key]=len(frequency[key])
    val = sorted(len_domain.items(), key=lambda x: x[1])
    min_val = val[0][1]
    highest = 0
    mrv_state = val[0][0]
    for k in val:
        if k[1] > min_val:
            break
        (state,curr) = k
        if len(neighbors[state]) > highest:
            highest = len(neighbors[state])
            mrv_state = state
    return mrv_state

# function lcv returns a list of possible values for a state by ordering values such that value causes least conflict
# comes first in the list

def lcv(state,assignment,frequency):
    choices = frequency[state]
    conflict_queue =queue.PriorityQueue()
    lcv_lst=[]
    for choice in choices:
        value = count_conflicts(state,choice,frequency,assignment)
        conflict_queue.put((value,(choice,)))
    while conflict_queue.empty() is not True:
        (value,(choice,)) = conflict_queue.get()
        lcv_lst.append(choice)
    return lcv_lst



# Temporary assign the value to a state. Remove the rest of the frequency from state's domain,append it to a list and return the list
def temp_assign(state,value,frequency):
    remove_freq = []
    for k in frequency[state]:
        if k != value:
            remove_freq.append((state,k))
    frequency[state]= [value]
    return remove_freq



# Count the number of future conflicts caused by the possible assignment of the frequency to the state.
def count_conflicts(state,choice,frequency,assignment):
    global neighbors
    count = 0
    con_queue = queue.Queue()
    for neighbor in neighbors[state]:
        if neighbor not in assignment:
            con_queue.put((neighbor,choice))
    while not con_queue.empty():
        (state,mychoice) = con_queue.get()
        if len(frequency[state]) == 1 and [choice] == frequency[state] :
            count += 10
        if mychoice in frequency[state]:
            count += 1
    return count
    
# Check whether frequency assignment caused any violation of constraint or not and return the result.
def arc_consistent(assignment,frequency,state=None,remove_lst=None):
    global neighbors
    myqueue = queue.Queue()
    if state == None:
        for state in neighbors:
            for neighbor in neighbors[state]:
                myqueue.put((state,neighbor))
    else:
        for neighbor in neighbors[state]:
            myqueue.put((neighbor,state))
    while not myqueue.empty():
        (state,neighbor) = myqueue.get()
        if remove_inconsistent(state,neighbor,remove_lst):
            if len(frequency[state]) == 0:
                return False
            for new_neigh in neighbors[state]:
                myqueue.put((new_neigh,state))
    return True

# Remove all the frequency from the domain of a state that violates the constraint.
def remove_inconsistent(state,neighbor,remove_lst):
    removed = False
    for freq in frequency[state]:
        if len(frequency[neighbor]) == 1 and [freq] == frequency[neighbor] :
            if remove_lst != None:
                remove_lst.append((state,freq))
            frequency[state].remove(freq)
            removed = True
    return removed

# To count the number of bactracks in the program
def myfunc():
    myfunc.counter += 1
    
        

# Main backtracking function that assigns values to a state and checks whether this assignment violates the constraint or not.
# If an assignment violates the constraints, function removes the assignment and backtrack to try another assignment. This function
# is same as given in textbook and ucb's video lecture. 
def assign(assignment,frequency):
    global neighbors
    myfunc.counter = 0
    if len(assignment) == len(frequency):
        return assignment
    state = mrv(assignment, frequency)
    choices = lcv(state,assignment,frequency)
    invalid = False
    for freq in choices:
        for neighbor in neighbors[state]:
            if neighbor in assignment and assignment[neighbor] == freq:
                invalid = True
            if invalid == False:
                assignment[state] = freq
                removal_lst = temp_assign(state,freq,frequency)
                if arc_consistent(assignment,frequency,state,removal_lst) == True:
                    if (assign(assignment,frequency)) != None:
                        return True
                for k in remove_lst:
                    (state,val) = k
                    frequency[state].append(val)
    myfunc()
    if state in assignment:
        del assignment[state] 
    return None

# with given constraints, this function search for the solution and report if it does not exist.
def search_solution(frequency):
    assignment = {}
    for state in frequency:                 # Here all those states, which has just one frequency in their domain, have 
        if len(frequency[state])== 1:           # been assigned to the assignment dictionary and then checking it's consistency
            value = (frequency[state])[0]       
            assignment[state] = value
    if arc_consistent(assignment,frequency) == False:   # If legacy_constraints provides such values that no assignment is feasible
        print (" No Solution is Feasible")       # satisfying the constraints, then no solution can be predicted at this stage

    
    if assign(assignment,frequency) == None :
        print (" No assignment is valid")
    else:   
        with open("results.txt","w") as file:
            for key in assignment:
                file.write( str(key) + " :    " + str(assignment[key]))
                file.write("\n")
        file.close()

if __name__ == "__main__":
    load_data()
    search_solution(frequency)  
    end = time.time()
    print (" Total Elapses time:  " + str(end - start))
    print ("\n")
    print ("Number of backtracks:  " + str(myfunc.counter))