Skip to content

Instantly share code, notes, and snippets.

@decatur
Last active August 18, 2017 13:25
Show Gist options
  • Save decatur/cdd2099bd7eb6cefbf3db259f3fbc34e to your computer and use it in GitHub Desktop.
Save decatur/cdd2099bd7eb6cefbf3db259f3fbc34e to your computer and use it in GitHub Desktop.
Run-Length-Encode/Decode Parameters in GAMS (General Algebraic Modeling System)
$include rle.gms
Set T / 1*5 /;
* Test series without additional domain.
Parameter a(T), a_rle(T) / 1 1, 3 EPS, 5 2 /
a_expected(T) / 1 1, 2 1, 5 2 /;
a(T) = a_rle(T);
rle_decode_1(a, T);
display a, a_expected;
rle_encode_1(a, T);
display a, a_rle;
Parameter b(T), b_rle(T) / 1 EPS, 5 2 /,
b_expected(T) / 5 2 /;
b(T) = b_rle(T);
rle_decode_1(b, T);
display b, b_expected;
rle_encode_1(b, T)
display b, b_rle;
* Test series on a card=4 domain.
Set S / a*d /;
Parameter c(T, S);
Table c_rle(T, S)
a b c d
1 1 3 1 EPS
2 EPS
3 4
4
5 2 ;
Table c_expected(T, S)
a b c d
1 1 3 1
2 3 1
3 4 1
4 4 1
5 2 4 1 ;
c(T,S) = c_rle(T,S);
rle_decode_2(c, T, S);
display c, c_expected;
rle_encode_2(c, T, S);
display c, c_rle;
* Now we do some crazy GAMS stuff to clarify.
Scalar vv / NA /;
vv = (EPS=EPS);
display "EPS compares to EPS", vv;
vv = (0=EPS);
display "EPS compares to 0", vv;
vv = (not EPS);
display "not EPS is 0", vv;
vv = (1 and EPS);
display "1 and EPS is true", vv;
vv = NA;
vv = 1$EPS;
display "EPS is true", vv;
vv = (NA=NA);
display "NA compares to NA ", vv;
* Demo that GAMS is a sparse system
Set Q / a1*a1000000 /;
Parameter p(Q);
* Following line does not do anything.
p(Q) = 0;
* p(Q) = EPS would be devastating;
p('a1') = EPS;
p('a1000') = 100000;
* Only saves two entries
Execute_Unload 'foobar.gdx', p;
Parameter x(T) / 1 1 /;
x(T+1) = x(T)
display x;
$ontext
RunLengthEncoding (RLE) Series:
A Series where only changes in value are recorded.
Example A
index = 1 2 3 4 5 6
value = 6 6 0 0 7 7
as RLE series is
index = 1 3 5
value = 6 0 7
Example B from demo_rle
RLE-Encoded
a b c d
1 1 3 1 EPS
2 EPS
3 4
4
5 2 ;
RLE-Decoded
a b c d
1 1 3 1
2 3 1
3 4 1
4 4 1
5 2 4 1 ;
Important: Since GAMS is a sparse system where 0 values simply are not recorded,
we use EPS as explained below.
Notes:
1. Macros may not contain other Dollar Control Options such as $load.
2. The statement p(t) = p(t-1) is skipped for ord(t) = 1.
3. EPS is the marker for the zero value. In Python EPS is gams.SV_EPS
4. EPS and 0 compare to each other, i.e. EPS=1. However, (not EPS) is 0, whereas (not 0) is 1.
So DO NOT use p(t)=0, use not p(t)
From the GAMS documentation:
Special attention needs to be given to the value of 0.
Since GAMS is a sparse system it does not store (parameter) records with a true 0.
If a record with numerical value of 0 is needed, EPS(SV_EPS) can help.
Macros rle_decode_x(parameter, time_set, other_domain, ...):
Roll out a DiffSparse series
$offtext
* if p(t) is missing then set to p(t-1), else keep value by setting EPS to 0:
* if ( not p(t), p(t)=p(t-1); else if ( p(t)=EPS, p(t)=0 ) )
* Note that the term
* if ( p(t)=EPS, p(t)=0 )
* can be written as
* p(t) = p(t)$(not(p(t)=0)).
* So we could write
* p(t) = ifthen( not p(t), p(t-1), p(t)$(not(p(t)=0)) )
* or
* p(t) = p(t-1)$(not p(t)) + p(t)$not(p(t)=0)
* In the first round ( ord(t)=1 ) this happens:
* If p(t) is 0, then we jump to the true-expressen, where nothing happens because
* t-1 is skipped.
* If p(t) is not zero, then we jump to the false-expression, and p(t) is set to 0
* if equal to EPS.
$macro rle_decode_1(p, t) \
Loop(t, \
if ( not p(t), p(t)=p(t-1); else if ( p(t)=EPS, p(t)=0 ) ) \
)
$macro rle_decode_2(p, t, d) \
Loop((t, d), \
if ( not p(t,d), p(t,d) = p(t-1,d); else if ( p(t,d)=EPS, p(t,d)=0 ) ); \
)
$ontext
Macros rollin_x(parameter, time_set, other_domain, ...):
Inverse of rollout_x
$offtext
Scalar prev_val_ / NA /;
Scalar val_ / NA /;
$macro rle_encode_1(p, t) \
Loop(t, \
val_ = round(p(t), 4); \
if ( ord(t) > 1 and val_=prev_val_, p(t) = 0; else prev_val_=val_; p(t)=ifthen(val_=0, EPS, val_) ); \
)
$macro rle_encode_2(p, t, d) \
Loop((d,t), \
val_ = round(p(t,d), 4); \
if ( ord(t) > 1 and val_=prev_val_, p(t,d) = 0; else prev_val_=val_; p(t,d)=ifthen(val_=0, EPS, val_) ); \
)
$macro rle_encode_3(p, t, d1, d2) \
Loop((d1,d2,t), \
val_ = round(p(t,d1,d2), 4); \
if ( ord(t)>1 and val_=prev_val_, p(t,d1,d2) = 0; else prev_val_=val_; p(t,d1,d2)=ifthen(val_=0, EPS, val_) ); \
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment