Watching this video (11:56)
It shows a recursive procedure that multiplies the numbers contained in a list
The idea is that if the list contains a zero, the whole stack of recursive calls can be discarded and 0 can be returned
So to save some multiplications
It does so by early exiting the procedure with delimited continuations
I'd like to reproduce this in Guile Scheme and I wrote this code
(define (times numbers)
(define (times-iter numbers)
(match numbers
((a-number rest ...)
(* a-number (times rest)))
('() 1)
((0 rest ...) (shift k 0) )
))
(reset (times-iter numbers))
)
it multiplies correctly but if I pass it a list containing a zero and I trace such call, I get
scheme#(guile-user)> ,trace (times2 '(1 3 0 4))
trace: | (times2 (1 3 0 4))
trace: | | (default-prompt-tag##ice-9/control)
trace: | | (_)
trace: | | ("prompt")
trace: | | (_)
trace: | | | (list? (3 0 4))
trace: | | | #t
trace: | | | (times (3 0 4))
trace: | | | | (list? (0 4))
trace: | | | | #t
trace: | | | | (times (0 4))
trace: | | | | | (list? (4))
trace: | | | | | #t
trace: | | | | | (times (4))
trace: | | | | | | (list? ())
trace: | | | | | | #t
trace: | | | | | | (times ())
trace: | | | | | | 1
trace: | | | | | 4
trace: | | | | 0
trace: | | | 0
trace: | | 0
trace: | (_ #<procedure values _> (0))
trace: | (_ 0)
trace: | 0
scheme#(guile-user)>
It seems to me that the early exit doesn't kick in and the whole stack of multiplications gets applied
What am I doing wrong ?
Based on the comments, it's unclear if you still have a question here. (shift k 0) does indeed clear the current continuation and discards it.
I don't have Guile on this machine but I wrote a simplified times example below with racket using cond -
(require racket/control)
(define/traced (times numbers)
(cond ((null? numbers) 1)
((zero? (car numbers)) (shift k 0)) ;; <- shift
(else (* (car numbers) (times (cdr numbers))))))
#ignisvolens provides define/traced in this Q&A. reset wraps the expression but you could move it to an inner auxiliary function like you did in your code -
(reset ;; <- reset
(times '(1 2 3 4 5 6 7 8 9)))
(times (1 2 3 4 5 6 7 8 9)) ...
(times (2 3 4 5 6 7 8 9)) ...
(times (3 4 5 6 7 8 9)) ...
(times (4 5 6 7 8 9)) ...
(times (5 6 7 8 9)) ...
(times (6 7 8 9)) ...
(times (7 8 9)) ...
(times (8 9)) ...
(times (9)) ...
(times ()) ...
-> (1)
-> (9)
-> (72)
-> (504)
-> (3024)
-> (15120)
-> (60480)
-> (181440)
-> (362880)
-> (362880)
362880
We can see the immediate exit when the 0 is encountered -
(reset (times '(1 2 0 4 5 6 7 8 9)))
(times (1 2 0 4 5 6 7 8 9)) ...
(times (2 0 4 5 6 7 8 9)) ...
(times (0 4 5 6 7 8 9)) ...
0
Notice in the first example, define/traced shows -> ... when times returns a value. In the second example, the entire continuation is discarded and times never fully evaluates.
Related
Suppose I have two matrices MatrixA and MatrixB given as follows (where i is the row number and j is the column number:
MatrixA | MatrixB
i | j | val | i | j | val
---|---|---- | ---|---|----
1 | 1 | 3 | 1 | 1 | 2
1 | 2 | 5 | 1 | 2 | 3
1 | 3 | 9 | 2 | 1 | 7
2 | 1 | 2 | 2 | 2 | -1
2 | 2 | 1 | 3 | 1 | 0
2 | 3 | 3 | 3 | 2 | -4
3 | 1 | 3 |
3 | 2 | -1 |
3 | 3 | 2 |
4 | 1 | 0 |
4 | 2 | 7 |
4 | 3 | 6 |
In a more familiar form, they look like this:
MatrixA = 3 5 9 MatrixB = 2 3
2 1 3 7 -1
-1 2 0 0 -4
7 0 6
I'd like to calculate their product (which is demonstrated in this YouTube video):
Product = 41 -32
11 -7
12 -5
14 -3
In the unpivoted column form I used earlier, this is
i | j | val
---|---|----
1 | 1 | 41
1 | 2 | -32
2 | 1 | 11
2 | 2 | -7
3 | 1 | 12
3 | 2 | -5
4 | 1 | 12
4 | 2 | -3
I'm looking for a general calculation that multiplies any compatible k x n and n x m matrices together as a calculated table.
I think I've got it figured out. If MatrixA is k x n and MatrixB is n x m dimensional:
Product =
ADDCOLUMNS(
CROSSJOIN(VALUES(MatrixA[i]), VALUES(MatrixB[j])),
"val",
SUMX(
ADDCOLUMNS(
SELECTCOLUMNS(GENERATESERIES(1, DISTINCTCOUNT(MatrixA[j])), "Index", [Value]),
"A", LOOKUPVALUE(MatrixA[val], MatrixA[i], [i], MatrixA[j], [Index]),
"B", LOOKUPVALUE(MatrixB[val], MatrixB[i], [Index], MatrixB[j], [j])),
[A] * [B]))
The CROSSJOIN creates a new table with columns [i] and [j] which has k x m rows. For each i and j row pair in this cross join table, the value for that cell is computed as the sum product of i row of MatrixA with j column of MatrixB. The GENERATESERIES bit just creates an Index list that has a length of the matching dimension n.
For example, when i = 3 and j = 2, the middle section for the given example is
ADDCOLUMNS(
SELECTCOLUMNS(GENERATESERIES(1, DISTINCTCOUNT(MatrixA[j])), "Index", [Value]),
"A", LOOKUPVALUE(MatrixA[val], MatrixA[i], 3, MatrixA[j], [Index]),
"B", LOOKUPVALUE(MatrixB[val], MatrixB[i], [Index], MatrixB[j], 2))
which generates the table
Index | A | B
------|-----|----
1 | -1 | 3
2 | 2 | -1
3 | 0 | -4
where the [A] column is the 3rd row of MatrixA and the [B] column is the 2nd row of MatrixB.
I am trying to repeat a row value in the subsequent rows with in GROUP. A Group can have one or more TAG. The requirement is to populate NEW_TAG in the row where the TAG is populated and in the subsequent rows until another TAG populated with in the same group or we reach end of that GROUP.
Current Table Required Table
GROUPID SEQ TAG GROUPID SEQ TAG NEW_TAG
------- --- ---- ------- --- --- --------
1 1 1 1
1 2 1 2
1 3 1 3
1 4 4 1 4 4 4
1 5 1 5 4
1 6 1 6 4
1 7 1 7 4
1 8 1 8 4
2 1 2 1
2 2 2 2
2 3 2 3
2 4 2 4
2 5 5 2 5 5 5
2 6 2 6 5
2 7 2 7 5
2 8 2 8 5
2 9 9 2 9 9 9
2 10 2 10 9
2 11 2 11 9
Thanks
Assuming TAG is always increasing
max(TAG) over
(
partition by GROUPID
order by SEQ
rows between unbounded preceding
and current row
) as NEW_TAG
select *
,max(TAG) over
(
partition by GROUPID
order by SEQ
rows between unbounded preceding
and current row
) as NEW_TAG
from mytable
;
+---------+--------+--------+---------+
| groupid | seq | tag | new_tag |
+---------+--------+--------+---------+
| 1 | 1 | | |
| 1 | 2 | | |
| 1 | 3 | | |
| 1 | 4 | 4 | 4 |
| 1 | 5 | | 4 |
| 1 | 6 | | 4 |
| 1 | 7 | | 4 |
| 1 | 8 | | 4 |
| 2 | 1 | | |
| 2 | 2 | | |
| 2 | 3 | | |
| 2 | 4 | | |
| 2 | 5 | 5 | 5 |
| 2 | 6 | | 5 |
| 2 | 7 | | 5 |
| 2 | 8 | | 5 |
| 2 | 9 | 9 | 9 |
| 2 | 10 | | 9 |
| 2 | 11 | | 9 |
+---------+--------+--------+---------+
I want to find maximum of a group of rows in a certain column which satisfies a condition in TIBCO Spotfire. For example, consider the table below:
col 1|col 2|col 3
1 | 2 | y
1 | 3 | y
1 | 6 | y
1 | 8 | n
1 | 7 | n
1 | 6 | y
2 | 2 | y
2 | 10 | y
2 | 6 | y
2 | 9 | n
2 | 7 | y
2 | 6 | n
I want to group all the rows with [col 1] = 1, and find the max of col 2 considering only those rows that have [col 3] = "y".
My final table must look like:
col 1|col 2|col 3|col 4
1 | 2 | y | 6
1 | 3 | y | 6
1 | 6 | y | 6
1 | 8 | n | 6
1 | 7 | n | 6
1 | 6 | y | 6
2 | 2 | y | 10
2 | 10 | y | 10
2 | 6 | y | 10
2 | 9 | n | 10
2 | 7 | y | 10
2 | 6 | n | 10
Can some one please help me out with this?
First(case when [col 3]="y" then Max([col 2]) OVER ([col 1]) end) OVER ([col 1]) should do the trick (version 7.5).
Thanks!
I came up with something that sounds like what you already tried, but here goes.
Insert Calculated Column: CASE WHEN [col 3]="y" THEN Max([col 2]) OVER ([col 1]) END AS [calc]
Insert Calculated Column: Max([calc]) OVER ([col 1]) AS [col 4]
Those give me the value in [col 4] that you were looking for.
#monte_fisto in the similar case can we identify the min and max of a col2
Let's say I define a matrix:
matrix a = (2,3 \ 4,7 \ 6,13)
I can access "13" like this:
display a[3,2]
Is it also possible to access "13" while referring to "6" to specify the row? In other words, we would somehow signify that the row is the row (there could be more than one) that contains a 6 in the first column and then we want the second column of this row.
In R, we might do it like this:
a1 <- data.frame(c(2,4,6), c(3,7,13))
a1[a1[,1]==6, 2]
Is there anything analogous in Stata?
You could do this with Stata's matrix language, with some programming, but I would turn to Mata whose defined functions allow direct solutions similar in spirit to R. Consider this dialogue.
. mata
------------------------------------------------- mata (type end to exit) --------------
: a = (2,3 \ 4,7 \ 6,13)
: a :== 1
1 2
+---------+
1 | 0 0 |
2 | 0 0 |
3 | 0 0 |
+---------+
: a :== 6
1 2
+---------+
1 | 0 0 |
2 | 0 0 |
3 | 1 0 |
+---------+
: rowsum(a :== 6)
1
+-----+
1 | 0 |
2 | 0 |
3 | 1 |
+-----+
: select(a, rowsum(a :== 6))
1 2
+-----------+
1 | 6 13 |
+-----------+
: a2 = select(a, rowsum(a :== 6))
: a2[, 2]
13
: b = (6,6 \ 6,6 \ 6,6)
: select(b, rowsum(b :== 6))
1 2
+---------+
1 | 6 6 |
2 | 6 6 |
3 | 6 6 |
+---------+
: b2 = select(b, rowsum(b :== 6))
: b2[, 2]
1
+-----+
1 | 6 |
2 | 6 |
3 | 6 |
+-----+
"row contains a 6" is defined by the total of "element is equal to 6" across rows. Note that the code works if (a) there is more than one 6 on a row and/or (b) there is more than one row with a 6. In the last case, what is selected contains more than one element.
The notation should seem self-explanatory, except possibly that : as a prefix signals "elementwise" operations. To copy a Stata matrix into Mata, use st_matrix().
Note: Working out what the code should be to select in the first column only is set as an exercise for the zealous.
For caches of small size, a direct-mapped instruction cache can sometimes outperform a fully associative instruction cache using LRU replacement.
Could anyone explain how this would be possible with an example access pattern?
This can happen for caches of small size. Let's compare caches of size 2.
In my example, the directly-mapped "DM" cache will use row A for odd addresses, and row B for even addresses.
The LRU cache will use the least recently used row to store values on a miss.
The access pattern I suggest is 13243142 (repeated as many times as one wants).
Here's a breakdown of how botch caching algorithms will behave:
H - hits
M - misses
----- time ------>>>>>
Accessed: 1 | 3 | 2 | 4 | 3 | 1 | 4 | 2
\ \ \ \ \ \ \ \
LRU A ? | ? | 3 | 3 | 4 | 4 | 1 | 1 | 2 |
B ? | 1 | 1 | 2 | 2 | 3 | 3 | 4 | 4 |
M M M M M M M M
DM A ? | 1 | 3 | 3 | 3 | 3 | 1 | 1 | 1 |
B ? | ? | ? | 2 | 4 | 4 | 4 | 4 | 2 |
M M M M H M H M
That gives 8 misses for the LRU, and 6 for directly-mapped. Let's see what happens if this pattern gets repeated forever:
----- time ------>>>>>
Accessed: 1 | 3 | 2 | 4 | 3 | 1 | 4 | 2
\ \ \ \ \ \ \ \
LRU A | 2 | 3 | 3 | 4 | 4 | 1 | 1 | 2 |
B | 1 | 1 | 2 | 2 | 3 | 3 | 4 | 4 |
M M M M M M M M
DM A | 1 | 3 | 3 | 3 | 3 | 1 | 1 | 1 |
B | 2 | 2 | 2 | 4 | 4 | 4 | 4 | 2 |
H M H M H M H M
So the directly-mapped cache will have 50% of hits, which outperforms 0% hits of LRU.
This works this way because:
Any address repeated in this pattern has not been accessed for previous 2 accesses (and both these were different), so LRU cache will always miss.
The DM cache will sometimes miss, as the pattern is designed so that it utilizes what has been stored the last time the corresponding row was used.
Therefore once can build similar patterns for larger cache sizes, but the larger the cache size, the longer such pattern would need to be. This corresponds to the intuition that for larger caches it would be harder to exploit them this way.