Recursive routine escape for backtracking routine - python

I was wondering if anyone could help me out with this recursive routine for a sudoku back-tracking problem. I was wanting to get out of the recursive routine when the a certain problem had been executing for a known quantity of time, in this case - 2 seconds. However, I am having some trouble getting this to work and believe there may be something wrong with my base case. Any help would be appreciated.
def solver(Domains,SudokuSolv):
start = time.time()
global global_length
global global_row_index
global global_column_index
global global_val_index
global global_number
if global_length == 0:
return True
else:
global_row_index+=3
global_column_index+=3
global_val_index+=3
print(global_row_index)
row = Domains[global_row_index]
col = Domains[global_column_index]
val = global_val_index
for i in Domains[val]:
end = time.time()
if end-start > 2:
global_length = 0
Checker = isValid(i,row,col,SudokuSolv)
if Checker == False:
SudokuSolv[row][col] = i
print(SudokuSolv)
global_length-= 1
if solver(Domains, SudokuSolv):
return True
global_length+=1
SudokuSolv[row][col] = 0
else:
print("Trying next value...")
global_row_index-=3
global_column_index-=3
global_val_index-=3
return False

Related

Negamax Not Working For Python Chess Engine

I'm making a very simple Python chess engine using the standard Python chess library with a very simple evaluation function; the sum of the total black piece weights (positive) plus the sum of the total white piece weights (negative). The engine always plays as black.
I used the Negamax Wikipedia page for guidance and the depth is to the fourth ply. I don't expect grandmaster performance, but the engine makes very questionable moves, for example: e2e4 and f1c4 for white causes the engine to freely give up it's pawn via b7b5.
Can anyone help me out? I'm completely lost as to what I did wrong. The negamax (called search) and the evaluation function is shown below:
import chess
import time
import math
from time import sleep
from chessboard import display
scoreMovePair = {}
def colorMap(color):
if color == True:
return -1
return 1
def pieceMap(pieceNum):
if pieceNum == 1:
return 1
elif pieceNum == 2:
return 3
elif pieceNum == 3:
return 3
elif pieceNum == 4:
return 5
elif pieceNum == 5:
return 9
return pieceNum
def posEval(board):
score = 0
for i in range(0, 64):
piece = board.piece_at(i)
if piece != None:
score = score + pieceMap(piece.piece_type)*colorMap(piece.color)
return score
def search(board, level, a, b, moveSet, color):
if level == 4:
score = posEval(board)
scoreMovePair[score] = moveSet[0]
return score*color
if board.is_checkmate():
return 1000*colorMap(board.turn)
value = -10000
for move in board.legal_moves:
board.push(move)
moveSet.append(move)
value = max(value, -search(board, level + 1, -b, -a, moveSet, -color))
a = max(a, value)
moveSet.pop()
board.pop()
if (a >= b):
break
return value
def main():
global scoreMovepair
board = chess.Board()
display.start(board.fen())
while not display.checkForQuit():
validMoves = list(board.legal_moves)
if len(validMoves) == 0:
break
else:
move = input("Enter move: ")
t0 = time.time()
move = str(move)
myMove = chess.Move.from_uci(move)
if myMove in validMoves:
board.push_san(move)
value = search(board, 0, -10000, 10000, [], 1)
move = scoreMovePair[value]
print(scoreMovePair)
print("FINAL -> "+str(value))
board.push(move)
print(board.fen())
display.update(board.fen())
sleep(1)
t1 = time.time()
print(t1-t0)
else:
continue
display.terminate()
if __name__ == "__main__":
main()
Just based on a first glance, I would say you may be missing a "quiescence search" (meaning a search for quietness). Also called "captures only search".
https://www.chessprogramming.org/Quiescence_Search
This is a search that is called instead of an evaluation function on your leaf nodes (nodes where max depth is reached). The search makes only capture moves until there are no more captures (with unlimited depth).
In short, without this search, whoever gets the last move in the search (determined by depth) will be able to do anything without consequences. This can lead to some weird results.

Python else block doesn't print anything

Here in this code else block is not printing the value Treasure locked
def counted(value):
if(value == 5):
return 1
else:
return 0
def numb(value1):
sam = 95
value = 0
stp = 97
h = {}
for i in range(0,26):
h.update({chr(stp) : (ord(chr(stp))-sam)})
sam = sam-1
stp = stp+1
for j in range(0,5):
value = h[value1[j]]+value
if(value > 80):
print('First lock-unlocked')
else:
print('Treasure locked')
string = input()
firstcheck = counted(len(string))
if(firstcheck == 1):
numb(string)
a good idea is to check what the condition is before entering the if statements, possibly check what value is printing before the if statement. the logic in def numb() has very little do with what's in def counted(). as long as one is 1 or 0 is being passed to numb() we know that function will run and seems like it.
else block is working properly. if you want to print Treasure Locked. you have to pass lower character string like 'aaaaa'. if value is > 80. then it always print First lock-unlocked.

Don't understand this timed while loop attribute error

So I have been trying to make a while loop that will run for 10 minutes. But is keeps erroring out on the line with the while loop. It says 'str' object has no attribute 'time'.
I have discovered that if i remove the lines with now.strftime() in them that the code runs but I don't know why it runs without those lines or how to fix it.
I did also try to do something using the datetime module instead of importing the time module but this also fails.
import math
from datetime import datetime
import time
test_num = 1
largest_loop = 0
delay = 60 * 10
end_time = time.time() + delay
def even_number(value):
if value == 2:
return True
def divide_five(value):
if value == 5:
return True
def is_square(value):
if math.sqrt(value).is_integer():
return False
def multiple_of(value):
if value == 2:
return True
def is_happy():
global check
if check == 1:
return True
while time.time() <= end_time:
test_num += 1
check = test_num
now = datetime.now()
loop_counter = 0
record_loop = 6
date = now.strftime("%m/%d/%Y")
time = now.strftime("%H:%M:%S")
if even_number(test_num) == True:
if divide_five(test_num) == True:
if is_square(test_num) == True:
for _ in range(record_loop + 4):
loop_counter += 1
if is_happy() == True:
if multiple_of(test_num) == True:
#print(test_num)
record_loop = loop_counter
break
else:
pass
else:
pass
else:
pass
else:
pass
else:
pass
As #CoryKramer pointed out, you named a variable time, which is also the name of the module you are importing. All I really did was change the time variable to something like currTime. Try the code below (runs for me):
import math
from datetime import datetime
import time
test_num = 1
largest_loop = 0
delay = 60 * 10
end_time = time.time() + delay
def even_number(value):
if value == 2:
return True
def divide_five(value):
if value == 5:
return True
def is_square(value):
if math.sqrt(value).is_integer():
return False
def multiple_of(value):
if value == 2:
return True
def is_happy():
global check
if check == 1:
return True
while time.time() <= end_time:
test_num += 1
check = test_num
now = datetime.now()
loop_counter = 0
record_loop = 6
date = now.strftime("%m/%d/%Y")
currTime = now.strftime("%H:%M:%S")
if even_number(test_num) == True:
if divide_five(test_num) == True:
if is_square(test_num) == True:
for _ in range(record_loop + 4):
loop_counter += 1
if is_happy() == True:
if multiple_of(test_num) == True:
#print(test_num)
record_loop = loop_counter
break
else:
pass
else:
pass
else:
pass
else:
pass
else:
pass
Additionally, consider reading up on:
How to name a module without conflict with variable name?
https://en.wikipedia.org/wiki/Variable_shadowing
dont name your variable in your while loop time when you import the time library:
time = now.strftime("%H:%M:%S")
in your while loop you want to use the time function of the time library but as soon as you run the while loop once it will try to use time() on the string time you defined in the while loop.
I think the problem is here:
time = now.strftime("%H:%M:%S")
Thus, you converted time into a string variable. Name this variable in a different way!
Apart from this, running for 10 minutes at "full throttle" is a lot! Consider to introduce a "sleep" time at the end of the while loop (just suggesting)

Start and pause a process in python

I have a function that calculates the Fibonacci numbers. I am trying to add a feature that sends a signal indicating that I need to pause the function running. Once I get the signal, I store away all the numbers calculated thus far.
And when the user wants to resume the function, I can load back the files and start calculating from where we had stopped.
This is the code I have
MAX = 100000
fibo_series = [0] * MAX
import pickle
def fib(start_value=0, stop_value=1000, stop_signal=False):
if not stop_signal:
for i in range(start_value, stop_value):
if i == 0:
fibo_series[i] = 0
elif i == 1 or i == 2:
fibo_series[i] = 1
else:
fibo_series[i] = fibo_series[i-1] + fibo_series[i-2]
return fibo_series[i]
else:
with open('fibo_series.pkl', 'wb') as f:
pickle.dump(fibo_series, f)
def reload_fib():
with open('fibo_series.pkl', 'rb') as f:
fibo_series = pickle.load(f)
start_value = fibo_series[1:].index(0) + 1
stop_value = len(fibo_series)
return fib(start_value, stop_value, stop_signal=False)
The part that I am not able to figure out is how to use this stop_signal once the function has started running. Once the function has started the value stop_signal is locked. The only way I know to pause a function is by terminating it which is not what I am trying to do.
How do I achieve this?
I am not sure what are the stop and run conditions, but a simple work around is to use a global variable for these two functions. This is not better than using a lock of a thread library but if your work is simply to use one process and does not need complexity, then you may try.
import threading
import time
MAX = 100000
fibo_series = [0] * MAX
import pickle
stop_signal = False
def fib(start_value=0, stop_value=1000):
for i in range(start_value, stop_value):
if (not stop_signal):
print('here', i)
time.sleep(1)
if i == 0:
fibo_series[i] = 0
elif i == 1 or i == 2:
fibo_series[i] = 1
else:
fibo_series[i] = fibo_series[i-1] + fibo_series[i-2]
else:
break
return fibo_series[i]
print('exiting... stop_signal: ', stop_signal)
with open('fibo_series.pkl', 'wb') as f:
pickle.dump(fibo_series, f)
def reload_fib():
with open('fibo_series.pkl', 'rb') as f:
fibo_series = pickle.load(f)
start_value = fibo_series[1:].index(0) + 1
stop_value = len(fibo_series)
global stop_signal
stop_signal = False
return fib(start_value, stop_value)
x = threading.Thread(target=fib )
x.start()
time.sleep(10)
stop_signal = True
print('finished...')
Then, whenever the user wants to stop the execution, you can set the global variable stop_signal=True
and the output is:
here 0
here 1
here 2
here 3
here 4
here 5
here 6
here 7
here 8
here 9
finished...
I hope this helps.

Repeatedly replacing parts of a string in a loop

I created a HTML text cleaner, which deletes data between tags.
It's working fine on one iteration, but not in a loop.
The problem is, I cannot save newhtml as a variable due to Python's string immutability.
So, my loop is only working for the last iteration of the function return.
What would be the best practice in such a situation?
def find_all(a_str, sub):
start = 0
while True:
start = a_str.find(sub, start)
if start == -1: return
yield start
start += len(sub) # use start += 1 to find overlapping matches
def replace_string(index1, index2, mainstring):
replacementstring = ''
return mainstring.replace(mainstring[index1:index2], replacementstring)
def strip_images(html):
begin_indexes = list(find_all(html, '<DESCRIPTION>GRAPHIC'))
end_indexes = list(find_all(html, '</TEXT>'))
for i in range(len(begin_indexes)):
if begin_indexes[i] > end_indexes[i]:
end_indexes.pop(0)
else:
if len(begin_indexes) == len(end_indexes):
break
for i in range(len(begin_indexes)):
#code problem is here--
newhtml = replace_string(begin_indexes[i],end_indexes[i], html)
if i == len(begin_indexes) - 1:
return newhtml
#code only returns one iteration
var = strip_images(html)
print var
Your current issue is that html never changes within the loop. So, your input will always be for the first iteration, regardless of the length of the lists.
The solution here follows these steps
Assign the string to the original value before the loop
Edit within the loop, passing in the current content, returning a replaced string
Return from the function after the loop
newhtml = html
for begin, end in zip(begin_indexes, end_indexes):
newhtml = replace_string(begin, end, newhtml)
return newhtml
Got it working, here's the code snippet. It's not pretty but it's doing the job of removing text between those two tags:
def find_all(a_str, sub):
start = 0
while True:
start = a_str.find(sub, start)
if start == -1: return
yield start
start += len(sub) # use start += 1 to find overlapping matches
def strip_images(html):
begin_indexes = list(find_all(html, '<DESCRIPTION>GRAPHIC'))
end_indexes = list(find_all(html, '</TEXT>'))
for i in range(len(begin_indexes)):
if begin_indexes[i] > end_indexes[i]:
end_indexes.pop(0)
else:
if len(begin_indexes) == len(end_indexes):
break
newhtml = html
begin_indexes2 = begin_indexes[::-1]
end_indexes2 = end_indexes[::-1]
for i in range(len(begin_indexes2)):
#for i, value in enumerate(begin_indexes,0):
#end_indexes.reset_index(drop=True)
newhtml = list(newhtml)
del newhtml[begin_indexes2[i]:end_indexes2[i]]
if i == len(begin_indexes2) - 1:
str1 = ''.join(newhtml)
return str1

Categories

Resources