function corinnawrapper global Xd Yd L0 = 9; %** %L0 = 5; alf = 'abc'; if isempty(Xd) [Xd,Yd] = reglang_posneg_dense(0,L0,null_dfsa(alf)); end global fname REPFID fname = 'runningreport.txt'; REPFID = fopen(fname,'w'); myprint('Empirically testing Corinna''s algorithm \n'); myprint('on randomly generated piecewise-testable languages \n'); TESTREC = []; good = 1; while good % generate rand pt-language goodM = 0; while ~goodM fprintf('generating random pt-language...\n'); M = randpt('abc',0,2,1,15); % have we observed M before? newM = 1; for i=1:length(TESTREC) newM = ~empty_fsa(symdiff_dfsa(M,TESTREC(i))); if ~newM, break; end end % compute Corinna's L L = getcorL(M); %goodM = (newM & (L<=10)); % just to keep length reasonable %** goodM = (newM & (L<=7)); % just to keep length reasonable end TESTREC = [TESTREC; M]; myprint('----------------------------------------------------------\n'); myprint(fsa2str(M)); % generate sample of length 0 to L [X,Y] = reglang_posneg_dense(0,L,M); % get the separator via Corinna's algorithm [U,w,MU] = trainptonsample(M,X); % display features & weights print_uw(U,w); if length(U)<9 %** %if length(U)<9 % we can get a closed-form, 100% certain answer % by computing the explicit automaton represented by the separator myprint(sprintf('|U| = %d is small, so we are computing \n',length(U))); myprint('explicit automaton represented by the separator w \n'); M1 = wb2dfsa_pt(U,w,0,M.ALF); Md = symdiff_dfsa(M,M1); good = empty_fsa(Md); if good myprint('Good news! We''ve recovered M exactly. There is no need for random testing.\n'); else [b,x] = accept_str(Md); myprint('PROBLEM!! The automaton represented by w is not identical to M: \n'); print_fsa(M1); myprint(sprintf('The two differ on the string x = [%s] \n',x)); end else % can't get 100% certainty, must test randomly myprint(sprintf('|U| = %d is too big to recover explicitly \n',length(U))); myprint(sprintf('Testing on sample of all strings of length up to %d \n',L0)); eval_muw_c(MU,w,X,M); TT = 10000; %** %TT = 100; myprint(sprintf('Testing on a sparse random sample of %d random strings\n',TT)); test_sparse(M,U,MU,w,TT,.3); end end fclose(REPFID); return function test_sparse(M,U,MU,w,TT,lam) X0 = simple_paths(M); RR = {}; for i=1:length(X0) RR{i} = spath2cell(M,X0{i}); end %PROGstart(TT,'sparse testing'); PROGstart(TT); for t=1:TT for i=1:length(X0) x = sample_from_sp(RR{i},lam); y = b2y(run_dfsa(M,x)); %myprint('x = %s\n',x); %myprint('x = %s; y = %d\n',x,y); %y_hat = compute_yhat_c(Xii,{x},aa,b0,@ptkermx); y_hat = eval_muw(MU,w,x); if y~=y_hat myprint('PROBLEM!! The separator w disagrees with M \n'); myprint(sprintf('on the string x = [%s] \n',x)); end end PROGupdate(t); end PROGend; return function print_uw(u,w) for i=1:length(u) myprint(sprintf('%3d. u=[%s] w = %1.5f \n',i,u{i},w(i))); end return function eval_muw_c(MU,w,X,M) nx = length(X); PROGstart(nx); for i=1:length(X) yh = eval_muw(MU,w,X{i}); yt = b2y(run_dfsa(M,X{i})); if yt*yh+1e-10 < 0 myprint('PROBLEM!! The separator w disagrees with M \n'); myprint(sprintf('on the string x = [%s] \n',x)); keyboard end PROGupdate(i); end PROGend; return function str = fsa2str(DFSA) str = ''; DS = deadstate_dfsa(DFSA); str = [str sprintf('Alphabet: "%s"\n',DFSA.ALF)]; str = [str sprintf('The states Q: %s\n',num2str(DFSA.Q))]; str = [str sprintf('Start state: %d\n',DFSA.q0)]; str = [str sprintf('Accepting states: [%s]\n',num2str(sort(DFSA.F)))]; str = [str sprintf('Dead states: %s\n',num2str(DS))]; for q = setdiff(DFSA.Q,DS) % the new, more convenient to view way [rr,ss] = get_ddelta(DFSA,q); % don't show dead state transitions %x = find(~ismember(rr,DS)); % DO show deadstate transitions x = find(rr); rr=rr(x); ss=ss(x); ru = unique(rr); if ~isempty(ru) for r=ru x=find(r==rr); S=ss(x); str = [str sprintf('(%3d,%5s) -> %3d \n',q,S,r)]; end end end return function myprint(str) global fname REPFID fprintf(str); fprintf(REPFID,str); fclose(REPFID); REPFID = fopen(fname,'a'); return function s = sample_from_sp(R,lam) % larger lam => longer strings s = ''; for i=1:length(R) A = R{i}; if length(A)==1 s(end+1) = A; else while 1 a = randel(A); if a == '@' if rand > lam break end else s(end+1) = a; end end end end s = strrep(s,'@',''); return