图片中给出的是无线电平均标号的定义,以及两条路笛卡尔乘积图的示意图,请你根据定义求出两条路的无限电平...

Créé le : 18 juin 2026

Répondu en utilisant GPT-5.5 Thinking par Chat01

Question

290cbbef014daf03587bd46ca59afd3.jpg
9896f39e5496679774a0d147d0e82ff.jpg

图片中给出的是无线电平均标号的定义,以及两条路笛卡尔乘积图的示意图,请你根据定义求出两条路的无限电平均标号数,最后的结果我想要的是确切的数值以及表达式,而不是范围区间,并给出严谨的上下届证明,最后结果以PDF格式显现

Python

python
from functools import lru_cache def solve_ladder(n, M, want_assignment=False): verts=[(r,c) for c in range(n) for r in range(2)] # columns order N=len(verts); d=n dist=[[abs(c1-c2)+(r1!=r2) for (r2,c2) in verts] for (r1,c1) in verts] # recursive: process labels 1..M, assigned list vertex per used label (dict tuple) # state: label, used mask, tuple of used assignments maybe need constraints with labels # Since constraints depend on previous labels values and vertices, need store assigned pairs. # backtracking with pruning assigned=[] usedmask=0 # order vertices maybe extremes first allmask=(1<<N)-1 # For each l and previous (p,vp), compute allowed v if distance cond. def ok_pair(l,v,p,vp): return dist[v][vp] + ((l+p+1)//2) >= n+1 # ceil best=None # symmetrical fix label 1 to one vertex? Since automorphisms, label 1 can be top-left? maybe only for existence? Not necessarily any vertex can be moved to one of orbits by dihedral. Ladder automorphism transposes rows and reverses columns; vertices in column c and n-1-c same orbit. Label1 likely must be near end? But no fix. from functools import lru_cache # Need memo on l, usedmask, assigned tuple? constraints depend assigned labels/positions. Can't compress. calls=0 def rec(l, usedmask, ass): nonlocal best,calls calls+=1 usedcnt=usedmask.bit_count() if usedcnt==N: best=ass return True if l>M: return False if usedcnt + (M-l+1) < N: return False # Try skipping l maybe, but only if enough left and maybe skip small to satisfy. But for minimizing M, skipping low labels common. # Try assigning l first? It might be necessary to use many labels. # Generate allowed vertices allowed=[] for v in range(N): if not (usedmask>>v)&1: good=True for p,vp in ass: if not ok_pair(l,v,p,vp): good=False; break if good: allowed.append(v) # heuristic: if l small, assign restricted vertices. Try allowed ordered by extremes # But also skip option. # Branch choose assign l or skip. Use memo? for v in allowed: if rec(l+1, usedmask| (1<<v), ass+((l,v),)): return True # skip if rec(l+1, usedmask, ass): return True return False res=rec(1,0,tuple()) if want_assignment and res: return True, [(l, verts[v]) for l,v in best], calls return res,calls for n in range(1,8): N=2*n for M in range(N, 5*n+5): ok,_=solve_ladder(n,M) if ok: print(n, M) break

Python

python
for n in range(8,11): for M in range(2*n, 4*n): ok,calls=solve_ladder(n,M) if ok: print("n",n,"M",M,"calls",calls) break # print(n,M,calls)

Python

python
for n in range(5,11): M=None for m in range(2*n,4*n): ok,calls=solve_ladder(n,m) if ok: M=m; break ok,ass,calls=solve_ladder(n,M,True) print("n",n,"M",M) # display grid with label or . grid=[["." for c in range(n)] for r in range(2)] for l,(r,c) in ass: grid[r][c]=str(l) for r in range(2): print(grid[r]) print("used labels", [l for l,v in ass], "skipped", [i for i in range(1,M+1) if i not in [l for l,v in ass]]) print()

Python

python
import sympy as sp n,M=sp.symbols('n M', integer=True, positive=True) # max weighted sum: 2n labels from 1..M; assign largest 2n-4 to deg 3, next 4 to deg 2. # Sum largest k labels up to M = k*(2M-k+1)/2 k=2*n-4 sum_largest_k=k*(2*M-k+1)/2 sum_next4=4*(2*M-k-4+1)/2 # labels M-k-3..M-k max_weight=3*sum_largest_k+2*sum_next4 req=(3*n-2)*(2*n-1) sp.expand(max_weight), sp.solve_univariate_inequality(sp.expand(max_weight-req)>=0,M)

Python

python
import sympy as sp n,M=sp.symbols('n M') k=2*n-4 sum_largest_k=k*(2*M-k+1)/2 sum_next4=4*(2*M-k-4+1)/2 max_weight=sp.expand(3*sum_largest_k+2*sum_next4) req=sp.expand((3*n-2)*(2*n-1)) print(max_weight) print(req) print(sp.expand(max_weight-req)) print(sp.solve(sp.Eq(max_weight-req,0),M))

Python

python
def pair_sum_lower_ladder(n): verts=[(r,c) for r in range(2) for c in range(n)] total=0 count=0 from itertools import combinations for u,v in combinations(range(2*n),2): r1,c1=verts[u]; r2,c2=verts[v] t=abs(c1-c2)+(r1!=r2) total+=2*n+1-2*t count+=1 return total for n in range(2,11): total=pair_sum_lower_ladder(n) print(n,total, total/(2*n-1)) # max sum labels with span M = n*(2*M-2*n+1). Lower yields import math M=math.ceil((total/(2*n-1)/n +2*n-1)/2) # solve n(2M-2n+1)>=total/(2n-1) print("Mlb",M, "formula", math.ceil((8*n-8)/3))

Python

python
from itertools import combinations def packing_ladder(n,r): # mutual distance >= r+1 verts=[(row,c) for c in range(n) for row in range(2)] N=2*n conflict=[[False]*N for _ in range(N)] for i in range(N): for j in range(i+1,N): d=abs(verts[i][1]-verts[j][1])+(verts[i][0]!=verts[j][0]) if d<=r: conflict[i][j]=conflict[j][i]=True # brute force max independent in conflict for small n best=0 bestset=None for mask in range(1<<N): # too large for 20 maybe ok 1M if mask.bit_count()<=best: continue ok=True for i in range(N): if (mask>>i)&1: # check only j>i for j in range(i+1,N): if (mask>>j)&1 and conflict[i][j]: ok=False; break if not ok: break if ok: best=mask.bit_count(); bestset=mask return best for r in range(1,8): print("r",r, [packing_ladder(n,r) for n in range(2,13)])

Python

python
import math def q_packing_lb(n): vals=[] for r in range(1,n+1): vals.append(n-r-math.ceil(n/r)) return max(0,max(vals)), vals for n in range(1,31): q,_=q_packing_lb(n) print(n,q, "Mlb",2*n+q)

Python

python
# Re-define more efficient solver with candidates and memo. from functools import lru_cache def feasible_ladder(n, M, find=False, time_limit_nodes=1000000): verts=[(r,c) for c in range(n) for r in range(2)] N=2*n dist=[[abs(c1-c2)+(r1!=r2) for (r2,c2) in verts] for (r1,c1) in verts] # precompute allowed mask for label l given previous label p and vertex vp: vertices v compatible comp={} for l in range(1,M+1): for p in range(1,l): req=n+1-((l+p+1)//2) # need dist>=req masks=[] for vp in range(N): mask=0 for v in range(N): if v!=vp and dist[v][vp]>=req: mask |= 1<<v masks.append(mask) comp[(p,l)]=masks full=(1<<N)-1 # symmetry for first used

Python

python
results={} for n in range(1,31): # use previous for n small? lb=2*n+q_packing_lb(n)[0] for M in range(lb, 4*n): # upper hopefully ok,nodes,ass=feasible_ladder(n,M,time_limit_nodes=1000000) if ok is None: print("timeout",n,M,nodes) break if ok: results[n]=M print(n,M,"q",M-2*n,"lbq",q_packing_lb(n)[0],"nodes",nodes) break if n not in results: print("not found n",n) break

Python

python
for n in [12,13,14,15,20,25]: M=results[n] ok,nodes,ass=feasible_ladder(n,M,find=True,time_limit_nodes=1000000) print("n",n,"M",M,"p",3*n-M,"skips",[i for i in range(1,M+1) if i not in [l for l,v in ass]][:50]) grid=[["." for c in range(n)] for r in range(2)] for l,(r,c) in ass: grid[r][c]=l for r in range(2): print(" ".join(f"{grid[r][c]:2}" for c in range(n))) print()

Python

python
from functools import lru_cache def feasible_deficits(t,n,find=False): verts=[(r,c) for c in range(n) for r in range(2)] N=2*n dist=[[abs(c1-c2)+(r1!=r2) for (r2,c2) in verts] for (r1,c1) in verts] # assign deficits t,t-1,...? Larger more restrictive. Deficit labels are values 1..t. order=list(range(t,0,-1)) # Fix largest deficit t maybe at left/right? Use symmetry row0 maybe, and column <= middle? ass={} used=0 nodes=0 def rec(idx, usedmask, assignments): nonlocal nodes nodes+=1 if idx==len(order): return assignments x=order[idx] # candidate all vertices not used meeting constraints with assigned deficits candidates=[] for v in range(N): if usedmask>>v &1: continue ok=True for y,vy in assignments.items(): req=(x+y)//2 +1 # floor((x+y)/2)+1 if dist[v][vy] < req: ok=False;break if ok: candidates.append(v) # symmetry for first if idx==0: candidates=[v for v in candidates if verts[v][0]==0 and verts[v][1]<= (n-1)//2] # order by near center/ends? candidates.sort(key=lambda v: abs(verts[v][1]-(n-1)/2)) for v in candidates: res=rec(idx+1, usedmask|1<<v, {**assignments,x:v}) if res is not None: return res return None res=rec(0,0,{}) if find and res is not None: return True,{x:verts[v] for x,v in res.items()},nodes return res is not None,nodes def W_deficits(t): for n in range(1,100): ok,_=feasible_deficits(t,n) if ok: return n for t in range(1,16): w=W_deficits(t) print(t,w)

Python

python
import math def W(t): if t<=0: return 0 if t==1: return 1 if t==2: return 2 if t%2==0: s=t//2 return 2*s*s-2*s+3 else: s=(t-1)//2 return 2*s*s+2 def A(n): t=0 while W(t+1)<=n: t+=1 return t for n in range(1,31): M=max(2*n,3*n-A(n)-1) print(n,A(n),M)

Python

python
for n in range(3,200): a=A(n) b=math.floor(1+math.sqrt(2*n-4)) if a!=b: print("mismatch",n,a,b,W(a),W(a+1)); break else: print("all ok")

Python

python
# implement a reliable coordinate construction manually maybe find one for t up to 9 using previous function but trust? Need not. def find_deficit_assignment(t): n=W(t) ok,assign,nodes=feasible_deficits(t,n,find=True) return assign for t in range(1,10): assign=find_deficit_assignment(t) print("t",t,"W",W(t),assign) # sort by deficit # grid n=W(t) grid=[["." for _ in range(n)] for _ in range(2)] for x,(r,c) in assign.items(): grid[r][c]=str(x) for row in grid: print(" ".join(f"{v:>2}" for v in row)) print()

Python

python
import itertools, math def min_path_weight(t): best=10**9; bestp=None for perm in itertools.permutations(range(1,t+1)): s=sum((perm[i]+perm[i+1])//2 for i in range(t-1)) if s<best: best=s;bestp=perm return best,bestp for t in range(1,9): print(t, min_path_weight(t), "W-1", W(t)-1)

Python

python
def construction_perm(t): if t==1: return [1] if t==2: return [2,1] # or # pattern for t: # for t=5 min path [3,2,1,4,5] # for t=7 [5,2,1,4,3,6,7] # for t=9 [7,2,1,4,3,6,5,8,9] maybe perm=[t-2 if t%2==1 else t-1] # endpoint largest-1 for odd, t-1 for even # Actually for t=9 start7; yes t-2. # then pairs 2,1,4,3,6,5,... up to t-3? for k in range(2,t-1,2): perm.extend([k,k-1]) # append remaining high endpoints? if t%2==1: # after k up to t-3,t-4, append t-1?, t? # for t=9, loop k=2,4,6,8? range(2,8,2)=2,4,6 -> [2,1,4,3,6,5], append8,9 perm.extend([t-1,t]) else: # for t=8, start7, loop k=2,4,6? append [2,1,4,3,6,5], append8 perm.append(t) return perm def coords_from_perm(perm, extra_even=True): cols=[0] rows=[0] for i in range(len(perm)-1): gap=(perm[i]+perm[i+1])//2 # for even t maybe add extra gap to first? Need check cols.append(cols[-1]+gap) rows.append(1-rows[-1]) # alternate if len(perm)%2==0 and extra_even: # add one to all after some position maybe after label1? easiest add to last coordinate? increases gaps for pairs across cut. pass return {x:(rows[i],cols[i]) for i,x in enumerate(perm)} def check_deficits(coords): xs=list(coords) ok=True; bad=[] for i,x in enumerate(xs): for y in xs[i+1:]: r1,c1=coords[x]; r2,c2=coords[y] d=abs(c1-c2)+(r1!=r2) req=(x+y)//2+1 if d<req: ok=False; bad.append((x,y,d,req)) width=max(c for r,c in coords.values())-min(c for r,c in coords.values())+1 return ok,width,bad[:10] for t in range(3,12): perm=construction_perm(t) coords=coords_from_perm(perm) print(t,perm,check_deficits(coords))

Python

python
def rec_coords(t): # Returns coords for deficits 1..t width W(t) if t==1: return {1:(0,0)} if t==2: return {2:(0,0),1:(1,1)} if t==3: return {3:(0,0),2:(1,2),1:(0,3)} if t==4: return {4:(0,0),3:(1,3),2:(0,5),1:(1,6)} old=rec_coords(t-2) # put t at left col 0 row0; shift old by a? put t-1 at right W(t)-1 row? # try a=t-2 or t-1; rows maybe flip depending. width_old=max(c for r,c in old.values())+1 for a in range(0,2*t): for row_t in [0,1]: for row_r in [0,1]: # maybe flip old rows or not for flip in [0,1]: coords={t:(row_t,0), t-1:(row_r,W(t)-1)} for x,(r,c) in old.items(): coords[x]=(r^flip,c+a) ok,width,bad=check_deficits(coords) if ok and width==W(t): return coords raise Exception("no") for t in range(1,13): coords=rec_coords(t) print("t",t,"width",check_deficits(coords)[1], "W",W(t), "coords", sorted(coords.items())) # print grid

Python

python
def walk_positions(t): col=0; row=0 coords={0:(row,col)} for i in range(1,t+1): # change row every time row=1-row step=i-1 if i==1: sign=1 else: block=(i-2)//2 sign=1 if block%2==0 else -1 col += sign*step coords[i]=(row,col) minc=min(c for r,c in coords.values()) coords={i:(r,c-minc) for i,(r,c) in coords.items()} width=max(c for r,c in coords.values())+1 return coords,width def check_deficits_subset(coords, include0=False): xs=[x for x in coords if include0 or x>0] bad=[] for idx,x in enumerate(xs): for y in xs[idx+1:]: r1,c1=coords[x]; r2,c2=coords[y] d=abs(c1-c2)+(r1!=r2) # condition for deficits x,y, both low if positive: req=floor((x+y)/2)+1 req=(x+y)//2 +1 if d<req: bad.append((x,y,d,req)) return bad for t in range(1,13): coords,width=walk_positions(t) low_coords={i:coords[i] for i in range(1,t+1)} minc=min(c for r,c in low_coords.values()) low_coords={i:(r,c-minc) for i,(r,c) in low_coords.items()} low_width=max(c for r,c in low_coords.values())+1 print("t",t,"allwidth",width,"lowwidth",low_width,"W",W(t),"bad",check_deficits_subset(low_coords)[:3],"coords",coords)

Python

python
def feasible_deficits_with0(t,n,find=False): vals=list(range(t, -1, -1)) # include 0 verts=[(r,c) for c in range(n) for r in range(2)] N=2*n dist=[[abs(c1-c2)+(r1!=r2) for (r2,c2) in verts] for (r1,c1) in verts] def req(x,y): return (x+y)//2 + 1 def rec(idx, usedmask, ass): if idx==len(vals): return ass x=vals[idx] candidates=[] for v in range(N): if usedmask>>v &1: continue ok=True for y,vy in ass.items(): if dist[v][vy] < req(x,y): ok=False;break if ok: candidates.append(v) if idx==0: candidates=[v for v in candidates if verts[v][0]==0 and verts[v][1]<= (n-1)//2] candidates.sort(key=lambda v: abs(verts[v][1]-(n-1)/2)) for v in candidates: res=rec(idx+1,usedmask|1<<v,{**ass,x:v}) if res is not None: return res return None res=rec(0,0,{}) if find and res is not None: return True,{x:verts[v] for x,v in res.items()} return res is not None def W0(t): for n in range(1,100): if feasible_deficits_with0(t,n): return n for t in range(1,9): print(t,W0(t), "W", W(t))

Python

python
for t in range(1,9): n=W0(t) ok,assign=feasible_deficits_with0(t,n,find=True) print("t",t,"n",n,assign) grid=[["." for _ in range(n)] for _ in range(2)] for x,(r,c) in assign.items(): grid[r][c]=str(x) for row in grid: print(" ".join(f"{v:>2}" for v in row)) print()

Python

python
import itertools, math def path_weight(perm): return sum((perm[i]+perm[i+1])//2 for i in range(len(perm)-1)) def equality_paths(s, limit=20): target=math.ceil(s*s/2 - s +1) paths=[] for perm in itertools.permutations(range(1,s+1)): if path_weight(perm)==target: paths.append(perm) if len(paths)>=limit: break return target,paths for s in [4,6]: target,paths=equality_paths(s,1000) print("s",s,"target",target,"num_sample",len(paths)) for p in paths[:10]: # construct cols gaps minimal, rows alternating cols=[0] for i in range(s-1): cols.append(cols[-1]+(p[i]+p[i+1])//2) rows=[i%2 for i in range(s)] coords={p[i]:(rows[i],cols[i]) for i in range(s)} bad=check_deficits(coords)[2] print(p,bad[:3]) print()

Python

python
def coords_from_perm_with_extra(perm, extra_after_label=None): cols=[0]; rows=[0] for i in range(len(perm)-1): gap=(perm[i]+perm[i+1])//2 if extra_after_label is not None and perm[i]==extra_after_label: gap+=1 cols.append(cols[-1]+gap) rows.append(1-rows[-1]) return {x:(rows[i],cols[i]) for i,x in enumerate(perm)} def even_perm(t): return construction_perm(t) for t in [4,6,8,10]: perm=even_perm(t) coords=coords_from_perm_with_extra(perm,extra_after_label=1) print(t, perm, check_deficits(coords)[:2], check_deficits(coords)[2][:5])

Python

python
def coords_from_perm_alt(perm): cols=[0]; rows=[0] for i in range(len(perm)-1): cols.append(cols[-1]+(perm[i]+perm[i+1])//2) rows.append(1-rows[-1]) return {x:(rows[i],cols[i]) for i,x in enumerate(perm)} for perm in [(5,2,3,1,4),(7,4,5,2,3,1,6),(9,6,7,4,5,2,3,1,8)]: coords=coords_from_perm_alt(list(perm)) print(perm, path_weight(perm), check_deficits(coords)[:2], check_deficits(coords)[2][:5])

Python

python
def coords_even(t): perm=even_perm(t) return coords_from_perm_with_extra(perm,extra_after_label=1) def perm_odd(t): # t odd >=3 perm=[t] # pairs (t-3,t-2), descending by 2 down to (2,3) for a in range(t-3,1,-2): perm.extend([a,a+1]) perm.extend([1,t-1]) return perm def coords_odd(t): return coords_from_perm_alt(perm_odd(t)) def possible_zero(coords,t): width=check_deficits(coords)[1] positions=[] for c in range(width): for r in [0,1]: if (r,c) in coords.values(): continue ok=True for i,(ri,ci) in coords.items(): d=abs(c-ci)+(r!=ri) req=i//2 +1 # floor(i/2)+1 if d<req: ok=False;break if ok: positions.append((r,c)) return positions for t in range(3,11): coords=coords_odd(t) if t%2 else coords_even(t) print("t",t,"width",check_deficits(coords)[1],"zero options",possible_zero(coords,t)[:10]) # print coords print(sorted(coords.items(), key=lambda kv: kv[1][1]))

Python

python
def req_for_def(x,y): # x,y are deficits: label n-x and n-y. For y negative means high label. # condition: dist + ceil((2n - x - y)/2) >= n+1 # ceil(n - (x+y)/2)= n - floor((x+y)/2) # req = floor((x+y)/2)+1. If <=1, distinct vertices automatically at dist>=1. return max(1, (x+y)//2 + 1) def feasible_special(t,n,find=False): vals=list(range(t, -(t-2)-1, -1)) # t,t-1,...,-(t-2) # order maybe positives first descending then 0 then negatives descending? # To search, use sorted by absolute/positive? Use vals as t..negative verts=[(r,c) for c in range(n) for r in range(2)] N=2*n dist=[[abs(c1-c2)+(r1!=r2) for (r2,c2) in verts] for (r1,c1) in verts] def rec(idx, usedmask, ass): if idx==len(vals): return ass x=vals[idx] candidates=[] for v in range(N): if usedmask>>v & 1: continue ok=True for y,vy in ass.items(): if dist[v][vy] < req_for_def(x,y): ok=False;break if ok:candidates.append(v) if idx==0: candidates=[v for v in candidates if verts[v][0]==0 and verts[v][1]<= (n-1)//2] candidates.sort(key=lambda v: abs(verts[v][1]-(n-1)/2)) for v in candidates: res=rec(idx+1, usedmask|1<<v, {**ass,x:v}) if res is not None:return res return None res=rec(0,0,{}) if find and res is not None: return True,{x:verts[v] for x,v in res.items()} return res is not None for t in range(1,9): n= max(W0(t),2*t-1) # actually width W? print("t",t,"W0",W0(t),"2t-1",2*t-1, "feas at W0", feasible_special(t,W0(t))) if feasible_special(t,W0(t)): ok,assign=feasible_special(t,W0(t),find=True) print(assign)

Python

python
def special_extend_from_coords(coords,t): # coords positives, place 0 and negatives greedily maybe using known zero then search # We'll search with fixed positives for remaining 0,-1,... width=check_deficits(coords)[1] verts=[(r,c) for c in range(width) for r in range(2)] N=2*width used=set(coords.values()) vals=[0]+[-j for j in range(1,t-1)] ass={**coords} # sort maybe 0, -1... def rec(idx,ass,used): if idx==len(vals): return ass x=vals[idx] cands=[] for v in verts: if v in used: continue ok=True for y,vy in ass.items(): d=abs(v[1]-vy[1])+(v[0]!=vy[0]) if d<req_for_def(x,y): ok=False;break if ok: cands.append(v) # prefer near label1/zero cands.sort(key=lambda rc: (abs(rc[1]-width/2), rc[0])) for v in cands: res=rec(idx+1,{**ass,x:v}, used|{v}) if res: return res return None return rec(0,ass,used) for t in range(3,11): coords=coords_odd(t) if t%2 else coords_even(t) ass=special_extend_from_coords(coords,t) print("t",t, "width",check_deficits(coords)[1]) print(sorted(ass.items(), key=lambda kv: kv[1][1])) print()

Python

python
for n in [26,27,30,50]: t=math.floor(1+math.sqrt(2*n-4)) M=3*n-t-1 print(n,t,M) # check n26 M70 with solver maybe ok,nodes,ass=feasible_ladder(26,70,time_limit_nodes=2000000) print("n26 M70",ok,nodes)

Réflexion

bash -lc rm -rf /mnt/data/_renders_rmn /mnt/data/rmn_ladder_proof.aux /mnt/data/rmn_ladder_proof.log /mnt/data/rmn_ladder_proof.out /mnt/data/rmn_ladder_proof.tex /mnt/data/xelatex_second.log && ls -l /mnt/data/rmn_ladder_proof.pdf

Thought for 15m 14s

Réponse

已按图 4-3 所示的 P2PnP_2\square P_n 写成 PDF,包含精确公式、上下界证明和一个 n=10n=10 的标号示例。

PDF 下载: 无线电平均标号数证明

Question

从数学角度重新给定这个标号函数,不要是什么亏量,因为从未听过这个定义,就是确切的数值,结果以PDF格式输出

Python

python
from itertools import combinations, permutations def ladder_dist(n): verts=[(r,i) for i in range(2) for i in range(1,n+1)] D={} for a,u in enumerate(verts): for b,v in enumerate(verts): D[a,b]=abs(u[1]-v[1])+(u[0]!=v[0]) return verts,D def feasible(n,m, verbose=False): V,D=ladder_dist(n) N=len(V) # choose N labels from 1..m? Better assign labels maybe all but holes. # We can choose vertices for each used label; skip labels allowed. Backtrack label 1..m deciding use or skip. # Need use N labels. Low labels constrained. Use symmetry graph autom? skip. min_dist_req={} labels=range(1,m+1) for a in labels: for b in labels: if a<b: # need d >= ceil((2n+1 - (a+b))/2) if positive req=max(0, (2*n+1 - (a+b) +1)//2) # ceil # actually if req<=0, no constraint min_dist_req[(a,b)]=req # domain for labels: all vertices; if label pairs require req>n impossible? But pairs may not both used. # Backtrack used labels increasing; try always use smaller labels? skipping maybe needed. # If using label l, skip decision. Lower bound: if remaining labels enough. assigned={} # label->vertex index used_vertices=set() # Use labels in increasing order; use MRV? use/skip. # For canonical, use label 1? likely yes for minim max, but maybe maybe yes because replacing min used label with 1 decreases constraints? actually lower label makes constraints harder, so not necessarily use 1. But labels are positive, skipping small labels can help but increases span maybe. For fixed m, feasible subset of N labels; not necessarily includes 1. # Need choose subset. We'll search labels descending? large less constrained, but low constrained. # Use recursion on labels ascending with skip. # Symmetry: fix label 1 to a representative? Maybe if label 1 used. But can skip. vert_order=list(range(N)) # Sort vertices by maybe position; no need. def can_assign(label, v): for lab,u in assigned.items(): req=min_dist_req[(lab,label) if lab<label else (label,lab)] if D[u,v] < req: return False return True def rec(label, used_count): if label>m: return used_count==N rem=m-label+1 if used_count+rem<N: return False # If used_count==N: can ignore rest? But max span m requires label m? Actually rmn(f) <= m, not necessarily uses m. Feasible for <=m. Then true. if used_count==N: return True # try skip? For small labels perhaps skipping beneficial. But to minimize max, not necessarily use all smallest labels. Try use/skip maybe. # But if rem == N-used_count, must use all. # Try use label maybe if likely. # choose candidate vertices that satisfy constraints if rem == N-used_count: do_skip=False else: do_skip=True # maybe skip first for low constrained? For feasibility skip may succeed quicker if do_skip and rec(label+1, used_count): return True # use # candidates sorted by pruning for v in vert_order: if v not in used_vertices and can_assign(label,v): assigned[label]=v; used_vertices.add(v) if rec(label+1, used_count+1): return True used_vertices.remove(v); del assigned[label] return False res=rec(1,0) if verbose and res: print("assign", assigned) return res for n in range(1,8): lo=2*n m=lo while not feasible(n,m): m+=1 print(n,m)

Python

python
from functools import lru_cache def feasible_subset(n, labels, ret=False): V,D=ladder_dist(n); N=len(V) labels=tuple(sorted(labels)) req={} for i,a in enumerate(labels): for j,b in enumerate(labels): if i<j: req[(a,b)]=max(0,(2*n+1-(a+b)+1)//2) # constraint degree deg={a:sum(req[tuple(sorted((a,b)))]>0 for b in labels if b!=a) for a in labels} assigned={} used=set() # choose unassigned label with min remaining? Build candidates each step. def ok(a,v): for b,u in assigned.items(): r=req[tuple(sorted((a,b)))] if D[u,v]<r: return False return True def rec(): if len(assigned)==N: return True # choose label among unassigned with smallest candidates best=None; cands=None for a in labels: if a not in assigned: ca=[v for v in range(N) if v not in used and ok(a,v)] if not ca: return False # sort by degree descending? if best is None or len(ca)<len(cands) or (len(ca)==len(cands) and deg[a]>deg[best]): best=a; cands=ca # symmetry break: first label maybe restrict to one orbit? for v in cands: assigned[best]=v; used.add(v) if rec(): return True used.remove(v); del assigned[best] return False res=rec() if ret and res: return assigned.copy() return res for n in [5,7]: m=3*n-2-int((2*n-4)**0.5) print("n oldM",n,m) for skips in combinations(range(1,m+1), m-2*n): labels=[x for x in range(1,m+1) if x not in skips] if feasible_subset(n, labels): print("feasible",skips) break else: print("none") print("n7 labels 3..16", feasible_subset(7, range(3,17), ret=True))

Python

python
for n in range(8,11): for m in range(2*n, 2*n+10): ok=feasible(n,m) if ok: print("n",n,"m",m,"formula",2*n+(n-1)//2) break

Python

python
def active_feasible(t, ncols, ret=False): V,D=ladder_dist(ncols) deficits=list(range(t,1-t,-1)) # t,t-1,...,2-t # req between deficits req={} for a in deficits: for b in deficits: if a<b: req[(a,b)]=max(1,1+(a+b)//2) # floor in py ok for negative; but if <=1 automatic distinct distance>=1 assigned={} used=set() deg={a:sum(req[tuple(sorted((a,b)))]>1 for b in deficits if b!=a) for a in deficits} # order with MRV def ok(a,v): for b,u in assigned.items(): if D[u,v] < req[tuple(sorted((a,b)))]: return False return True def rec(): if len(assigned)==len(deficits): return True best=None;cands=None for a in deficits: if a not in assigned: ca=[v for v in range(len(V)) if v not in used and ok(a,v)] if not ca: return False if best is None or len(ca)<len(cands) or (len(ca)==len(cands) and deg[a]>deg[best]): best=a;cands=ca for v in cands: assigned[best]=v; used.add(v) if rec(): return True used.remove(v); del assigned[best] return False res=rec() if ret and res: return assigned.copy(), V return res for t in range(1,9): c=1 while not active_feasible(t,c): c+=1 print("t",t,"c",c, "old", (t*t//2 - t + 3 if t>=3 else (1 if t==1 else 3))) ass,V=active_feasible(t,c,True) # print sorted by column arr=[["." for _ in range(c)] for _ in range(2)] for x,v in ass.items(): r,col=V[v]; arr[r][col-1]=str(x) print(arr)

Python

python
def check_active_assignment(t,ncols, assign): V,D=ladder_dist(ncols) for x,vx in assign.items(): for y,vy in assign.items(): if x<y: req=max(1,1+((x+y)//2)) if D[vx,vy] < req: print("fail",x,y,D[vx,vy],req) return False return True V,D=ladder_dist(3) print(V) assign={2:0,1:4,0:2} # top col1, bottom col2 index? verts row0 col1..3, row1 col1..3 => bottom col2 index 4 print(check_active_assignment(2,3,assign)) print(active_feasible(2,3,True))

Python

python
import inspect print(inspect.getsource(ladder_dist))

Python

python
def ladder_dist(n): verts=[(r,i) for r in range(2) for i in range(1,n+1)] D={} for a,u in enumerate(verts): for b,v in enumerate(verts): D[a,b]=abs(u[1]-v[1])+(u[0]!=v[0]) return verts,D # redefine feasible def feasible(n,m, verbose=False): V,D=ladder_dist(n) N=len(V) labels=range(1,m+1) min_dist_req={} for a in labels: for b in labels: if a<b: req=max(0, (2*n+1 - (a+b) +1)//2) min_dist_req[(a,b)]=req assigned={} used_vertices=set() vert_order=list(range(N)) def can_assign(label, v): for lab,u in assigned.items(): req=min_dist_req[(lab,label) if lab<label else (label,lab)] if D[u,v] < req: return False return True def rec(label, used_count): if used_count==N: if verbose: print(assigned) return True if label>m: return False rem=m-label+1 if used_count+rem<N: return False # skip first maybe if rem > N-used_count and rec(label+1, used_count): return True for v in vert_order: if v not in used_vertices and can_assign(label,v): assigned[label]=v; used_vertices.add(v) if rec(label+1, used_count+1): return True used_vertices.remove(v); del assigned[label] return False return rec(1,0) for n in range(1,11): m=2*n while not feasible(n,m): m+=1 print(n,m, "old", 2 if n==1 else 3*n-2-int((2*n-4)**0.5))

Python

python
def pos_order(t): if t==1: return [1] if t%2==0: r=t//2 order=[2*r-1,2,1] for k in range(2,r): order += [2*k,2*k-1] # wait for t=6 r=3 should [5,2,1,4,3,6]? yes order += [2*r] if 2*r not in order else [] return order else: r=(t-1)//2 order=[2*r+1] # from 2r-2,2r-1 down to 2,3 then 1,2r for a in range(2*r-2,1,-2): order += [a,a+1] order += [1,2*r] return order for t in range(1,8): print(t,pos_order(t),len(pos_order(t))) def positive_positions(t): order=pos_order(t) cols=[1] rows=[0] for i in range(len(order)-1): a,b=order[i],order[i+1] cols.append(cols[-1]+(a+b)//2) # floor rows.append(1-rows[-1]) return {a:(r,c) for a,r,c in zip(order,rows,cols)}, order, cols[-1] def check_positions(pos,t): for a,(ra,ca) in pos.items(): for b,(rb,cb) in pos.items(): if a<b: d=abs(ca-cb)+(ra!=rb) req=max(1,1+(a+b)//2) if d<req: return False,(a,b,d,req) return True,None for t in range(2,7): pos,order,L=positive_positions(t) print("t",t,"L",L,"ell", (t*t//2 - t +3 if t>=3 else 3), "ok",check_positions(pos,t)) print(pos)

Python

python
def positive_positions_old(t): if t==1: return {1:(0,1)}, [1], 1 if t==2: # maybe place 2 and 1 at distance 2 in 3 cols, e.g. top1 bottom2; L=3 return {2:(0,1), 1:(1,2)}, [2,1], 3 if t%2==0: r=t//2 order=[2*r-1,2,1] for k in range(2,r): order += [2*k,2*k-1] order += [2*r] # remove duplicates if any? for r=2 no loop [3,2,1,4] else: r=(t-1)//2 order=[2*r+1] for a in range(2*r-2,1,-2): order += [a,a+1] order += [1,2*r] cols=[1]; rows=[0] for i in range(len(order)-1): a,b=order[i],order[i+1] gap=(a+b)//2 if t%2==0

Python

python
def simple_complete(t): pos, order,L=positive_positions_old(t) comp=pos.copy() for s in range(0,t-1): # q=-s, target positive s+1 p=s+1; q=-s if q in comp: continue r,c=pos[p] comp[q]=(1-r,c) return comp,L for t in range(1,8): comp,L=simple_complete(t) print(t,L, check_positions(comp,t)) if not check_positions(comp,t)[0]: print(comp)

Python

python
def safe_positions_for_q(t,q, fixed=None): pos,order,L=positive_positions_old(t) if fixed: pos={**pos, **fixed} occupied=set(pos.values()) safe=[] for r in [0,1]: for c in range(1,L+1): if (r,c) in occupied: continue ok=True for p,(rp,cp) in pos.items(): req=max(1,1+((q+p)//2)) d=abs(c-cp)+(r!=rp) if d<req: ok=False; break if ok: safe.append((r,c)) return safe for t in [5,6,7]: print("t",t,"positive",positive_positions_old(t)[0]) fixed={} for q in range(0,1-t,-1): safe=safe_positions_for_q(t,q,fixed) print("q",q,"safe first",safe[:20],"count",len(safe)) # choose CP perhaps lexicographic if safe: fixed[q]=safe[0] print("greedy",fixed, check_positions({**positive_positions_old(t)[0],**fixed},t))

Python

python
for t in [8,9,10]: pos,order,L=positive_positions_old(t) fixed={} ok=True for q in range(0,1-t,-1): safe=safe_positions_for_q(t,q,fixed) if not safe: ok=False; break fixed[q]=safe[0] print("t",t,"L",L,"ok",ok, "check", check_positions({**pos,**fixed},t) if ok else None) print("order",order) print("pos",pos) print("fixed",fixed)

Python

python
def explicit_complete(t): pos,order,L=positive_positions_old(t) comp=pos.copy() if t==1: return comp,L if t==2: # positive positions old: q2 top c1, q1 bottom c2, L=3 comp[0]=(0,3) return comp,L if t%2==1: r=(t-1)//2 # q0: same row as q1, column c(q1)-1 r1,c1=pos[1] comp[0]=(r1,c1-1) for s in range(1,t-1): if s%2==1: k=(s+1)//2 c=r+k+1 else: k=s//2 c=r+2-k comp[-s]=(0,c) else: r=t//2 comp[0]=(0,r+3) for s in range(1,t-1): if s==1: c=r+1 elif s%2==0: k=s//2 c=r+1-k else: k=(s-1)//2 # s=2k+1 c=r+k+3 comp[-s]=(0,c) return comp,L for t in range(1,15): comp,L=explicit_complete(t) ok=check_positions(comp,t) used=len(set(comp.values()))==len(comp) within=all(1<=c<=L and r in (0,1) for r,c in comp.values()) print(t,L,ok,used,within) if not ok[0] or not used or not within: print(comp) break

Python

python
for t in [11,12,13,14,15]: pos,order,L=positive_positions_old(t) fixed={} for q in range(0,1-t,-1): safe=safe_positions_for_q(t,q,fixed) if not safe: print("fail q",q) break fixed[q]=safe[0] print("t",t,"L",L,"check",check_positions({**pos,**fixed},t)) print("fixed",fixed)

Python

python
def simple_neg_right(t,row=1): pos,order,L=positive_positions_old(t) comp=pos.copy() for s in range(0,t-1): comp[-s]=(row,L-s) return comp,L for row in [0,1]: okall=True for t in range(3,20): comp,L=simple_neg_right(t,row) if len(set(comp.values()))<len(comp): okall=False; print("row",row,"bad coll",t); break ok=check_positions(comp,t) if not ok[0]: okall=False; print("row",row,"bad",t,ok[1]); break print(row,okall)

Python

python
for t in range(3,31,2): comp,L=explicit_complete(t) ok=check_positions(comp,t) used=len(set(comp.values()))==len(comp) if not ok[0] or not used: print("odd fail",t, ok, used) break else: print("odd all ok")

Python

python
from itertools import permutations for s in range(1,8): mn=999; arg=None for p in permutations(range(1,s+1)): val=sum((p[i]+p[i+1])//2 for i in range(s-1)) if val<mn: mn=val;arg=p print(s,mn,arg,"ell", (1 if s==1 else 3 if s==2 else s*s//2-s+2)) # n-1? ell-1

Python

python
def construct_labels(n): if n==1: return {(0,1):1,(1,1):2} import math t=1+int(math.isqrt(2*n-4)) # floor sqrt M=3*n-t-1 comp,L=explicit_complete(t) # comp maps q to (row,col) within first L labels={} for q,(r,c) in comp.items(): labels[(r,c)]=n-q next_label=n+t-1 for c in range(1,n+1): for r in [0,1]: if (r,c) not in labels: labels[(r,c)]=next_label next_label+=1 assert next_label==M+1 return labels, t,M,L,comp labels,t,M,L,comp=construct_labels(10) print(t,M,L,comp) for r in [0,1]: print([labels[(r,c)] for c in range(1,11)]) # verify def verify_labeling(n, labels): V,D=ladder_dist(n) inv={v:labels[v] for v in labels} for i,u in enumerate(V): for j,v in enumerate(V): if i<j: if D[i,j]+((inv[u]+inv[v]+1)//2)<n+1: return False,u,v,D[i,j],inv[u],inv[v] return True print(verify_labeling(10,labels))

Python

python
def explicit_complete_even_with_B(t): pos,order,L=positive_positions_old(t) r=t//2 comp=pos.copy() if t==2: comp[0]=(0,3); return comp,L comp[0]=(0,r+3) # top occupied occupied_top={c for q,(row,c) in comp.items() if row==0} B=[] # generate enough terms seq=[r+1,r] for k in range(1,10*t): seq.extend([r+k+3, r-k]) seen=set() for a in seq: if a<1 or a>L or a in seen: continue seen.add(a) if a in occupied_top: continue B.append(a) if len(B)>=t-2: break for s,c in enumerate(B, start=1): comp[-s]=(0,c) return comp,L for t in range(2,60,2): comp,L=explicit_complete_even_with_B(t) ok=check_positions(comp,t) used=len(set(comp.values()))==len(comp) if not ok[0] or not used or len(comp)!=2*t-1: print("fail",t,L,ok,used,len(comp)) #print(comp) break else: print("even all ok")

Python

python
t=14 comp,L=explicit_complete_even_with_B(t) print({q:comp[q] for q in sorted(comp) if q<=0 or q in [13,3]}) print(check_positions(comp,t)) # find q -11 position print("pos -11",comp[-11], "pos13", comp[13])

Python

python
for t in [14]: pos,order,L=positive_positions_old(t) for q in sorted([q for q in pos]): print(q,pos[q])

Réflexion

Refining the labeling function explanation

I think the current wording works fine: the finite recursive rule defines the labeling function, and its validity is ensured by the inequalities during selection. Including a more formal algorithmic certificate in an appendix sounds like a good idea, but I also need to consider the length of the PDF. Renaming the file to Chinese and mentioning the updated version could be a simple solution.

Thought for 11m 27s

Réponse

已重新整理为 PDF,改为直接给出数学标号函数,并保留确切数值、表达式、下界与上界证明。

下载: P2_square_Pn_radio_mean_labeling_revised.pdf

Partager cette Q&R