@ -60,7 +60,7 @@ class State:
x : int
x : int
y : int
y : int
ski_position : int
ski_position : int
#velocity: int
velocity : int
def default_value ( ) :
def default_value ( ) :
return { ' action ' : None , ' choiceValue ' : None }
return { ' action ' : None , ' choiceValue ' : None }
@ -77,6 +77,7 @@ def exec(command,verbose=True):
num_tests_per_cluster = 50
num_tests_per_cluster = 50
factor_tests_per_cluster = 0.2
factor_tests_per_cluster = 0.2
num_ski_positions = 8
num_ski_positions = 8
num_velocities = 8
def input_to_action ( char ) :
def input_to_action ( char ) :
if char == " 0 " :
if char == " 0 " :
@ -106,11 +107,11 @@ def saveObservations(observations, verdict, testDir):
ski_position_counter = { 1 : ( Action . LEFT , 40 ) , 2 : ( Action . LEFT , 35 ) , 3 : ( Action . LEFT , 30 ) , 4 : ( Action . LEFT , 10 ) , 5 : ( Action . NOOP , 1 ) , 6 : ( Action . RIGHT , 10 ) , 7 : ( Action . RIGHT , 30 ) , 8 : ( Action . RIGHT , 40 ) }
ski_position_counter = { 1 : ( Action . LEFT , 40 ) , 2 : ( Action . LEFT , 35 ) , 3 : ( Action . LEFT , 30 ) , 4 : ( Action . LEFT , 10 ) , 5 : ( Action . NOOP , 1 ) , 6 : ( Action . RIGHT , 10 ) , 7 : ( Action . RIGHT , 30 ) , 8 : ( Action . RIGHT , 40 ) }
#def run_single_test(ale, nn_wrapper, x,y,ski_position, velocity, duration=50) :
def run_single_test ( ale , nn_wrapper , x , y , ski_position , duration = 50 ) :
def run_single_test ( ale , nn_wrapper , x , y , ski_position , velocity , duration = 50 ) :
#def run_single_test(ale, nn_wrapper, x,y,ski_position, duration=50) :
#print(f"Running Test from x: {x:04}, y: {y:04}, ski_position: {ski_position}", end="")
#print(f"Running Test from x: {x:04}, y: {y:04}, ski_position: {ski_position}", end="")
#testDir = f"{x}_{y}_{ski_position}_{velocity} "
testDir = f " {x}_{y}_{ski_position} "
testDir = f " {x}_{y}_{ski_position}_{velocity} "
#testDir = f"{x}_{y}_{ski_position} "
for i , r in enumerate ( ramDICT [ y ] ) :
for i , r in enumerate ( ramDICT [ y ] ) :
ale . setRAM ( i , r )
ale . setRAM ( i , r )
ski_position_setting = ski_position_counter [ ski_position ]
ski_position_setting = ski_position_counter [ ski_position ]
@ -172,17 +173,16 @@ def fillStateRanking(file_name, match=""):
choices = { key : float ( value ) for ( key , value ) in choices . items ( ) }
choices = { key : float ( value ) for ( key , value ) in choices . items ( ) }
#print("choices", choices)
#print("choices", choices)
#print("ranking_value", ranking_value)
#print("ranking_value", ranking_value)
#state = State(int(stateMapping["x"]), int(stateMapping["y"]), int(stateMapping["ski_position"]), int(stateMapping["velocity"]) )
state = State ( int ( stateMapping [ " x " ] ) , int ( stateMapping [ " y " ] ) , int ( stateMapping [ " ski_position " ] ) )
state = State ( int ( stateMapping [ " x " ] ) , int ( stateMapping [ " y " ] ) , int ( stateMapping [ " ski_position " ] ) , int ( stateMapping [ " velocity " ] ) / / 2 )
#state = State(int(stateMapping["x"]), int(stateMapping["y"]), int(stateMapping["ski_position"]) )
value = StateValue ( ranking_value , choices )
value = StateValue ( ranking_value , choices )
state_ranking [ state ] = value
state_ranking [ state ] = value
logger . info ( f " Parsing state ranking - DONE: took {toc()} seconds " )
logger . info ( f " Parsing state ranking - DONE: took {toc()} seconds " )
return state_ranking
return state_ranking
except EnvironmentError :
except EnvironmentError :
print ( " Ranking file not available. Exiting. " )
print ( " Ranking file not available. Exiting. " )
toc ( )
toc ( )
sys . exit ( 1 )
sys . exit ( - 1 )
except :
except :
toc ( )
toc ( )
@ -190,43 +190,69 @@ def createDisjunction(formulas):
return " | " . join ( formulas )
return " | " . join ( formulas )
def clusterFormula ( cluster ) :
def clusterFormula ( cluster ) :
if len ( cluster ) == 0 : return
formulas = list ( )
for state in cluster :
formulas . append ( f " (x={state[0].x} & y={state[0].y} & velocity={state[0].velocity} & ski_position={state[0].ski_position}) " )
while len ( formulas ) > 1 :
formulas_tmp = [ f " ({formulas[i]} | {formulas[i+1]}) " for i in range ( 0 , len ( formulas ) / / 2 ) ]
if len ( formulas ) % 2 == 1 :
formulas_tmp . append ( formulas [ - 1 ] )
formulas = formulas_tmp
return " ( " + formulas [ 0 ] + " ) "
def clusterFormulaTrimmed ( cluster ) :
formula = " "
formula = " "
#states = [(s[0].x,s[0].y, s[0].ski_position, s[0].velocity) for s in cluster]
states = [ ( s [ 0 ] . x , s [ 0 ] . y , s [ 0 ] . ski_position ) for s in cluster ]
states = [ ( s [ 0 ] . x , s [ 0 ] . y , s [ 0 ] . ski_position , s [ 0 ] . velocity ) for s in cluster ]
#states = [(s[0].x,s[0].y, s[0].ski_position) for s in cluster ]
skiPositionGroup = defaultdict ( list )
skiPositionGroup = defaultdict ( list )
for item in states :
for item in states :
skiPositionGroup [ item [ 2 ] ] . append ( item )
skiPositionGroup [ item [ 2 ] ] . append ( item )
first = True
#todo add velocity here
#todo add velocity here
for skiPosition , group in skiPositionGroup . items ( ) :
formula + = f " ski_position={skiPosition} & ( "
yPosGroup = defaultdict ( list )
for item in group :
yPosGroup [ item [ 1 ] ] . append ( item )
for y , y_group in yPosGroup . items ( ) :
if first :
first = False
firstVelocity = True
for skiPosition , skiPos_group in skiPositionGroup . items ( ) :
formula + = f " ski_position={skiPosition} & "
velocityGroup = defaultdict ( list )
for item in skiPos_group :
velocityGroup [ item [ 3 ] ] . append ( item )
for velocity , velocity_group in velocityGroup . items ( ) :
if firstVelocity :
firstVelocity = False
else :
else :
formula + = " | "
formula + = " | "
sorted_y_group = sorted ( y_group , key = lambda s : s [ 0 ] )
formula + = f " ( y={y} & ( "
current_x_min = sorted_y_group [ 0 ] [ 0 ]
current_x = sorted_y_group [ 0 ] [ 0 ]
x_ranges = list ( )
for state in sorted_y_group [ 1 : - 1 ] :
if state [ 0 ] - current_x == 1 :
current_x = state [ 0 ]
formula + = f " (velocity={velocity} & "
firstY = True
yPosGroup = defaultdict ( list )
for item in velocity_group :
yPosGroup [ item [ 1 ] ] . append ( item )
for y , y_group in yPosGroup . items ( ) :
if firstY :
firstY = False
else :
else :
x_ranges . append ( f " ({current_x_min}<= x & x<={current_x}) " )
current_x_min = state [ 0 ]
current_x = state [ 0 ]
x_ranges . append ( f " ({current_x_min}<= x & x<={sorted_y_group[-1][0]}) " )
formula + = " | " . join ( x_ranges )
formula + = " ) ) "
formula + = " ) "
formula + = " | "
sorted_y_group = sorted ( y_group , key = lambda s : s [ 0 ] )
formula + = f " ( y={y} & ( "
current_x_min = sorted_y_group [ 0 ] [ 0 ]
current_x = sorted_y_group [ 0 ] [ 0 ]
x_ranges = list ( )
for state in sorted_y_group [ 1 : - 1 ] :
if state [ 0 ] - current_x == 1 :
current_x = state [ 0 ]
else :
x_ranges . append ( f " ({current_x_min}<= x & x<={current_x}) " )
current_x_min = state [ 0 ]
current_x = state [ 0 ]
x_ranges . append ( f " ({current_x_min}<= x & x<={sorted_y_group[-1][0]}) " )
formula + = " | " . join ( x_ranges )
formula + = " ) ) "
formula + = " ) "
return formula
return formula
def createBalancedDisjunction ( indices , name ) :
def createBalancedDisjunction ( indices , name ) :
#logger.info(f"Creating balanced disjunction for {len(indices)} ({indices}) formulas")
#logger.info(f"Creating balanced disjunction for {len(indices)} ({indices}) formulas")
if len ( indices ) == 0 :
if len ( indices ) == 0 :
@ -245,9 +271,9 @@ def createUnsafeFormula(clusters):
formulas = " "
formulas = " "
indices = list ( )
indices = list ( )
for i , cluster in enumerate ( clusters ) :
for i , cluster in enumerate ( clusters ) :
formulas + = f " formula Unsafe_{i} = {clusterFormula(cluster)}; \n "
formulas + = f " formula Unsafe_{i} = {clusterFormulaTrimmed (cluster)}; \n "
indices . append ( f " Unsafe_{i} " )
indices . append ( f " Unsafe_{i} " )
return formulas + " \n " + createBalancedDisjunction ( indices , " Unsafe " ) + label
return formulas + " \n " + createBalancedDisjunction ( indices , " Unsafe " ) # + label
def createSafeFormula ( clusters ) :
def createSafeFormula ( clusters ) :
label = " label \" Safe \" = Safe; \n "
label = " label \" Safe \" = Safe; \n "
@ -257,7 +283,7 @@ def createSafeFormula(clusters):
formulas + = f " formula Safe_{i} = {clusterFormula(cluster)}; \n "
formulas + = f " formula Safe_{i} = {clusterFormula(cluster)}; \n "
indices . append ( f " Safe_{i} " )
indices . append ( f " Safe_{i} " )
return formulas + " \n " + createBalancedDisjunction ( indices , " Safe " ) + label
return formulas + " \n " + createBalancedDisjunction ( indices , " Safe " ) # + label
def updatePrismFile ( newFile , iteration , safeStates , unsafeStates ) :
def updatePrismFile ( newFile , iteration , safeStates , unsafeStates ) :
logger . info ( " Creating next prism file " )
logger . info ( " Creating next prism file " )
@ -299,25 +325,32 @@ markerSize = 1
imagesDir = f " images/testing_{experiment_id} "
imagesDir = f " images/testing_{experiment_id} "
def drawOntoSkiPosImage ( states , color , target_prefix = " cluster_ " , alpha_factor = 1.0 ) :
def drawOntoSkiPosImage ( states , color , target_prefix = " cluster_ " , alpha_factor = 1.0 ) :
markerList = { ski_position : list ( ) for ski_position in range ( 1 , num_ski_positions + 1 ) }
#markerList = {ski_position:list() for ski_position in range(1,num_ski_positions + 1)}
markerList = { ( ski_position , velocity ) : list ( ) for velocity in range ( 0 , num_velocities + 1 ) for ski_position in range ( 1 , num_ski_positions + 1 ) }
for state in states :
for state in states :
s = state [ 0 ]
s = state [ 0 ]
#marker = f"-fill 'rgba({color}, {alpha_factor * state[1].ranking})' -draw 'rectangle {s.x-markerSize},{s.y-markerSize} {s.x+markerSize},{s.y+markerSize} '"
#marker = f"-fill 'rgba({color}, {alpha_factor * state[1].ranking})' -draw 'rectangle {s.x-markerSize},{s.y-markerSize} {s.x+markerSize},{s.y+markerSize} '"
marker = f " -fill ' rgba({color}, {alpha_factor * state[1].ranking}) ' -draw ' point {s.x},{s.y} ' "
marker = f " -fill ' rgba({color}, {alpha_factor * state[1].ranking}) ' -draw ' point {s.x},{s.y} ' "
markerList [ s . ski_position ] . append ( marker )
for pos , marker in markerList . items ( ) :
command = f " convert {imagesDir}/{target_prefix}_{pos:02}_individual.png { ' ' .join(marker)} {imagesDir}/{target_prefix}_{pos:02}_individual.png "
markerList [ ( s . ski_position , s . velocity ) ] . append ( marker )
for ( pos , vel ) , marker in markerList . items ( ) :
command = f " convert {imagesDir}/{target_prefix}_{pos:02}_{vel:02}_ individual.png { ' ' .join(marker)} {imagesDir}/{target_prefix}_{pos:02}_{vel :02}_individual.png "
exec ( command , verbose = False )
exec ( command , verbose = False )
def concatImages ( prefix , iteration ) :
def concatImages ( prefix , iteration ) :
exec ( f " montage {imagesDir}/{prefix}_*_individual.png -geometry +0+0 -tile x1 {imagesDir}/{prefix}_{iteration}.png " , verbose = False )
exec ( f " sxiv {imagesDir}/{prefix}_{iteration}.png& " , verbose = False )
images = [ f " {imagesDir}/{prefix}_{pos:02}_{vel:02}_individual.png " for vel in range ( 0 , num_velocities + 1 ) for pos in range ( 1 , num_ski_positions + 1 ) ]
for vel in range ( 0 , num_velocities + 1 ) :
for pos in range ( 1 , num_ski_positions + 1 ) :
command = f " convert {imagesDir}/{prefix}_{pos:02}_{vel:02}_individual.png "
command + = f " -pointsize 10 -gravity NorthEast -annotate +8+0 ' p{pos:02}v{vel:02} ' "
command + = f " {imagesDir}/{prefix}_{pos:02}_{vel:02}_individual.png "
exec ( command , verbose = False )
exec ( f " montage { ' ' .join(images)} -geometry +0+0 -tile 8x9 {imagesDir}/{prefix}_{iteration}.png " , verbose = False )
#exec(f"sxiv {imagesDir}/{prefix}_{iteration}.png&", verbose=False)
def drawStatesOntoTiledImage ( states , color , target , source = " images/1_full_scaled_down.png " , alpha_factor = 1.0 ) :
def drawStatesOntoTiledImage ( states , color , target , source = " images/1_full_scaled_down.png " , alpha_factor = 1.0 ) :
"""
"""
Useful to draw a set of states , e . g . a single cluster
Useful to draw a set of states , e . g . a single cluster
"""
markerList = { 1 : list ( ) , 2 : list ( ) , 3 : list ( ) , 4 : list ( ) , 5 : list ( ) , 6 : list ( ) , 7 : list ( ) , 8 : list ( ) }
markerList = { 1 : list ( ) , 2 : list ( ) , 3 : list ( ) , 4 : list ( ) , 5 : list ( ) , 6 : list ( ) , 7 : list ( ) , 8 : list ( ) }
logger . info ( f " Drawing {len(states)} states onto {target} " )
logger . info ( f " Drawing {len(states)} states onto {target} " )
tic ( )
tic ( )
@ -330,20 +363,27 @@ def drawStatesOntoTiledImage(states, color, target, source="images/1_full_scaled
exec ( command , verbose = False )
exec ( command , verbose = False )
exec ( f " montage {imagesDir}/{target}_*_individual.png -geometry +0+0 -tile x1 {imagesDir}/{target}.png " , verbose = False )
exec ( f " montage {imagesDir}/{target}_*_individual.png -geometry +0+0 -tile x1 {imagesDir}/{target}.png " , verbose = False )
logger . info ( f " Drawing {len(states)} states onto {target} - Done: took {toc()} seconds " )
logger . info ( f " Drawing {len(states)} states onto {target} - Done: took {toc()} seconds " )
"""
def drawClusters ( clusterDict , target , iteration , alpha_factor = 1.0 ) :
def drawClusters ( clusterDict , target , iteration , alpha_factor = 1.0 ) :
for ski_position in range ( 1 , num_ski_positions + 1 ) :
source = " images/1_full_scaled_down.png "
exec ( f " cp {source} {imagesDir}/{target}_{ski_position:02}_individual.png " , verbose = False )
logger . info ( f " Drawing clusters " )
tic ( )
for velocity in range ( 0 , num_velocities + 1 ) :
for ski_position in range ( 1 , num_ski_positions + 1 ) :
source = " images/1_full_scaled_down.png "
exec ( f " cp {source} {imagesDir}/{target}_{ski_position:02}_{velocity:02}_individual.png " , verbose = False )
for _ , clusterStates in clusterDict . items ( ) :
for _ , clusterStates in clusterDict . items ( ) :
color = f " {np.random.choice(range(256))}, {np.random.choice(range(256))}, {np.random.choice(range(256))} "
color = f " {np.random.choice(range(256))}, {np.random.choice(range(256))}, {np.random.choice(range(256))} "
drawOntoSkiPosImage ( clusterStates , color , target , alpha_factor = alpha_factor )
drawOntoSkiPosImage ( clusterStates , color , target , alpha_factor = alpha_factor )
concatImages ( target , iteration )
concatImages ( target , iteration )
logger . info ( f " Drawing clusters - DONE: took {toc()} seconds " )
def drawResult ( clusterDict , target , iteration ) :
def drawResult ( clusterDict , target , iteration ) :
for ski_position in range ( 1 , num_ski_positions + 1 ) :
source = " images/1_full_scaled_down.png "
exec ( f " cp {source} {imagesDir}/{target}_{ski_position:02}_individual.png " )
logger . info ( f " Drawing clusters " )
for velocity in range ( 0 , num_velocities + 1 ) :
for ski_position in range ( 1 , num_ski_positions + 1 ) :
source = " images/1_full_scaled_down.png "
exec ( f " cp {source} {imagesDir}/{target}_{ski_position:02}_{velocity:02}_individual.png " , verbose = False )
for _ , ( clusterStates , result ) in clusterDict . items ( ) :
for _ , ( clusterStates , result ) in clusterDict . items ( ) :
color = " 100,100,100 "
color = " 100,100,100 "
if result == Verdict . GOOD :
if result == Verdict . GOOD :
@ -352,6 +392,7 @@ def drawResult(clusterDict, target, iteration):
color = " 200,0,0 "
color = " 200,0,0 "
drawOntoSkiPosImage ( clusterStates , color , target , alpha_factor = 0.7 )
drawOntoSkiPosImage ( clusterStates , color , target , alpha_factor = 0.7 )
concatImages ( target , iteration )
concatImages ( target , iteration )
logger . info ( f " Drawing clusters - DONE: took {toc()} seconds " )
def _init_logger ( ) :
def _init_logger ( ) :
logger = logging . getLogger ( ' main ' )
logger = logging . getLogger ( ' main ' )
@ -364,8 +405,8 @@ def _init_logger():
def clusterImportantStates ( ranking , iteration ) :
def clusterImportantStates ( ranking , iteration ) :
logger . info ( f " Starting to cluster {len(ranking)} states into clusters " )
logger . info ( f " Starting to cluster {len(ranking)} states into clusters " )
tic ( )
tic ( )
#states = [[s[0].x,s[0].y, s[0].ski_position * 10, s[0].velocity * 10, s[1].ranking] for s in ranking ]
states = [ [ s [ 0 ] . x , s [ 0 ] . y , s [ 0 ] . ski_position * 30 , s [ 1 ] . ranking ] for s in ranking ]
states = [ [ s [ 0 ] . x , s [ 0 ] . y , s [ 0 ] . ski_position * 20 , s [ 0 ] . velocity * 20 , s [ 1 ] . ranking ] for s in ranking ]
#states = [[s[0].x,s[0].y, s[0].ski_position * 30, s[1].ranking] for s in ranking ]
#kmeans = KMeans(n_clusters, random_state=0, n_init="auto").fit(states)
#kmeans = KMeans(n_clusters, random_state=0, n_init="auto").fit(states)
dbscan = DBSCAN ( eps = 15 ) . fit ( states )
dbscan = DBSCAN ( eps = 15 ) . fit ( states )
labels = dbscan . labels_
labels = dbscan . labels_
@ -400,7 +441,7 @@ if __name__ == '__main__':
for id , cluster in clusters . items ( ) :
for id , cluster in clusters . items ( ) :
num_tests = int ( factor_tests_per_cluster * len ( cluster ) )
num_tests = int ( factor_tests_per_cluster * len ( cluster ) )
num_tests = 1
num_tests = 1
logger . info ( f " Testing {num_tests} states (from {len(cluster)} states) from cluster {id} ")
#logger.info(f" Testing {num_tests} states (from {len(cluster)} states) from cluster {id}")
randomStates = np . random . choice ( len ( cluster ) , num_tests , replace = False )
randomStates = np . random . choice ( len ( cluster ) , num_tests , replace = False )
randomStates = [ cluster [ i ] for i in randomStates ]
randomStates = [ cluster [ i ] for i in randomStates ]
@ -409,9 +450,9 @@ if __name__ == '__main__':
x = state [ 0 ] . x
x = state [ 0 ] . x
y = state [ 0 ] . y
y = state [ 0 ] . y
ski_pos = state [ 0 ] . ski_position
ski_pos = state [ 0 ] . ski_position
#velocity = state[0]. velocity
result = run_single_test ( ale , nn_wrapper , x , y , ski_pos , duration = 50 )
#result = run_single_test(ale,nn_wrapper,x,y,ski_pos, velocity, duration=50 )
velocity = state [ 0 ] . velocity
#result = run_single_test(ale,nn_wrapper,x,y,ski_pos, duration=50 )
result = run_single_test ( ale , nn_wrapper , x , y , ski_pos , velocity , duration = 50 )
result = Verdict . BAD # TODO REMOVE ME!!!!!!!!!!!!!!
result = Verdict . BAD # TODO REMOVE ME!!!!!!!!!!!!!!
if result == Verdict . BAD :
if result == Verdict . BAD :
if testAll :
if testAll :
@ -427,7 +468,7 @@ if __name__ == '__main__':
logger . info ( f " Iteration: {iteration:03} - \t Safe Results : {sum([len(c) for c in safeStates])} - \t Unsafe Results:{sum([len(c) for c in unsafeStates])} " )
logger . info ( f " Iteration: {iteration:03} - \t Safe Results : {sum([len(c) for c in safeStates])} - \t Unsafe Results:{sum([len(c) for c in unsafeStates])} " )
if testAll : drawClusters ( failingPerCluster , f " failing " , iteration )
if testAll : drawClusters ( failingPerCluster , f " failing " , iteration )
drawResult ( clusterResult , " result " , iteration )
#drawResult(clusterResult, "result", iteration )
iteration + = 1
iteration + = 1