#OK to post homework #Blair Seidler, 4/17/22, Assignment 22 with(combinat): with(ListTools): Help:=proc(): print(`LP(G), AvNuLP(n,p,K)`): end: #4. Using LaG(G), write a procedure LP(G) that inputs a directed graph w/o cycles, G # (let n:=nops(G)) and outputs the subest of {1,...,n} of its losing positions. LP:=proc(G): {SearchAll(0,LaG(G))}: end: #5. Write a procedure AvNuLP(n,p,K) that inputs a positive integer n, a rational number p # between 0 and 1 and a large integer K and outputs an approximation to the average size of # the set of losing positions, for a random directed graph (w/o cycles) with n vertices, by # averaging over K random graphs gotten from RDG(n,p). AvNuLP:=proc(n,p,K) i,s: evalf(add(nops(LP(RDG(n,p))),i=1..K)/K): end: (* What did you get for AvNuLP(n,p,10000) for 3*4=12 cases n=10,50, 100; p=1/5,2/5,3/5,4/5 *) RunAvNuLP:=proc() local n,p,K: K:=10000: for n in {10,50,100} do for p in {1/5,2/5,3/5,4/5} do printf("n=%d, p=%.1f, K=%d, AvNuLP(n,p,K)=%f\n",n,p,K,AvNuLP(n,p,K)): od: od: end: (* Output: n=10, p=0.2, K=10000, AvNuLP(n,p,K)=5.490100 n=10, p=0.4, K=10000, AvNuLP(n,p,K)=3.796100 n=10, p=0.6, K=10000, AvNuLP(n,p,K)=2.794700 n=10, p=0.8, K=10000, AvNuLP(n,p,K)=2.029800 n=50, p=0.2, K=10000, AvNuLP(n,p,K)=11.457600 n=50, p=0.4, K=10000, AvNuLP(n,p,K)=6.673300 n=50, p=0.6, K=10000, AvNuLP(n,p,K)=4.462900 n=50, p=0.8, K=10000, AvNuLP(n,p,K)=2.994500 n=100, p=0.2, K=10000, AvNuLP(n,p,K)=14.343700 n=100, p=0.4, K=10000, AvNuLP(n,p,K)=7.977900 n=100, p=0.6, K=10000, AvNuLP(n,p,K)=5.193500 n=100, p=0.8, K=10000, AvNuLP(n,p,K)=3.426900 *) #### Included from C22.txt #### #C22.txt: April 11, 2022 Help22:=proc(): print(`mex(S), ai(i), aiC(i), RDG(n,p), Parents(G), OneStep0(G,AL,T) , OneStep1(G,AL,T), OneStep(G,AL,T), LaG(G) `): end: #mex(S): inputs a set of NON-NEGATIVE integers and outputs the smallest #non-neg. intger NOT in the set S, i.e. min({0,1,2,3,...} minus S) mex:=proc(S) local i: for i from 0 while member(i,S) do od: i: end: #ai(i): the a-component in the losing position for Wythoff's game [a_i,i+a_i] ai:=proc(i) local j: option remember: if i=0 then RETURN(0): else mex({seq(ai(j),j=0..i-1),seq(ai(j)+j,j=0..i-1)}): fi: end: #aiC(i) : Faster way to compute ai(i) using Wythof's formula trunc(phi*i): aiC:=proc(i) trunc((1+sqrt(5))/2*i): end: #RDG(n,p): inputs a pos. integer n and a RATIONAL number p=a/b between 0 and 1 #and outputs a random directed graph w/o cycles such tha the prob. of #an edge is p RDG:=proc(n,p) local a,b,L,i,j,S,ra: a:=numer(p): b:=denom(p): ra:=rand(1..b): L:=[]: for i from 1 to n do S:={}: for j from i+1 to n do if ra()<=a then S:=S union {j}: fi: od: L:=[op(L),S]: od: L: end: #Parents(G): inputs a directed graph on {1,...,n} where n:=nops(G) such that G[i] is the set of children of i (the set of outgoing neihbors) #outputs the list whose i-th component is the set of "parents" of i, i.e. those j such that i belongs to G[j]. For example #Parents([{2,3},{3},{}]); should be [{},{1},{1,2}] Parents:=proc(G) local n,i,j,P: option remember: n:=nops(G): #We initialize all the parents-sets to be empty for j from 1 to n do P[j]:={}: od: for i from 1 to n do for j in G[i] do P[j]:=P[j] union {i}: od: od: #For each vertex i (we look for its children) and append i to the set of parents of each such child [seq(P[j],j=1..n)]: end: #OneStep0(G,AL,T): Given a graph G, with a set of already labelled vertices AL and a table T of lables #performs one step in the labelling algorithm, the implication that if a vertex is labeled 0 then all its parents are labeled 1 #(since there exists is a legal move that will make the opponent lose) OneStep0:=proc(G,AL,T) local AL1,n,T1,i,j,P: AL1:=AL: n:=nops(G): P:=Parents(G): T1:=T: for i in AL do if T1[i]=0 then for j in P[i] do T1:=[op(1..j-1,T1),1,op(j+1..n,T1)]: AL1:=AL1 union {j}: od: fi: od: RETURN(G,AL1,T1): end: #OneStep1(G,AL,T): Given a graph G, with a set of already labelled vertices AL and a table T of lables #performs one step in the labelling algorithm, that if all the children of a vertex are already labeld 1 then #it is labeled 0 (since whatever the player can do it would be winning for the opponent) OneStep1:=proc(G,AL,T) local n,T1,i,j: n:=nops(G): T1:=T: for i from 1 to n do if not member(i,AL) then if G[i] minus AL={} and {seq(T1[j],j in G[i])}={1} then T1:=[op(1..i-1,T1),0,op(i+1..n,T1)]: RETURN(G,AL union {i},T1): fi: fi: od: G,AL,T1: end: #OneStep(G,AL,T): Given a graph G, with a set of already labelled vertices AL and a table T of lables #performs one step in the labelling algorithm, that if all the children of a vertex are already labeld 1 then #it is labeled 0 (since whatever the player can do it would be winning for the opponent) OneStep:=proc(G,AL,T) local n,Hope: n:=nops(G): if nops(AL)=n then RETURN(G,AL,op(T)): fi: Hope:=OneStep0(G,AL,T): if nops(Hope[2])>nops(AL) then RETURN(Hope): fi: Hope:=OneStep1(G,AL,T): if nops(Hope[2])>nops(AL) then RETURN(Hope): fi: FAIL: end: #LaG(G) LaG:=proc(G) local n,i,AL,T,Hope: n:=nops(G): T:=[(-1)$n]: AL:={}: for i from 1 to n do if G[i]={} then T:=[op(1..i-1,T),0,op(i+1..n,T)]: AL:=AL union {i}: fi: od: Hope:=G,AL,T: while nops(Hope[2])