From bug-octave-request at bevo dot che dot wisc dot edu Thu Nov 5 06:54:10 1998 Subject: Problems with arrays of strings From: Francesco Potorti` To: Octave bugs list Date: Thu, 5 Nov 1998 06:53:50 -0600 (CST) I read in the octave manual: - Function File: str2mat (S_1, ..., S_N) Return a matrix containing the strings S_1, ..., S_N as its rows. Each string is padded with blanks in order to form a valid matrix. *Note:* This function is modelled after MATLAB. In Octave, you can create a matrix of strings by `[S_1; ...; S_N]' even if the strings are not all the same length. but: octave:2> x=["a";"ab"] x = a ab octave:4> y=x(1,:) y = a octave:5> length(y) ans = 2 <-- strings are all the same length, contrary to what I expected octave:7> strcat("`",y,"'") ans = `a ' octave:8> version ans = 2.0.13.91 Moreover, running this script I get: ---------- test.sh ------- #! /usr/bin/octave -qf [argv(1,:), ".inp"] -------------------------- $ test.sh td6 25407 1025724 ans = td6 and I also get an internal error from octave running the script appended: $ make_markov_inp.sh td6 25407 1025724 ofile = td6 error: octave_char_matrix_str::valid_as_scalar_index(): not implemented error: string type invalid as index value error: evaluating index expression near line 108, column 16 error: evaluating assignment expression near line 108, column 14 error: called from `make_markov_inp' in file `/home/foda/fracas/make_markov_inp.m' --------- make_markov_inp.sh ----------- #! /usr/bin/octave -qf make_markov_inp(argv(1,:), str2num(argv(2,:)), str2num(argv(3,:))); ---------------------------------------- --------- make_markov_inp.m ------------ function make_markov_inp (ifile, mint, maxt) ## Read an IFILE containing a matrix with states and write IFILE.inp in ## the format described below. If IFILE.inp already exists, the old file ## is renamed as IFILE.inp~. ## The throughput of the resulting generator will be comprised between ## MINT and MAXT, scaled so that the mean throughput is 1. ## ## Each line of FILE.inp contains: ## - A positive integer which is the name of a state ## - A float which is the probability that the state will be the initial ## state. ## - A float which is the stationary state probability of the state. ## - A float representing the throughput relative to that state. ## - A number of pairs made of: ## -- A positive integer which is the name of a state where to go from ## the current state. ## -- A float representing the transition probability to that state from ## the current state. save_prefer_column_vectors = prefer_column_vectors; unwind_protect prefer_column_vectors = 0; ## Open and read the input file contents if (mint >= maxt) error ("mint must be less than maxt"); endif ifid = fopen (ifile, "r"); m = fscanf (ifid, " from stato %u to stato %u p= %f", [3, Inf]); fclose (ifid); ## Check the file contents and build s (full matrix), used (vector of used ## states), and u (s normalised with unused states removed). states = m(1,columns(m)); s = zeros (states, states); for i=1:columns(m) s(m(1,i),m(2,i)) = m(3,i); endfor ss = sum (s'); # Sum of the rows: should be 1 or 0 goodmatrix = all (abs(ss-1) > 10e-3 | abs(ss) > 10e-3); if (!goodmatrix) error ("matrix not good: sum different from 1"); endif used = find (abs(ss-1) <= 10e-3); # Used states nused = length (used); # Number of used states usedcols = find (sum(s) > 0); if (any (used != usedcols)) error ("matrix not good: used row and columns differ"); endif u = s(used,used); # Matrix of used states only uu = sum (u'); # Used for normalisation u = (u' ./ uu(ones(nused,1),:))'; # Force sum of rows to 1 ## Compute the stationary state probabilities [V, l] = eig (u'); # Compute einvectors and eigenvalues stat = find (abs(diag(l)-1) < sqrt(eps)); # Locate eigenvalues equal to 1 if (length(stat) != 1) # There must be one at least error ("matrix not good: more than one stationary state"); endif ps = V(:,stat); # Consider the corrensponding autovector ps = ps' / sum (ps); # Normalise it ## Now consider only the transient states trans = find (abs(ps) == 0); # Consider the transient states ntrans = length (trans); if (ntrans < 1) # There must be at least one error ("matrix not good: no transient states"); endif t = u(trans,trans); # Take them as if they were independent tt = sum (t'); # Used for normalisation t = (t' ./ tt(ones(ntrans,1),:))'; # Force sum of rows to 1 ## Compute the stationary state probabilities of the transient state ## considered isolated [V, l] = eig (t'); # Compute einvectors and eigenvalues stat = find (abs(diag(l)-1) < sqrt(eps)); # Locate eigenvalues equal to 1 if (length(stat) != 1) # There must be one at least error ("transient matrix not good: more than one stationary state"); endif pt = V(:,stat); # Consider the corrensponding autovector pt = pt' / sum (pt); # Normalise it ## Build the vector of initial probabilities considering only the ## transient state p = zeros (1, nused); p(trans) = pt; ## Compute the vector of throughputs in such a way that the mean ## throuput of the markov chain is 1. There are 8 possible different ## throughputs, and the throughput of state number N is ## mint+(maxt-mint)/8*(1/2+N%8). thr = mint + (maxt - mint) / 8 * (0.5 + rem (used, 8)); thr = thr / sum (thr .* ps); ## Create the output file ofile = [ifile, ".inp"] [s, err] = stat (ofile) if (err != 0) backup = [ofile, "~"] [err, msg] = rename (ofile, backup) if (err != 0) error ("cannot rename %s to %s\n", ofile, backup); endif endif ofid = fopen (ofile, "w"); for i=1:rows(u) fprintf (ofid, "%3u %.4f %.4f %.4f", used(i), p(i), ps(i), thr(i)); j = find (u(i,:) > 0); fprintf (ofid, " %3u %.4f", [used(j); u(i,j)]); fprintf (ofid, "\n"); endfor fclose (ofid); unwind_protect_cleanup prefer_column_vectors = save_prefer_column_vectors; end_unwind_protect endfunction ## Local Variables: ## comment-column: 40 ## End: ----------------------------------------