##################################################### # Finding the Trees for the Apex of the Naruki cone # ##################################################### # If the valuation on the Cross functions are the expected ones, all anticanonical coordinates of the tropical nodes can be determined. If the valuations are higher than expected, some entries on the tropical nodes become unknown, yielding to jumps. For the apex, all Cross functions have unknown true valuations and their expected valuations are zero. # The goal of this script is to understand these differences. We go over all nodes and all lines and analyze the structure of the true and expected tropical matrices for the apex # We create the tropical matrices with 'None' for each cone and each extremal curve, and study the blocks of 4 columns associated to each of the nodes (rows of the matrix). We know all these columns differ by a multiple of the all-ones vector. In principle, it is possible that one column has all None entries, wheather another one has no indeterminates. We show that this happens in almost all cases. # Blocks for a given cone and extremal curve will be indexed by a node. # When we can find a column without nones on each block, we can project to the resulting P^9 and conclude that the trees behave as in the generic case. Those combinations of cone and lines with good projections are listed in the dictionary 'linesPerConeWithGoodProjectionsApex'. # When we cannot find a good column on each block, we must analyze how bad the block is. Even though all the Columns have 9 None entries on each column, we find that all the entries share one Cross summand. Only one of the entries of each column has two summands. We remove the common factor from each Column and reduce our computations to a single bad entry per column. # With this information, we build the dictionary of relevant coordinates and shifted matrices that we will use for the apex as well as the other non-apex cones on the Naruki fan. We pick the first entry from each block. We label all blocks Bad since there is a 'None' entry on each. # The file 'Input/newcolsForNoGoodProjectionsApex.sobj' records the columns we must choose for each extremal curve. We will use it in 'ComputationsWithNoGoodProjectionsApex.sage' # We start by describing the steps: # STEP 0: Setting up the ambient rings with the W(E6) action, the Cross functions, and Tropical Nodes. # STEP 1: Construction of tropical nodes for the apex, collection of all Cross summands with unknown valuations, classification of 'None' entries per cone and extremal curve, construction of '+Infinity' blocks of relevant anticanonical coordinates. # STEP 2: Analysis of blocks, selection of relevant columns, construction of shifted matrices and selection of relevant Cross functions after shifting. # STEP 3: Classifying entries on Shifted matrices and certifying that the same cross functions appear among Symmetric entries with Cross summands. # STEP 4: Finding Cross functions per extremal, computation of parameters g0,...,g4 recording differences between true and expected valution of the 5 Cross summands appearing on each matrix, and computation of generic and non-generic shifted matrices. # STEP 5: Algorithms for construction of trees. # STEP 6: Construction of trees and leaf labeling from the Shifted matrices. # STEP 7: Measuring distance between adjacent vertices of a tree. # STEP 8: Computations of all vertices, leaves and edge lengths for combinations of extremals and cones for the Apex. ####################################################################################################### # STEP 0: Setting up the ambient rings with the W(E6) action, the Cross functions, and Tropical Nodes # ####################################################################################################### # A list of variables d_1, ..., d_6 for the coefficients ds = [var("d%s"%i) for i in range(1,7)] # A list of variables E_1, ..., E_6 Es = [var("E%s"%i) for i in range(1,7)] # A list of variables F_12, ..., F_56 Fs = [var("F%s%s"%(i,j)) for i in range(1,7) for j in range(1,7) if i < j] # A list of variables G_1, ..., G_6 Gs = [var("G%s"%i) for i in range(1,7)] # A list of variables X_12, ..., X_65 Xs = [var("X%s%s"%(i,j)) for i in range(1,7) for j in range(1,7) if i != j] # A list of variables Y_123456, ..., Y_162534 Ys = [var("Y%s%s%s%s%s%s"%(i,j,k,l,m,n)) for i in range(1,7) for j in range(1,7) for k in range(1,7) for l in range(1,7) for m in range(1,7) for n in range(1,7) if i0: neweq = equations.pop() pairFornewEq = [rowcol for rowcol in equations if rowcol == (neweq[1], neweq[0])] if pairFornewEq != []: equations = [rowcol for rowcol in equations if rowcol !=pairFornewEq[0]] symmetricPairs = symmetricPairs + [[neweq,pairFornewEq[0]]] else: # print 'no pair for ' + str(neweq) continue return symmetricPairs #################### # Classify entries # #################### # The following function takes a given element of the list AllEntriesByLength (e.g. AllEntriesByLength[26][0]) and classifies the entries: def classifyEntries(allEntries): entriesAndCols = extractVBColumns(allEntries) # return (generateSymmetricPairs(entriesAndCols[0]), entriesAndCols[1]) return (generateSymmetricPairs(allEntries), entriesAndCols) ############################################### # Constructing ratios for each extremal curve # ############################################### # Now that we can classify entries, our next step is to generate the ratios. We have ratios of three types: # 1) symmetric pairs # 2) non-symmetric pairs (between the first tuple of each symmetric pair) # 3) all pairs within a column # The common sub-routine in all takes a list of pairs and generates all ordered pairs (binomial(len(list),2) many) to make the comparisons. This is the role of the function generateAllPairs (the input is a list) # The following functions are used for computing ratios for each type of pairs listed above: # 1) compareSymmetricPairs # 2) compareNonSymmetricPairs # 3) generateRatiosForCols # Procedure for columns has three steps and functions associated to each: # 1) 'generateRatiosForCols' takes all 36 pairs among the 9 relevant entries of a VB column, # 2) 'classifyPairsForColumns' classify pairs with valid ratios by an equivalence class and record the ratios with respect to the first element of the class. # 3) 'treatCols' combines the previous two functions. # The inputs for all the above functions are: # extremal = an extremal curve (i.e. keys in the dictionary 'newNoneEntriesCrossFactorsApex'). # newNoneEntriesCrossFactorsApex = the dictionary of Cross factors for each entry with 'None' valuation. ############################### # Generating Pairs to compare # ############################### # The next function generates all pairs of distinct elements from a list. def generatePairs(allEntries): n = len(allEntries) return [(allEntries[i],allEntries[j]) for i in range(0,n-1) for j in range(i+1,n)] ############################# # Comparing symmetric pairs # ############################# # The following function takes a list of symmetric pairs, computes their ratios and returns a list of tuples. The first entry of each tuple is a pair of symmetric entries, and the second is their ratio written as a Laurent monomial in Yoshidas whenever possible, or False, if it's not. # extremal = an extremal curve # newNoneEntriesCrossFactors is the dictionary of Cross factors for each entry with 'None' valuation for the Shifted matrices # pairsOfEntries = list of symmetric pairs def compareSymmetricPairs(pairsOfEntries, extremal, newNoneEntriesCrossFactors): ratioSymmetricPairs = dict() for k in range(0,len(pairsOfEntries)): x = sorted(pairsOfEntries[k]) print str(x) cr0 =newNoneEntriesCrossFactors[extremal][x[0]] cr1 =newNoneEntriesCrossFactors[extremal][x[1]] print cr0 print cr1 ratioSymmetricPairs[k] = bool(cr0 == cr1) return [(sorted(pairsOfEntries[k]), ratioSymmetricPairs[k]) for k in range(0,len(pairsOfEntries))] ################################# # Comparing non-symmetric pairs # ################################# # The next function takes the first tuple (row,col) of each of the symmetric pairs and computes the ratios that are monomials in Yoshidas. We expect the output will be [] in almost all cases. # pairsOfEntries = list of pairs of entries (either symmetric or pairs of valid ratios for a VB column) def compareNonSymmetricPairs(pairsOfEntries, extremal, newNoneEntriesCrossFactors): spairsOfEntries = [sorted(x) for x in pairsOfEntries] firstOfEachPair = sorted([x[0] for x in spairsOfEntries]) nonSymmPairs = generatePairs(firstOfEachPair) ratioNonSymmetricPairs = [] for x in nonSymmPairs: x = sorted(x) print str(x) cr0 =newNoneEntriesCrossFactors[extremal][x[0]] cr1 =newNoneEntriesCrossFactors[extremal][x[1]] print cr0 print cr1 newRatio = bool(cr0 == cr1) if newRatio == False: print 'pair does not work!' else: ratioNonSymmetricPairs = ratioNonSymmetricPairs + [(x,newRatio)] return ratioNonSymmetricPairs ################################### # Generating ratios for all trees # ################################### # The functions described above allow us to generate all possible ratios (symmetric, non-symmetric and within each VB column) for all valid combinations (triple, cone,extremal). We create a function for a single tree (associated to a fixed tce) and then generate a dictionary recording this information for all trees. ##################################### # Generate ratios for a single tree # ##################################### # The following function ('generateRatiosForOneTree') generates the ratios for a given tree (indexed by tce).It outputs a tuple of valid ratios for symmetric pairs, ratios for non-symmetric paris (not in a VB column) and ratios for equivalence classes withing each VB column. # Inputs: # extremal = a key in the dictionary 'newNoneEntriesCrossFactorsApex'). # allEntries = the dictionary 'newNoneEntriesCrossFactorsApex' # newNoneEntriesCrossFactors = the dictionary of Cross factors for each entry with 'None' valuation. def generateRatiosForOneTree(extremal, newNoneEntriesCrossFactors): # we classify the entries into pairs of symmetric entries and dictionaries of columns: allEntries = newNoneEntriesCrossFactors[extremal] (pairsOfEntries, dict_cols) = classifyEntries(allEntries) # generate the ratios for columns by equivalence classes ratiosForCols =dict() for i in dict_cols.keys(): ratiosForCols[i] = treatCols(dict_cols[i], extremal, newNoneEntriesCrossFactors) # print ratiosForCols # generate and compare ratios for symmetric pairs and nonSymmPairs symmRatios = compareSymmetricPairs(pairsOfEntries, extremal, newNoneEntriesCrossFactors) # print symmRatios nonSymRatios = compareNonSymmetricPairs(pairsOfEntries, extremal, newNoneEntriesCrossFactors) # print symmRatios return (symmRatios,nonSymRatios,ratiosForCols) ################################################ # Dictionary of ratios for all extremal curves # ################################################ # Finally, we create the dictionary 'allRatiosForApex' of all ratios for the shifted 10x10 matrices. allRatiosForApex = dict() for extremal in extremalCurves: print str(extremal) allRatiosForApex[extremal] = generateRatiosForOneTree(extremal, newNoneEntriesCrossFactorsApex) print 'Done with ' + str(extremal) # # We confirm that the second and third entry of each allRatiosForApex[extremal] are [] and dict(), respectively: # [extremal for extremal in extremalCurves if allRatiosForApex[extremal][1]!=[]] # [] # [extremal for extremal in extremalCurves if allRatiosForApex[extremal][2]!=dict()] # [] # # We check that there are five symmetric pairs, and symmetric ratios are valid: # [extremal for extremal in extremalCurves if len(allRatiosForApex[extremal][0]) != 5] [] # [extremal for extremal in extremalCurves if False in [x[1] for x in allRatiosForApex[extremal][0]]] # [] # # We record the output: # for extremal in extremalCurves: # print str(extremal) # print allRatiosForApex[extremal] # E1 # ([([(0, 4), (4, 0)], True), ([(5, 9), (9, 5)], True), ([(3, 8), (8, 3)], True), ([(1, 2), (2, 1)], True), ([(6, 7), (7, 6)], True)], [], {}) # E2 # ([([(3, 5), (5, 3)], True), ([(0, 2), (2, 0)], True), ([(1, 4), (4, 1)], True), ([(8, 9), (9, 8)], True), ([(6, 7), (7, 6)], True)], [], {}) # E3 # ([([(3, 5), (5, 3)], True), ([(2, 4), (4, 2)], True), ([(0, 9), (9, 0)], True), ([(1, 8), (8, 1)], True), ([(6, 7), (7, 6)], True)], [], {}) # E4 # ([([(7, 8), (8, 7)], True), ([(1, 6), (6, 1)], True), ([(0, 9), (9, 0)], True), ([(2, 3), (3, 2)], True), ([(4, 5), (5, 4)], True)], [], {}) # E5 # ([([(1, 4), (4, 1)], True), ([(0, 9), (9, 0)], True), ([(3, 6), (6, 3)], True), ([(5, 7), (7, 5)], True), ([(2, 8), (8, 2)], True)], [], {}) # E6 # ([([(1, 5), (5, 1)], True), ([(4, 9), (9, 4)], True), ([(2, 6), (6, 2)], True), ([(3, 8), (8, 3)], True), ([(0, 7), (7, 0)], True)], [], {}) # F12 # ([([(4, 8), (8, 4)], True), ([(6, 9), (9, 6)], True), ([(0, 1), (1, 0)], True), ([(2, 3), (3, 2)], True), ([(5, 7), (7, 5)], True)], [], {}) # F13 # ([([(3, 5), (5, 3)], True), ([(0, 2), (2, 0)], True), ([(7, 8), (8, 7)], True), ([(1, 9), (9, 1)], True), ([(4, 6), (6, 4)], True)], [], {}) # F14 # ([([(7, 9), (9, 7)], True), ([(5, 6), (6, 5)], True), ([(1, 4), (4, 1)], True), ([(0, 8), (8, 0)], True), ([(2, 3), (3, 2)], True)], [], {}) # F15 # ([([(5, 9), (9, 5)], True), ([(2, 3), (3, 2)], True), ([(1, 8), (8, 1)], True), ([(0, 7), (7, 0)], True), ([(4, 6), (6, 4)], True)], [], {}) # F16 # ([([(7, 9), (9, 7)], True), ([(5, 8), (8, 5)], True), ([(2, 4), (4, 2)], True), ([(0, 1), (1, 0)], True), ([(3, 6), (6, 3)], True)], [], {}) # F23 # ([([(4, 8), (8, 4)], True), ([(2, 7), (7, 2)], True), ([(6, 9), (9, 6)], True), ([(0, 3), (3, 0)], True), ([(1, 5), (5, 1)], True)], [], {}) # F24 # ([([(5, 6), (6, 5)], True), ([(0, 3), (3, 0)], True), ([(1, 7), (7, 1)], True), ([(4, 9), (9, 4)], True), ([(2, 8), (8, 2)], True)], [], {}) # F25 # ([([(3, 5), (5, 3)], True), ([(2, 7), (7, 2)], True), ([(6, 9), (9, 6)], True), ([(0, 4), (4, 0)], True), ([(1, 8), (8, 1)], True)], [], {}) # F26 # ([([(1, 4), (4, 1)], True), ([(3, 7), (7, 3)], True), ([(0, 5), (5, 0)], True), ([(2, 6), (6, 2)], True), ([(8, 9), (9, 8)], True)], [], {}) # F34 # ([([(3, 5), (5, 3)], True), ([(0, 1), (1, 0)], True), ([(6, 7), (7, 6)], True), ([(4, 9), (9, 4)], True), ([(2, 8), (8, 2)], True)], [], {}) # F35 # ([([(2, 6), (6, 2)], True), ([(1, 3), (3, 1)], True), ([(8, 9), (9, 8)], True), ([(0, 7), (7, 0)], True), ([(4, 5), (5, 4)], True)], [], {}) # F36 # ([([(2, 7), (7, 2)], True), ([(3, 4), (4, 3)], True), ([(0, 1), (1, 0)], True), ([(6, 8), (8, 6)], True), ([(5, 9), (9, 5)], True)], [], {}) # F45 # ([([(7, 9), (9, 7)], True), ([(3, 8), (8, 3)], True), ([(0, 6), (6, 0)], True), ([(1, 2), (2, 1)], True), ([(4, 5), (5, 4)], True)], [], {}) # F46 # ([([(0, 8), (8, 0)], True), ([(3, 7), (7, 3)], True), ([(1, 9), (9, 1)], True), ([(2, 6), (6, 2)], True), ([(4, 5), (5, 4)], True)], [], {}) # F56 # ([([(0, 4), (4, 0)], True), ([(3, 6), (6, 3)], True), ([(5, 7), (7, 5)], True), ([(1, 8), (8, 1)], True), ([(2, 9), (9, 2)], True)], [], {}) # G1 # ([([(5, 8), (8, 5)], True), ([(0, 6), (6, 0)], True), ([(4, 7), (7, 4)], True), ([(1, 3), (3, 1)], True), ([(2, 9), (9, 2)], True)], [], {}) # G2 # ([([(0, 2), (2, 0)], True), ([(3, 8), (8, 3)], True), ([(5, 9), (9, 5)], True), ([(1, 6), (6, 1)], True), ([(4, 7), (7, 4)], True)], [], {}) # G3 # ([([(4, 8), (8, 4)], True), ([(2, 5), (5, 2)], True), ([(3, 7), (7, 3)], True), ([(0, 9), (9, 0)], True), ([(1, 6), (6, 1)], True)], [], {}) # G4 # ([([(0, 3), (3, 0)], True), ([(4, 9), (9, 4)], True), ([(1, 6), (6, 1)], True), ([(5, 7), (7, 5)], True), ([(2, 8), (8, 2)], True)], [], {}) # G5 # ([([(5, 8), (8, 5)], True), ([(0, 2), (2, 0)], True), ([(1, 6), (6, 1)], True), ([(3, 9), (9, 3)], True), ([(4, 7), (7, 4)], True)], [], {}) # G6 # ([([(5, 6), (6, 5)], True), ([(3, 4), (4, 3)], True), ([(0, 1), (1, 0)], True), ([(2, 9), (9, 2)], True), ([(7, 8), (8, 7)], True)], [], {}) ######################################################################## # Checking exponents of all Cross factors with undetermined Valuations # ######################################################################## # # We start by checking there is a single Cross summand with undetermined valuations for relevant entry of a given tce combination with VB=0: # all([1 == len(newNoneEntriesCrossFactorsApex[extremal][key]) for extremal in extremalCurves for key in newNoneEntriesCrossFactorsApex[extremal].keys()]) # True # # Each value of the dictionary is (scalar, Cross). We check the scalar of the unique Cross summand on each list: # all([1 == newNoneEntriesCrossFactorsApex[extremal][key][0][0] for extremal in extremalCurves for key in newNoneEntriesCrossFactorsApex[extremal].keys()]) # True ################################################################################### # STEP 4: Computation of generic and non-generic shifted matrices, and parameters # ################################################################################### # We load the shifted matrices. We compute the expected and true tropicalization of the 10x10 matrix. The expected tropicalization is obtained by replacing the Cross functions by the expected valuations plus a variable, whenever the true valuation is unknown ###################################################### # Adjusting the expected valuations with parameters # ###################################################### # We star by recording all the crosses involved in the shifted matrices: allCrossesApex = sorted([x[1] for x in list(set(combineLists([combineLists(newNoneEntriesCrossFactorsApex[extremal].values()) for extremal in extremalCurves])))], reverse=True) # print allCrossesApex # [Cross0, Cross3, Cross6, Cross9, Cross12, Cross15, Cross18, Cross21, Cross24, Cross28, Cross30, Cross33, Cross37, Cross41, Cross42, Cross45, Cross48, Cross51, Cross54, Cross57, Cross60, Cross63, Cross66, Cross69, Cross73, Cross76, Cross78, Cross81, Cross84, Cross87, Cross90, Cross93, Cross97, Cross99, Cross102, Cross105, Cross110, Cross111, Cross114, Cross117, Cross120, Cross123, Cross126, Cross129, Cross132] # len(allCrossesApex) # 45 allCrossesApexPerExtremal = {extremal: sorted([x[1] for x in list(set(combineLists(newNoneEntriesCrossFactorsApex[extremal].values())))], reverse=True) for extremal in extremalCurves} # allCrossesApexPerExtremal # {F23: [Cross6, Cross30, Cross84, Cross105, Cross129], # F36: [Cross37, Cross41, Cross97, Cross99, Cross120], # E1: [Cross9, Cross33, Cross42, Cross78, Cross111], # F12: [Cross9, Cross57, Cross81, Cross97, Cross114], # G4: [Cross21, Cross42, Cross76, Cross102, Cross123], # F25: [Cross69, Cross87, Cross93, Cross120, Cross132], # E3: [Cross0, Cross84, Cross90, Cross99, Cross102], # G2: [Cross9, Cross84, Cross87, Cross110, Cross126], # F13: [Cross0, Cross48, Cross78, Cross117, Cross132], # F45: [Cross3, Cross6, Cross76, Cross97, Cross117], # E4: [Cross3, Cross18, Cross28, Cross73, Cross126], # G3: [Cross15, Cross28, Cross37, Cross78, Cross105], # F24: [Cross21, Cross41, Cross48, Cross60, Cross126], # E2: [Cross21, Cross63, Cross93, Cross105, Cross114], # F46: [Cross30, Cross73, Cross81, Cross123, Cross132], # G6: [Cross33, Cross63, Cross66, Cross73, Cross99], # G5: [Cross3, Cross51, Cross90, Cross93, Cross111], # F14: [Cross12, Cross18, Cross42, Cross120, Cross129], # F26: [Cross12, Cross54, Cross63, Cross110, Cross117], # F35: [Cross12, Cross15, Cross60, Cross81, Cross90], # F34: [Cross28, Cross54, Cross57, Cross69, Cross102], # E6: [Cross37, Cross45, Cross51, Cross110, Cross123], # E5: [Cross15, Cross24, Cross66, Cross76, Cross87], # G1: [Cross0, Cross18, Cross24, Cross45, Cross114], # F56: [Cross48, Cross51, Cross57, Cross66, Cross129], # F16: [Cross6, Cross33, Cross45, Cross60, Cross69], # F15: [Cross24, Cross30, Cross41, Cross54, Cross111]} # We save the output: # save(allCrossesApexPerExtremal, 'Input/allCrossesApexPerExtremal.sobj') # A list of variables g_0, ..., g_44 for the gaps between the expected and true valuations of all the 45 Cross functions appearing in allCrossesNoGoodProjections: gs = [var("g%s"%i) for i in range(0,len(allCrossesApex))] # We create the dictionaries of the adjusted expected valuations. We only add the parameter where the true valuation is unknown: dict_exp_Apex = dict() for extremal in allRatiosForApex.keys(): dict_exp_Apex[extremal] = dict() m = len(allCrossesApexPerExtremal[extremal]) print extremal for k in range(0,m): dict_exp_Apex[extremal][SR(allCrossesApexPerExtremal[extremal][k])] = SR(gs[k]) # We record the output: # print dict_exp_Apex # {F23: {Cross129: g4, Cross30: g1, Cross6: g0, Cross84: g2, Cross105: g3}, F36: {Cross41: g1, Cross120: g4, Cross99: g3, Cross37: g0, Cross97: g2}, E1: {Cross42: g2, Cross9: g0, Cross111: g4, Cross78: g3, Cross33: g1}, F12: {Cross97: g3, Cross9: g0, Cross81: g2, Cross114: g4, Cross57: g1}, G4: {Cross42: g1, Cross102: g3, Cross21: g0, Cross76: g2, Cross123: g4}, F25: {Cross120: g3, Cross87: g1, Cross69: g0, Cross132: g4, Cross93: g2}, E3: {Cross90: g2, Cross0: g0, Cross102: g4, Cross84: g1, Cross99: g3}, G2: {Cross9: g0, Cross87: g2, Cross110: g3, Cross126: g4, Cross84: g1}, F13: {Cross0: g0, Cross78: g2, Cross48: g1, Cross132: g4, Cross117: g3}, F45: {Cross97: g3, Cross6: g1, Cross117: g4, Cross76: g2, Cross3: g0}, E4: {Cross18: g1, Cross73: g3, Cross126: g4, Cross28: g2, Cross3: g0}, G3: {Cross105: g4, Cross15: g0, Cross78: g3, Cross37: g2, Cross28: g1}, F24: {Cross41: g1, Cross48: g2, Cross126: g4, Cross21: g0, Cross60: g3}, E2: {Cross114: g4, Cross105: g3, Cross63: g1, Cross21: g0, Cross93: g2}, F46: {Cross73: g1, Cross123: g3, Cross30: g0, Cross132: g4, Cross81: g2}, G6: {Cross66: g2, Cross33: g0, Cross63: g1, Cross99: g4, Cross73: g3}, G5: {Cross90: g2, Cross111: g4, Cross51: g1, Cross93: g3, Cross3: g0}, F14: {Cross18: g1, Cross42: g2, Cross120: g3, Cross12: g0, Cross129: g4}, F26: {Cross110: g3, Cross63: g2, Cross54: g1, Cross117: g4, Cross12: g0}, F35: {Cross90: g4, Cross81: g3, Cross15: g1, Cross60: g2, Cross12: g0}, F34: {Cross102: g4, Cross57: g2, Cross54: g1, Cross69: g3, Cross28: g0}, E6: {Cross123: g4, Cross51: g2, Cross110: g3, Cross37: g0, Cross45: g1}, E5: {Cross66: g2, Cross24: g1, Cross15: g0, Cross87: g4, Cross76: g3}, G1: {Cross18: g1, Cross114: g4, Cross0: g0, Cross24: g2, Cross45: g3}, F56: {Cross66: g3, Cross57: g2, Cross48: g0, Cross129: g4, Cross51: g1}, F16: {Cross33: g1, Cross6: g0, Cross45: g2, Cross60: g3, Cross69: g4}, F15: {Cross41: g2, Cross24: g0, Cross111: g4, Cross30: g1, Cross54: g3}} # We record the expressions of parameters g0,...,g4: reldictCrossParamApex = dict() for extremal in extremalCurves: reldictCrossParamApex[extremal] = dict() for g in sorted(dict_exp_Apex[extremal].values(), reverse=False): reldictCrossParamApex[extremal][g] = [cross for cross in dict_exp_Apex[extremal].keys() if dict_exp_Apex[extremal][cross] == g][0] # We record the output: # print reldictCrossParamApex # {F23: {g4: Cross129, g3: Cross105, g2: Cross84, g1: Cross30, g0: Cross6}, F36: {g4: Cross120, g3: Cross99, g2: Cross97, g1: Cross41, g0: Cross37}, E1: {g4: Cross111, g3: Cross78, g2: Cross42, g1: Cross33, g0: Cross9}, F12: {g4: Cross114, g3: Cross97, g2: Cross81, g1: Cross57, g0: Cross9}, G4: {g4: Cross123, g3: Cross102, g2: Cross76, g1: Cross42, g0: Cross21}, F25: {g4: Cross132, g3: Cross120, g2: Cross93, g1: Cross87, g0: Cross69}, E3: {g4: Cross102, g3: Cross99, g2: Cross90, g1: Cross84, g0: Cross0}, G2: {g4: Cross126, g3: Cross110, g2: Cross87, g1: Cross84, g0: Cross9}, F13: {g4: Cross132, g3: Cross117, g2: Cross78, g1: Cross48, g0: Cross0}, F45: {g4: Cross117, g3: Cross97, g2: Cross76, g1: Cross6, g0: Cross3}, E4: {g4: Cross126, g3: Cross73, g2: Cross28, g1: Cross18, g0: Cross3}, G3: {g4: Cross105, g3: Cross78, g2: Cross37, g1: Cross28, g0: Cross15}, F24: {g4: Cross126, g3: Cross60, g2: Cross48, g1: Cross41, g0: Cross21}, E2: {g4: Cross114, g3: Cross105, g2: Cross93, g1: Cross63, g0: Cross21}, F46: {g4: Cross132, g3: Cross123, g2: Cross81, g1: Cross73, g0: Cross30}, G6: {g4: Cross99, g3: Cross73, g2: Cross66, g1: Cross63, g0: Cross33}, G5: {g4: Cross111, g3: Cross93, g2: Cross90, g1: Cross51, g0: Cross3}, F14: {g4: Cross129, g3: Cross120, g2: Cross42, g1: Cross18, g0: Cross12}, F26: {g4: Cross117, g3: Cross110, g2: Cross63, g1: Cross54, g0: Cross12}, F35: {g4: Cross90, g3: Cross81, g2: Cross60, g1: Cross15, g0: Cross12}, F34: {g4: Cross102, g3: Cross69, g2: Cross57, g1: Cross54, g0: Cross28}, E6: {g4: Cross123, g3: Cross110, g2: Cross51, g1: Cross45, g0: Cross37}, E5: {g4: Cross87, g3: Cross76, g2: Cross66, g1: Cross24, g0: Cross15}, G1: {g4: Cross114, g3: Cross45, g2: Cross24, g1: Cross18, g0: Cross0}, F56: {g4: Cross129, g3: Cross66, g2: Cross57, g1: Cross51, g0: Cross48}, F16: {g4: Cross69, g3: Cross60, g2: Cross45, g1: Cross33, g0: Cross6}, F15: {g4: Cross111, g3: Cross54, g2: Cross41, g1: Cross30, g0: Cross24}} ####################################################### # Computations of Expected and true tropical matrices # ####################################################### # Next, we take all the shifted matrices and substitute dict_exp_Apex. The expected tropical nodes will come from setting gs[k] = 0 for all k. A tropical minors computation will help us determine if the valuations will be higher than expected. def computeNewExpectedShiftedMatrix(oldmatrix, dict_exp): newMatrix = [[oldmatrix[k][l] for l in range(0,len(oldmatrix[k]))] for k in range(0,len(oldmatrix))] for k in range(0,len(oldmatrix)): for l in range(0,len(oldmatrix[k])): newMatrix[k][l] = SR(newMatrix[k][l]).substitute(dict_exp) return newMatrix # We create the true matrices using the function 'computeNewExpectedShiftedMatrix' on the corresponding matrix from the dictionary 'allShiftedTNodesApex'. The expected ones are obtained from the true ones by specializing the gs to 0 on the true matrices, using the same function. dict0gs = {SR(gs[k]): 0 for k in range(0,len(gs))} newTrueVBShiftedSymbMatricesApex = dict() newExpectedVBShiftedSymbMatricesApex = dict() for extremal in extremalCurves: print str(extremal) oldmatrix = allShiftedTNodesApex[extremal] newTrueVBShiftedSymbMatricesApex[extremal] = computeNewExpectedShiftedMatrix(oldmatrix, dict_exp_Apex[extremal]) newExpectedVBShiftedSymbMatricesApex[extremal] = computeNewExpectedShiftedMatrix(newTrueVBShiftedSymbMatricesApex[extremal], dict0gs) # Sample output: # newExpectedVBShiftedSymbMatricesApex[E1] # [[+Infinity, 0, 0, 0, 0, 0, 0, 0, 0, 0], # [0, +Infinity, 0, 0, 0, 0, 0, 0, 0, 0], # [0, 0, +Infinity, 0, 0, 0, 0, 0, 0, 0], # [0, 0, 0, +Infinity, 0, 0, 0, 0, 0, 0], # [0, 0, 0, 0, +Infinity, 0, 0, 0, 0, 0], # [0, 0, 0, 0, 0, +Infinity, 0, 0, 0, 0], # [0, 0, 0, 0, 0, 0, +Infinity, 0, 0, 0], # [0, 0, 0, 0, 0, 0, 0, +Infinity, 0, 0], # [0, 0, 0, 0, 0, 0, 0, 0, +Infinity, 0], # [0, 0, 0, 0, 0, 0, 0, 0, 0, +Infinity]] # newTrueVBShiftedSymbMatricesApex[E1] # [[+Infinity, 0, 0, 0, g3, 0, 0, 0, 0, 0], # [0, +Infinity, g1, 0, 0, 0, 0, 0, 0, 0], # [0, g1, +Infinity, 0, 0, 0, 0, 0, 0, 0], # [0, 0, 0, +Infinity, 0, 0, 0, 0, g0, 0], # [g3, 0, 0, 0, +Infinity, 0, 0, 0, 0, 0], # [0, 0, 0, 0, 0, +Infinity, 0, 0, 0, g2], # [0, 0, 0, 0, 0, 0, +Infinity, g4, 0, 0], # [0, 0, 0, 0, 0, 0, g4, +Infinity, 0, 0], # [0, 0, 0, g0, 0, 0, 0, 0, +Infinity, 0], # [0, 0, 0, 0, 0, g2, 0, 0, 0, +Infinity]] ######################################## # STEP 5: Algorithms for tree building # ######################################## # In what follows we use the matrices in 'newTrueVBShiftedSymbMatricesApex' to compute the non-generic trees. The following functions are copied from the script 'computeTreesForExtremalCurvesWithNoGoodProjections.sage'. ########################################### # STEP 5.1: Create leaves from the matrix # ########################################### # The following function takes the rows of the reshuffledMatrix and computes the initial set of vertices, consisting of the 10 leaves # Each leaf will have the following format: # ([list of Infinity entries of the leaf], list of coordinates of the leaf, False) # The result is a list. def createLeaves(matrixOfLeaves): leaves = [] m = len(matrixOfLeaves[0]) for k in range(0,m): newLeafCoords = matrixOfLeaves[k] if len(newLeafCoords)!=m: print 'Matrix has rows of different length!' return False if newLeafCoords[k] != +Infinity: print 'Matrix needs to be reshuffled' return False newLeaf = ([k], newLeafCoords, False) leaves.append(newLeaf) return leaves ################################################# # STEP 5.2: Create vertices from other vertices # ################################################# # The following scripts allow us to take two vertices of the tree and compute their meet. # The following auxiliary function computes the sum of the canonical basis vectors in R^m given by a list of (distinct) indices. # We need the vector to have entries in the Symbolic Ring def directionVector(listIndices,m): w = vector({m-1:SR(0)}) for k in listIndices: w[k] = SR(1) return w # We create three auxiliary functions, depending on the nature of the pair of vertices involved. ######################### # Case 1: LEAF AND LEAF # ######################### # The following function computes the meet of two leaves of the tree: # "leaf1" is a list with 1 infinity entry and the remaining in SR, representing the coordinates of a leaf of the tree. # "leaf2" is a list with 1 infinity entry and the remaining in SR, representing the coordinates of a leaf of the tree. # The output has the format: # (list of Infinity entries of the 2 leaves, list of coordinates of the meet, True) # The last entry indicates that the meet has no infinity coordinates def leafAndLeafMerge(leaf1,leaf2): # the length of the cherry is the ambient dimension m = len(leaf1[1]) # print m if m !=len(leaf2[1]): print 'Leaves have different lengths' return False # We check that the leaves are leaves: if leaf1[-1]==True: print 'Leaf1 is a cherry!' return False if leaf2[-1]==True: print 'Leaf2 is a cherry!' return False # we pick the Infinity entry of the leaves k1 = leaf1[0][0] k2 = leaf2[0][0] # we check the entries are indeed '+Infinity' if leaf1[1][k1]!=+Infinity: print 'Leaf1 is not in standard form!' return False if leaf2[1][k2]!=+Infinity: print 'Leaf2 is not in standard form!' return False # Set a system without the coordinates k1 and k2 allOnes = directionVector(range(0,m),m) constv = vector(SR,leaf1[1])-vector(SR,leaf2[1]) # we project away the k1 and k2th columns (to avoid systems involving 'Infinity' entries) # print constv noK = [x for x in range(0,m) if x !=k1 if x!=k2] projconstv = list(matrix(SR,list(constv)).matrix_from_columns(noK)[0]) print projconstv matrixDir = matrix(SR,[allOnes]) print matrixDir projmatrixDir = matrixDir.matrix_from_columns(noK) print projmatrixDir try: soln12 = projmatrixDir.transpose() \ vector(SR,projconstv) print soln12 newcherry = list(vector({m-1:SR(0)})) for j in range(0,m): newcherry[j] = SR(leaf1[1][j]) newcherry[k1] = SR(leaf2[1][k1] + SR(soln12[0])) # newCherryValue = vector(SR,newcherry) # return (sorted([k1,k2]),newCherryValue,True) return (sorted(list(set([k1,k2]))),newcherry,True) except ValueError: print 'Leaves do not meet!' return False ########################### # Case 2: CHERRY AND LEAF # ########################### # The following function computes the meet of a cherry and a leaf of the tree. # The format for leaf and cherry is: # (list of indices, list in SR with possibly a +Infinity entry, True/False) # "leaf" means last entry is False # "cherry" means last entry is True def cherryAndLeafMerge(cherry,leaf): # the length of the cherry is the ambient dimension m = len(cherry[1]) if leaf[-1] == True: print 'The leaf is not a leaf!' return False # we pick the Infinity entry of the leaf k = [j for j in range(0,m) if leaf[1][j]==+Infinity][0] # print k if cherry[-1] == False: print 'The cherry is a leaf!' return False # Set a system without the coordinate k dir1v=directionVector(cherry[0],m) allOnes = directionVector(range(0,m),m) constv = vector(SR,leaf[1])-vector(SR,cherry[1]) # we project away the kth column (to avoid systems involving 'Infinity' entrie) # print constv noK = [x for x in range(0,m) if x !=k] projconstv = list(matrix(SR,list(constv)).matrix_from_columns(noK)[0]) # print projconstv matrixDir = matrix(SR,[dir1v,allOnes]) print matrixDir projmatrixDir = matrixDir.matrix_from_columns(noK) # print projmatrixDir try: soln12 = projmatrixDir.transpose() \ vector(SR,projconstv) newCherryValue = list(soln12[0]*dir1v + soln12[1]*allOnes + vector(SR,cherry[1])) return (sorted(list(set(leaf[0]+cherry[0]))), newCherryValue, True) except ValueError: print 'Cherries do not meet!' return False ############################# # Case 3: CHERRY AND CHERRY # ############################# # The following function computes the meet of two cherries # cherry1 is the tuple associated to the first cherry # cherry2 is the tuple associated to the second cherry def cherryAndCherryMerge(cherry1,cherry2): # the length of the cherry is the ambient dimension m = len(cherry1[1]) if m !=len(cherry2[1]): print 'The cherries have different length!' return False if cherry1[-1] == False: print 'The first cherry is a leaf!' return False if cherry2[-1] == False: print 'The first cherry is a leaf!' return False # Set up the system to be solved dir1v = directionVector(cherry1[0],m) dir2v = directionVector(cherry2[0],m) allOnes = directionVector(range(0,m),m) constv = vector(SR,cherry1[1])-vector(SR,cherry2[1]) # print constv try: soln12 = matrix(SR,[dir1v,dir2v,allOnes]).transpose() \ constv # print soln12 newCherryValue = list(-soln12[0]*dir1v + vector(SR,cherry1[1])) return (sorted(list(set(cherry1[0]+cherry2[0]))), newCherryValue, True) except ValueError: print 'Cherries do not meet!' return False ################ # General case # ################ # The final function combines the auxilliary functions: def newVertexFromOldPair(vertex1,vertex2): if vertex1[-1] == False: if vertex2[-1] == False: # vertex1 is a leaf, vertex2 is a leaf return leafAndLeafMerge(vertex1,vertex2) else: # vertex1 is a leaf, vertex2 is a cherry return cherryAndLeafMerge(vertex2,vertex1) else: if vertex2[-1] == False: # vertex1 is a cherry, vertex2 is a leaf return cherryAndLeafMerge(vertex1, vertex2) else: # vertex1 is a cherry, vertex2 is a cherry return cherryAndCherryMerge(vertex1,vertex2) ############################### # STEP 5.3 : Merging cherries # ############################### # The following function takes a pair of cherries (i.e. vertices with no infinity coordinates) and replaces them by their merge whenever their coordinates agee up to a scalar multiple of the allOnes vector. # "cherry1" and "cherry2" are tuples with the following format: # (list of indices, list in SR with possibly a +Infinity entry, True/False) def merge2cherries(cherry1, cherry2): m = len(list(cherry1[1])) if m != len(list(cherry2[1])): print 'Cherries do not have the same lenght!' return False if cherry1[2] == False: print 'First vertex is a leaf, not a cherry!' return False if cherry2[2] == False: print 'Second vertex is a leaf, not a cherry!' return False dir1v = directionVector(cherry1[0],m) # print dir1v dir2v = directionVector(cherry2[0],m) # print dir2v allOnes = directionVector(range(0,m),m) constv = vector(SR,cherry1[1])-vector(SR,cherry2[1]) try: soln12 = matrix(SR,[allOnes]).transpose() \ constv # print soln12 return (sorted(list(set(cherry1[0]+cherry2[0]))),cherry1[1], True) except ValueError: print 'Cherries are different and hence do not merge!' return False # The following function takes a set of vertices (including leaves) and replaces it by merging vertices that are equal up to a scalar multiple of the allOnes vector. # begin is a list of tuples containing all leaves and cherries. Each tuple has the format: # (list of indices, list in SR with possibly a +Infinity entry, True/False) # leaves have last entry 'False' # cherries have last entry 'True' import copy def mergeVertices(begin): allLeaves = [x for x in begin if x[-1]==False] allCherries = [x for x in begin if x not in allLeaves] # print (len(allLeaves), len(allCherries)) # toMerge keeps a list of non-leaf vertices that are yet to be treated. In the beginning, it is just a copy of the set of all vertices. toMerge = copy.copy(allCherries) # merged keeps a set of the non-leaf vertices that have been merged. merged = [] while len(toMerge) > 0: # Pick the first equation to be symmetrized vertex = toMerge.pop() # print str(vertex) if len(toMerge) == 0: merged.append(vertex) else: for testVertex in toMerge: w = merge2cherries(vertex, testVertex) # If the merging is successful, we update the vertex and we remove the testvertex from 'toMerge' print len(toMerge) if w != False: vertex = tuple(copy.copy(list(w))) toMerge = [x for x in toMerge if x!= testVertex] # when we reach this step, we've covered the entire toMerge and the vertex has been updated as much as possible. merged.append(vertex) print "Found: " + str(len(merged)) print "To merge: " + str(len(toMerge)) print "Merged: " + str(len(merged)) print " " allMergedVertices = allLeaves + merged return allMergedVertices ################################ # STEP 5.4: Construct the tree # ################################ # The following script picks a cone, an extremal curve, and the dictionary of all tropicalNodes, and computes the tree associated to the tropicalization of the extremal curve. # We denote by m the number of leaves of the tree # Our stopping criterion is given by finding two vertices whose associated indices join to form a set of length m. In practice, these two vertices must have disjoint 0th-coordinate unless the tree is the star tree (corresponding to the trivially valued case). # We need to determine the correspondence between the leaves and the indices. import copy def computeTreeForConeAndExtremalCurve(extremal,matrixNodes,leavesIndices): m = len(matrixNodes[0]) # Step 0: Get the leaveIndexDictionary leavesIndexDict = leavesIndices[extremal] # Step 1: create the leaves leaves = createLeaves(matrixNodes) vertices = copy.copy(leaves) # Step 2: create vertices from pairs, and use "meetingIndices" as the stopping point: # "meeting Indices" checks if we have two vertices whose index sets (0th coordinate of the tuple) combined form a set of size m. This will indicate that we have covered all vertices (it would indicate that we have a path from each leaf to one of these two leaves). # The following gives our stopping point. meetingIndices = [(k,l) for k in range(0,len(vertices)) for l in range(0,len(vertices)) if k0: pair=PairsOfVertices.pop() newVertex = newVertexFromOldPair(pair[0],pair[1]) if newVertex !=False: vertices.append(newVertex) vertices = mergeVertices(vertices) # We update our stopping criterion since we may have new vertices: meetingIndices = [(k,l) for k in range(0,len(vertices)) for l in range(0,len(vertices)) if k1] pairsOfCherries = [(cherries[i], cherries[j]) for i in range(0,len(cherries)) for j in range(0,len(cherries)) if i