Column it's not supposed to look at is 'out of domain' - ampl

I get the following out-of-domain error, see below. The thing is, in the referred line, q comes out of the Qualities set, which does not even contain the LAT value. How can I prevent this from happening, and keep all my data in one table? I've been trying to work around it using the separate latdata table, but this looks ugly and redundant to me.
$ glpsol -m ron.mod
GLPSOL: GLPK LP/MIP Solver, v4.60
Parameter(s) specified in the command line:
-m ron.mod
Reading model section from ron.mod...
Reading data section from ron.mod...
86 lines were read
Generating req...
ron.mod:20: cannot convert LAT to floating-point number
MathProg model processing error
MacBook-Air-van-Ron:examples raarts$ glpsol -m ron.mod
GLPSOL: GLPK LP/MIP Solver, v4.60
Parameter(s) specified in the command line:
-m ron.mod
Reading model section from ron.mod...
Reading data section from ron.mod...
86 lines were read
Generating req...
ron.mod:20: data[DO_MINI,LAT] out of domain
MathProg model processing error
the source for ron.mod is below:
set AllProducts;
/* all products */
set Qualities;
/* minrequired */
param data{prod in AllProducts, {"price"} union Qualities};
param latdata{prod in AllProducts, "LAT"};
param maxallowed{"LAT"};
set Product := setof{ prod in AllProducts: latdata[prod, "LAT"] <= maxallowed["LAT"]} prod;
param minrequired{q in Qualities};
var x{p in Product}, integer, >= 0;
subject to req{q in Qualities}: sum{p in Product} data[p,q] * x[p] >= minrequired[q];
minimize cost: sum{p in Product} x[p] * data[p, "price"];
solve;
printf "aantal product CPU RAM DISK PR/STUK TOTAAL\n";
printf{p in Product: x[p] != 0} "%6d %-12s %6d %6d %6d %8.2f %8.2f\n", x[p], p, data[p,"CPU"] * x[p], data[p,"RAM"] * x[p], data[p,"DISK"] * x[p],data[p,"price"], data[p,"price"] * x[p];
printf "%6s %-12s %6d %6d %6d %8.2s %8.2f\n", "", "", sum{p in Product} data[p,"CPU"] * x[p], sum{p in Product} data[p,"RAM"] * x[p], sum{p in Product} data[p,"DISK"] * x[p], "", sum{p in Product} data[p,"price"] * x[p];
data;
param data : price CPU RAM DISK LAT :=
DO_MINI 5.00 1 512 20 2
DO_SMALL 10.00 2 1024 30 2
DO_MEDIUM 15.00 2 2048 40 2
DO_LARGE 25.00 3 4096 75 2
SW_MINI 5.00 1 1024 10 3
SW_SMALL 10.00 2 1024 15 3
SW_MEDIUM 15.00 2 2048 25 3
SW_LARGE 25.00 3 4096 50 3
BP_LARGE 5.00 3 4096 50 20
;
param latdata : LAT :=
DO_MINI 2
DO_SMALL 2
DO_MEDIUM 2
DO_LARGE 2
SW_MINI 3
SW_SMALL 3
SW_MEDIUM 3
SW_LARGE 3
BP_LARGE 20
;
set AllProducts :=
DO_MINI
DO_SMALL
DO_MEDIUM
DO_LARGE
SW_MINI
SW_SMALL
SW_MEDIUM
SW_LARGE
BP_LARGE
;
param minrequired :=
CPU 15
RAM 64000
DISK 1250
;
param maxallowed :=
LAT 5
;
set Qualities :=
CPU
RAM
DISK
;
end;

You can keep all the data in one table by allowing "LAT" in the data parameter:
param data{prod in AllProducts, {"price", "LAT"} union Qualities};
Then latdata can simply copy the LAT data from it:
param latdata{prod in AllProducts} = data[prod, "LAT"];
This will solve the out of domain error because ('DO_MINI', 'LAT') will be in the indexing set of data making this data statement valid:
param data : price CPU RAM DISK LAT :=
DO_MINI 5.00 1 512 20 2 # <- data[DO_MINI, LAT]
...

Related

Initialize a two-dimensional array from literals

I have this data file:
param: name car pro fat vit cal :=
1 'Fiddleheads' 3 1 0 3 80
2 'Fireweed Shoots' 3 0 0 4 150
3 'Prickly Pear Fruit' 2 1 1 3 190
;
and this model:
set I;
set J;
param name{I} symbolic;
param car{I} integer >= 0;
param pro{I} integer >= 0;
param fat{I} integer >= 0;
param vit{I} integer >= 0;
param cal{I} integer >= 0;
param nut{i in I, J} = (car[i], pro[i], fat[i], vit[i]);
The last line is invalid:
mod, line 10 (offset 176):
syntax error
context: param nut{i in I, J} = >>> (car[i], <<< pro[i], fat[i], vit[i]);
but I don't know how to get an equivalent working. Essentially, I want to form a {3,4} array based on a literal expression. I've tried a handful of different syntaxes both in the data and model file and haven't been able to get any working.
Model:
set names;
set components;
param nut{names,components} default 0;
Data:
set names :=
Fiddleheads
'Fireweed Shoots'
'Prickly Pear Fruit';
set components := car pro fat vit cal
;
param nut :=
[Fiddleheads,*]
car 3 pro 1 vit 3 cal 80
['Fireweed Shoots',*]
car 3 vit 4 cal 150
['Prickly Pear Fruit',*]
car 2 pro 1 fat 1 vit 3 cal 190
;
See Chapter 9 of the AMPL Book for variants.
The "default 0" option avoids the need to explicitly list zero values, which can be useful for sparse data sets.
It would be useful to have an AMPL input format that allows a 2-D parameter to be specified in a simple table layout with row and column headers, along the lines of your data step, but I'm not aware of one that does this.

Retrive data by row with lag function

Good morning.
I've this dataset:
Appendix | Change_Serial_Number| Status | Duration | Mileage | Service
20101234 0 . 60 120000 Z
20101234 1 Proposed 48 110000 Z
20101234 2 Activated 24 90000 Z
20101234 3 Proposed 60 120000 Z
20101234 4 Proposed 50 160000 B
20101234 5 Activated 36 110000 B
Each row is a variation that could be activated or only proposed with the first row with status like blank or the previously activated variation.
I need to have this table:
Appendix | Change_Serial_Number| Status | Duration | Mileage | Service |Duration_Prev| Mileage_prev |
20101234 0 . 60 120000 Z .
20101234 1 Proposed 48 110000 Z 60 120000
20101234 2 Activated 24 90000 Z 60 120000
20101234 3 Proposed 60 120000 Z 24 90000
20101234 4 Proposed 50 160000 B 24 90000
20101234 5 Activated 36 110000 B 24 90000
I need to compare the duration, mileage and service of each variation with the previously activated or with the initial condition only if there aren't variation activated.
I tried with lag function to retrieve a data of previous row, but i need to retrieve data of 3 field and retrieve data only from the last activated variation or, if there aren't, from the initial condition.
I used this code:
proc sort data=db_rdg;
by Appendix Change_Serial_Number descending Change_Serial_Number;
run;
data db_rdg2;
set db_rdg;
by Appendix;
Duration_prev=lag(Duration);
if first. Appendix then Durata_prev =.;
run;
With this code, i can retrieve a data only from the previously row (not from the previosly actived row or from the first condition) and only for a duration variable (not at the same time for duration, mileage and service).
I hope I have been clear enough :)
Thank you for your help!
The lag() function is only really useful for working with values from a specific number of observations earlier. In this case, you don't know whether the values you want to work with are from the previous observation or from five or six observations earlier, so instead of using lag(), you should RETAIN the additional variables and update their values when appropriate:
data db_rdg2;
retain duration_prev .;
set db_rdg;
by Appendix;
if first.Appendix or status = 'Activated' then duration_prev = duration;
run;
The RETAIN statement allows duration_prev to retain its value as each new observation in read from the input, instead of being reset to missing.
http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000214163.htm
Instead of using LAG to retrieve the duration from the prior row, you will want to store the activate state tracking variables (for duration, mileage and serial) in a variable that is retained and updated after an explicit output.
In these two sample codes I tossed in tracking serial as you may want to know # of changes from prior activate.
data have; input
Appendix Change_Serial_Number Status $ Duration Mileage Service $;
datalines;
20101234 0 . 60 120000 Z
20101234 1 Proposed 48 110000 Z
20101234 2 Activated 24 90000 Z
20101234 3 Proposed 60 120000 Z
20101234 4 Proposed 50 160000 B
20101234 5 Activated 36 110000 B
run;
* NOTE: _APA suffix means # prior activate;
* version 1;
* implicit loop with by group processing means ;
* explicit first. test needed in order to reset the apa tracking variables;
data want;
set have;
by appendix;
if first.appendix then do;
length csn_apa dur_apa mil_apa 8;
call missing(csn_apa, dur_apa, mil_apa);
end;
output;
if status in (' ' 'Activate') then do;
csn_apa = change_serial_number;
dur_apa = duration;
mil_apa = mileage;
end;
retain csn_apa dur_apa mil_apa;
run;
* version 2;
* DOW version;
* explicit loop over group means first. handling not explicitly needed;
* implicit loop performs tracking variable resets;
* retain not needed because output and tracking variables modified;
* within current iteration of implicit loop;
data want2;
do until (last.appendix);
set have;
by appendix;
output;
if status in (' ' 'Activate') then do;
csn_apa = change_serial_number;
dur_apa = duration;
mil_apa = mileage;
end;
end;
run;

Why my rules of bison don't work

Every time I run my parser, it will appear "syntax error in line 1 near <>" (Because there is a subroutine yyerror(char *s)). I think that's because there is something wrong with my rules in bison.
The file (c17.isc) I want to parse.
*c17 iscas example (to test conversion program only)
*---------------------------------------------------
*
*
* total number of lines in the netlist .............. 17
* simplistically reduced equivalent fault set size = 22
* lines from primary input gates ....... 5
* lines from primary output gates ....... 2
* lines from interior gate outputs ...... 4
* lines from ** 3 ** fanout stems ... 6
*
* avg_fanin = 2.00, max_fanin = 2
* avg_fanout = 2.00, max_fanout = 2
*
*
*
*
*
1 1gat inpt 1 0 >sa1
2 2gat inpt 1 0 >sa1
3 3gat inpt 2 0 >sa0 >sa1
8 8fan from 3gat >sa1
9 9fan from 3gat >sa1
6 6gat inpt 1 0 >sa1
7 7gat inpt 1 0 >sa1
10 10gat nand 1 2 >sa1
1 8
11 11gat nand 2 2 >sa0 >sa1
9 6
14 14fan from 11gat >sa1
15 15fan from 11gat >sa1
16 16gat nand 2 2 >sa0 >sa1
2 14
20 20fan from 16gat >sa1
21 21fan from 16gat >sa1
19 19gat nand 1 2 >sa1
15 7
22 22gat nand 0 2 >sa0 >sa1
10 20
23 23gat nand 0 2 >sa0 >sa1
21 19
My flex file is as follows and it is right. You can find some information about how my scanner work here.
Error in the output of my flex file
declare.h
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# define INPT 1
# define NOR 2
# define NAND 3
# define NOT 4
# define XOR 5
# define AND 6
# define BUFF 7
# define FROM 8
flex file is
%{
# include "declare.h"
# include "parse.tab.h"
/*gi=1,it's input;gi=8,it's fanout;otherwise,it's gate*/
static int gi=-1;
static int inum=0;
struct{
char *symbol;
int val;
} symtab[]={
{"inpt", INPT},
{"nor", NOR},
{"nand", NAND},
{"not", NOT},
{"xor", XOR},
{"and", AND},
{"buff", BUFF},
{"from",FROM},
{"0",0}
};
extern FILE *yyin;
extern int yylval;
%}
%start A B C D E
DIGITS [0-9]+
BLANK [ \t\n\r\f\v\b]+
ALPHA [a-z]+
%%
"*".*\n {BEGIN A; return(COMMENT);}
<A>{DIGITS} {yylval=atoi(yytext); BEGIN B; return(NUM);}
<B>{DIGITS}{ALPHA} {yylval=atoi(yytext); BEGIN C; return(GNAME);}
<C>{DIGITS} {yylval=atoi(yytext); BEGIN D; return(OPNUM);}
<C>{DIGITS}{ALPHA} {yylval=atoi(yytext); BEGIN A; return(FR);}
<D>{DIGITS} {inum=atoi(yytext);
yylval=inum;
if(gi==1)
{BEGIN A;}
if(gi!=1)
{BEGIN E;}
return(IPNUM);
}
<E>{DIGITS} {inum--;
yylval=atoi(yytext);
if(inum<0)
{BEGIN B; return(NUM);}
else
{BEGIN E; return(ILIST);}
}
{ALPHA} {yylval=lookup(yytext);
return(GTYPE);
}
">sa"[0-1] {yylval=atoi(&yytext[yyleng-1]);return(FAULT);}
{BLANK} ;
. ;
%%
int lookup(const char *s)
{
int i;
for (i = 0; symtab[i].val != 0; i++)
{
if (strcmp(symtab[i].symbol, s) == 0)
break;
}
return(symtab[i].val);
}
The right rules in bison file are as follows
parto:
| parto COMMENT
| parto parti
;
parti: NUM
{...}
GNAME
{...}
GTYPE
{...}
| parti partii
| parti partiii
;
partii:OPNUM
{...}
IPNUM
{...}
partiv
partv
;
partiii: FR
{...}
partiv
;
partiv:
| partiv FAULT
{...}
;
partv:
| partv ILIST
{...}
;
Transferring the key comments into an answer.
The first edition of the code had a couple of problems. In the scanner code, there were lines like this:
<A>{DIGITS} { yylval=atoi(yytext); return(NUM); BEGIN B; }
You should be getting warnings about unreachable code from the BEGIN operations appearing after return. The BEGIN operations have to be executed. They aren't being executed, so you're not switching into your start states.
Michael commented:
There is no warning. I've modified it as you say and edit my codes in the question. Now I put return after BEGIN. Still, "syntax error in line 1 near <�>".
This probably means you aren't compiling the C code with enough warnings. Assuming you're using GCC, add -Wall to the compilation options for starters. There's a chance the warning requires optimization too.
Have you printed the tokens as they're returned (in the Flex scanner)? Have you compiled the Bison grammar with -DYYDEBUG? You also need to turn the debug on: yydebug = 1; in the main() program. You're probably not getting the tokens you expect when you expect them. I've not tried compiling this code yet. Tracking the tokens is key (in my experience) to getting grammars to work. Otherwise, you're running blind.
The other problem (closely related) is that you need to generate the symbolic names for FAULT etc from the grammar (bison -d grammar.y generates grammar.tab.h). You'll find that COMMENT is assigned the value 258, for example. Your scanner, though, is returning other numbers altogether because they're in declare.h. You'll have to fix this mismatch. One option is to #include "grammar.tab.h" in your scanner; this is more or less normal.
In retrospect, I think this is probably the most important observation; things seemed to revert to normal C debugging after this was resolved.
(People often include 'grammar.h' and only update 'grammar.h' if the content of 'grammar.tab.h' changes, so you don't recompile the scanner all the time).
The significance of this is that the set of tokens used by a grammar tends to be fairly stable while the actions associated with the rules change all the time as the implementation of the grammar evolves. So, if it takes enough time to be worth worrying about, you can create file grammar.h that is a copy of grammar.tab.h, but only update grammar.h when the content of grammar.tab.h changes.
cmp -s grammar.tab.h grammar.h || cp grammar.tab.h grammar.h
You'd include this in the makefile rule that converts that grammar into a C file (or an object file).
If the scanner is small enough and your machine fast enough, it may be simpler not to bother with this refinement; it mattered more in the days of 50 MHz machines with a few MiB of RAM than it does in these days of multiple cores running at 2+ GHz with a few GiB of RAM.

Printing numeric values < NF in awk?

I ran a bunch of tests using pgbench, logging the results:
run-params: 1 1 1
transaction type: SELECT only
scaling factor: 1
query mode: simple
number of clients: 1
number of threads: 1
duration: 90 s
number of transactions actually processed: 280465
tps = 3116.254233 (including connections establishing)
tps = 3116.936248 (excluding connections establishing)
run-params: 1 1 2
transaction type: SELECT only
scaling factor: 1
query mode: simple
number of clients: 1
number of threads: 1
duration: 90 s
number of transactions actually processed: 505943
tps = 5621.570463 (including connections establishing)
tps = 5622.811538 (excluding connections establishing)
run-params: 10000 10 3
transaction type: SELECT only
scaling factor: 10000
query mode: simple
number of clients: 10
number of threads: 1
duration: 90 s
number of transactions actually processed: 10
tps = 0.012268 (including connections establishing)
tps = 0.012270 (excluding connections establishing)
I want to extract the values for graphing. Trying to learn AWK at the same time. Here's my AWK program:
/run-params/ { scaling = $2 ; clients = $3 ; attempt = $4 }
/^tps.*excluding/ { print $scaling "," $clients "," $attempt "," $3 }
When I run that, I get the following output:
$ awk -f b.awk -- b.log
tps,tps,tps,3116.936248
tps,tps,=,5622.811538
,,0.012270,0.012270
Which is not what I want.
I understand when scaling = 1, the 1 references field 1, which in this case happens to be tps. When scaling = 10000, because there aren't 10000 fields on the line, then null is returned. I did try assigning scaling and friends using "" $2, to no avail.
How does one use / report numeric values in a subsequent action block?
Simply drop the $ in front of scaling, etc. That is, scaling is a variable reference, $scaling is a field reference.

Hash function to iterate through a matrix

Given a NxN matrix and a (row,column) position, what is a method to select a different position in a random (or pseudo-random) order, trying to avoid collisions as much as possible?
For example: consider a 5x5 matrix and start from (1,2)
0 0 0 0 0
0 0 X 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
I'm looking for a method like
(x,y) hash (x,y);
to jump to a different position in the matrix, avoiding collisions as much as possible
(do not care how to return two different values, it doesn't matter, just think of an array).
Of course, I can simply use
row = rand()%N;
column = rand()%N;
but it's not that good to avoid collisions.
I thought I could apply twice a simple hash method for both row and column and use the results as new coordinates, but I'm not sure this is a good solution.
Any ideas?
Can you determine the order of the walk before you start iterating? If your matrices are large, this approach isn't space-efficient, but it is straightforward and collision-free. I would do something like:
Generate an array of all of the coordinates. Remove the starting position from the list.
Shuffle the list (there's sample code for a Fisher-Yates shuffle here)
Use the shuffled list for your walk order.
Edit 2 & 3: A modular approach: Given s array elements, choose a prime p of form 2+3*n, p>s. For i=1 to p, use cells (iii)%p when that value is in range 1...s-1. (For row-length r, cell #c subscripts are c%r, c/r.)
Effectively, this method uses H(i) = (iii) mod p as a hash function. The reference shows that as i ranges from 1 to p, H(i) takes on each of the values from 0 to p-1, exactly one time each.
For example, with s=25 and p=29 or 47, this uses cells in following order:
p=29: 1 8 6 9 13 24 19 4 14 17 22 18 11 7 12 3 15 10 5 16 20 23 2 21 0
p=47: 1 8 17 14 24 13 15 18 7 4 10 2 6 21 3 22 9 12 11 23 5 19 16 20 0
according to bc code like
s=25;p=29;for(i=1;i<=p;++i){t=(i^3)%p; if(t<s){print " ",t}}
The text above shows the suggestion I made in Edit 2 of my answer. The text below shows my first answer.
Edit 0: (This is the suggestion to which Seamus's comment applied): A simple method to go through a vector in a "random appearing" way is to repeatedly add d (d>1) to an index. This will access all elements if d and s are coprime (where s=vector length). Note, my example below is in terms of a vector; you could do the same thing independently on the other axis of your matrix, with a different delta for it, except a problem mentioned below would occur. Note, "coprime" means that gcd(d,s)=1. If s is variable, you'd need gcd() code.
Example: Say s is 10. gcd(s,x) is 1 for x in {1,3,7,9} and is not 1 for x in {2,4,5,6,8,10}. Suppose we choose d=7, and start with i=0. i will take on values 0, 7, 14, 21, 28, 35, 42, 49, 56, 63, 70, which modulo 10 is 0, 7, 4, 1, 8, 5, 2, 9, 6, 3, 0.
Edit 1 & 3: Unfortunately this will have a problem in the two-axis case; for example, if you use d=7 for x axis, and e=3 for y-axis, while the first 21 hits will be distinct, it will then continue repeating the same 21 hits. To address this, treat the whole matrix as a vector, use d with gcd(d,s)=1, and convert cell numbers to subscripts as above.
If you just want to iterate through the matrix, what is wrong with row++; if (row == N) {row = 0; column++}?
If you iterate through the row and the column independently, and each cycles back to the beginning after N steps, then the (row, column) pair will interate through only N of the N^2 cells of the matrix.
If you want to iterate through all of the cells of the matrix in pseudo-random order, you could look at questions here on random permutations.
This is a companion answer to address a question about my previous answer: How to find an appropriate prime p >= s (where s = the number of matrix elements) to use in the hash function H(i) = (i*i*i) mod p.
We need to find a prime of form 3n+2, where n is any odd integer such that 3*n+2 >= s. Note that n odd gives 3n+2 = 3(2k+1)+2 = 6k+5 where k need not be odd. In the example code below, p = 5+6*(s/6); initializes p to be a number of form 6k+5, and p += 6; maintains p in this form.
The code below shows that half-a-dozen lines of code are enough for the calculation. Timings are shown after the code, which is reasonably fast: 12 us at s=half a million, 200 us at s=half a billion, where us denotes microseconds.
// timing how long to find primes of form 2+3*n by division
// jiw 20 Sep 2011
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
double ttime(double base) {
struct timeval tod;
gettimeofday(&tod, NULL);
return tod.tv_sec + tod.tv_usec/1e6 - base;
}
int main(int argc, char *argv[]) {
int d, s, p, par=0;
double t0=ttime(0);
++par; s=5000; if (argc > par) s = atoi(argv[par]);
p = 5+6*(s/6);
while (1) {
for (d=3; d*d<p; d+=2)
if (p%d==0) break;
if (d*d >= p) break;
p += 6;
}
printf ("p = %d after %.6f seconds\n", p, ttime(t0));
return 0;
}
Timing results on 2.5GHz Athlon 5200+:
qili ~/px > for i in 0 00 000 0000 00000 000000; do ./divide-timing 500$i; done
p = 5003 after 0.000008 seconds
p = 50021 after 0.000010 seconds
p = 500009 after 0.000012 seconds
p = 5000081 after 0.000031 seconds
p = 50000021 after 0.000072 seconds
p = 500000003 after 0.000200 seconds
qili ~/px > factor 5003 50021 500009 5000081 50000021 500000003
5003: 5003
50021: 50021
500009: 500009
5000081: 5000081
50000021: 50000021
500000003: 500000003
Update 1 Of course, timing is not determinate (ie, can vary substantially depending on the value of s, other processes on machine, etc); for example:
qili ~/px > time for i in 000 004 010 058 070 094 100 118 184; do ./divide-timing 500000$i; done
p = 500000003 after 0.000201 seconds
p = 500000009 after 0.000201 seconds
p = 500000057 after 0.000235 seconds
p = 500000069 after 0.000394 seconds
p = 500000093 after 0.000200 seconds
p = 500000099 after 0.000201 seconds
p = 500000117 after 0.000201 seconds
p = 500000183 after 0.000211 seconds
p = 500000201 after 0.000223 seconds
real 0m0.011s
user 0m0.002s
sys 0m0.004s
Consider using a double hash function to get a better distribution inside the matrix,
but given that you cannot avoid colisions, what I suggest is to use an array of sentinels
and mark the positions you visit, this way you are sure you get to visit a cell once.