全球FlexSim系统仿真中文论坛

标题: 【脑洞大开】如何快速获取暂存区各类型临时实体数量 [打印本页]

作者: zorsite    时间: 2016-4-19 12:19
标题: 【脑洞大开】如何快速获取暂存区各类型临时实体数量
在某一时点(时点自己决定)想要获取暂存区中临时实体有多少种类型,以及每种类型的临时实体有多少个。
6 g/ o% V0 L' H- b7 [' }% O如何编写代码最简洁、占用系统资源最少、逻辑最清晰?
9 R0 o6 r9 c( |8 @* g- i/ ?请回复的时候附上主要代码。" O& ?! v6 J4 ]
附件基于Flexsim7.7.4。
  h( Y- U9 P7 A+ m' K
# q: G% j' }. ?$ Q2 A. W$ }1 `[attach]3067[/attach]
作者: 慧娴亚伦    时间: 2016-4-19 14:21
响应加老师号召,完成模型。: @6 }. S2 x5 }- T/ f
不过我一向不是极简主义者,因此可能提供的模型与“最简洁,所占资源最少”无缘。4 _' ~* M  S# m0 N5 }2 f8 s
我的思路主要集中在,用一个全局表来显示,为了使得能够获取不同类型的变动情况,还特别添加一个dashboard来表示。# l1 S2 N0 G/ A* _9 |# J
主要代码在暂存区的进入触发,重置触发里面只是在重置中修正了一下全局表的大小。
  1. int type = getitemtype(item);
    9 X2 W5 M+ x, r1 J) y9 X1 ]
  2. / k0 v6 |' y8 P: r2 R2 A0 d
  3. //如果已存在该类型,则对应单元格加11 \" Y7 W2 e0 D
  4. for(int i=1;i<=gettablerows("GlobalTable1");i++)
    9 e: C9 A% I. y$ o# Q. b
  5. {
    ; |) m4 Z+ s! ?- S( N
  6.         if(gettablenum("GlobalTable1",1,2) == 0)
    4 O2 u9 q7 w4 v- m# j4 R
  7.         {; ~( J  g) Z  f' l' I% e4 C- X
  8.                 settablenum("GlobalTable1",1,2,type);
    : q! {6 p/ ~  B
  9.                 settablenum("GlobalTable1",1,1,1);
    % A( P  B* v4 x7 W9 j
  10.                 settableheader("GlobalTable1",1,1,concat("type",numtostring(type)));
    + C/ c3 {$ d) x, |) K
  11.                 return 0;! ?( j5 ~* g! ^. Q& X
  12.         }) C3 V0 ^2 c9 K) F' D
  13.                                
    ; A- V8 E7 O: P' }: z
  14.         if(type == gettablenum("GlobalTable1",i,2))" `: q' d) b2 k8 j' |
  15.         {
    7 u7 C# S. L/ m: y
  16.                 inc(gettablecell("GlobalTable1", i, 1),1);' |* a3 D2 N" Z  s3 Z' l9 N
  17.                 return 0;, b7 E* Z" R$ _& \! z
  18.         }
    9 l2 j2 G# @5 j( a0 a6 q6 ]6 l
  19. }' y9 P7 T+ M+ H& ~' S0 H; [
  20. 5 |; ]! l  {+ m/ V# I
  21. 5 O' N2 C' i; ?) F0 s
  22. //如果是一个新的类型则多添加一行
    * H. j! x, a6 p% j: o0 D3 S1 ~
  23. addtablerow(reftable("GlobalTable1"),1,DATATYPE_NUMBER);
    ' U- ^0 ?) v9 D* Q
  24. settableheader("GlobalTable1",1,1,concat("type",numtostring(type)));
    % l, S7 Z6 U- b, L% m' X5 q
  25. settablenum("GlobalTable1",1,2,type);
    % p4 D3 `! ]( Q, ?; X! q8 p
  26. settablenum("GlobalTable1",1,1,1);
    ; O3 Y8 m. t  M
复制代码

作者: zorsite    时间: 2016-4-19 17:13
本帖最后由 zorsite 于 2016-4-20 16:18 编辑
0 P6 }7 A4 O3 G9 S; R7 F, ~
8 Y) G2 d( K- R% q6 k- x" q谢谢陈老师捧场~~1 P1 t4 Z# {0 S: o8 o+ j, A& w, S  h
我的代码写在模型的停止运行中。谢谢FFFrenk的提醒,临时实体的类型并不总是整数,所以以下代码在使用上有局限性。
  1. treenode queue=node("Queue3", model());: A1 A/ O/ V9 h7 W

  2. ( A) r6 [! y" w, a
  3. settablesize("统计结果",0,0);//清空全局表% C9 f5 c* A, y9 E
  4. //先把数据写入数组
    ; B% ~* d* e5 I
  5. int cont=content(queue);//获取暂存区中临时实体总数# N* L1 V5 |" @# N1 ]& P- Z
  6. intarray array=makearray(cont);//创建一个数组. M% R, M  [) \
  7. for (int i=1;i<=cont;i++)
    # e- u1 Q/ n! b! F0 g, s4 _
  8. {" Y, B" ^4 W  X" d" k
  9.         int type=getitemtype(rank(queue,i));
    - ~3 \- k( @" I  I( s
  10.         array[type]+=1;//计算每种临时实体的数量, Q! ?5 t: w3 N
  11. }
    5 ]* s8 U, J. x" ?
  12. //再把数据写入全局表
    * w: p% E( W4 {% `
  13. int row=1;' a, ?& ]& A/ e- ?
  14. for (int i=1;i<=cont;i++)
    ) v. j3 D' t& q; ]6 Y) }
  15. {        if (array)//如果某种临时实体的数量不为零
    : o# X5 U+ N! Z  ], A8 G3 R  r' O
  16.         {
    1 I% @# v5 v2 q6 x9 U6 t* S
  17.                 settablesize("统计结果",gettablerows("统计结果")+1,2);//新增一行3 f5 T4 m# r) {1 p* }8 X
  18.                 settablenum("统计结果",row,1,i);//记录其类型
      L6 R4 `4 Q7 [  x! u" Y, P7 A
  19.                 settablenum("统计结果",row,2,array);        //记录其数量
    . s$ b/ K, I+ i4 V% A
  20.                 row+=1;
    # k( h2 a( I& w
  21.         }        % B( C) w8 R2 a* e8 a1 S
  22. }
    . A& @& [4 @1 f1 }+ @( |" q2 n' A
  23. settableheader("统计结果",2,1,"类型");4 X; L# L) \- X# W5 Z+ c( I
  24. settableheader("统计结果",2,2,"数量");
复制代码

作者: FFFrenk    时间: 2016-4-19 20:25
谢谢陈老师捧场~~+ w! e" o: t) ], H! N; D
我的代码写在模型的停止运行中。treenode queue=node("Queue3", model());7 p1 J2 L, _! v6 r- x

: L( c* M5 c; @9 Q4 |4 z1 xsettablesize("统计结果",0,0);//清空全局表1 o6 ~2 _" C& w" ]1 `: `$ p9 c
//可以没有直接增加全局表的命令……
1 J8 r$ t( q- k# N' J9 J//先把数据写入数组9 Q* l! [% V. @: \3 H. ^) E$ p
...
! H" P% ^% V) X- Ezorsite 发表于 2016-4-19 17:13
+ w' ~6 D$ R$ V1 n/ {1 `) k

0 K7 z+ }1 H6 o+ r看了一下加老师代码,有个小问题....- _) W# q: q6 k& `
itemtype有可能是多精度型(包括小数、负数)的,并不都是正整数....
作者: FFFrenk    时间: 2016-4-19 21:42
思路是:将 type 转换成 str 作为某个东西的引用,这样就省去了一轮的 Loop ;) _0 V4 {3 Z: ^' ^2 B
具体来说,是用 bundle 中 getbundlefieldnr 可以传递引用参数来实现。$ w7 y% ?2 x9 E6 o$ S
恰好,7.7版本开始, FlexSim 可以使用 bundle 存储表格数据,不仅带来了更加轻便的数据处理,也带来了很多新的特性。(赶快升级呀!)3 l& V) ]  h& L) W) y" n

! J, ]1 S; ]& {" z) X# @8 \8 h以下是实例:- `3 s- V/ B4 R4 z5 C
创建一个名为"GlobalTable1"的全局表,并改成 Use Bundle。
4 n  s2 B9 @6 _& C9 i
2 [0 w; K4 o" P( L之后就是在需要统计的时间点或者事件处,运行如下代码:

  1. 4 T5 _$ L' r3 t
  2. treenode queue=node("Queue3", model());( I- ^, Z. Z: ^# C  Z" z; [

  3. $ ~; e5 I& n* [
  4. treenode targetTable=reftable("GlobalTable1");3 Y* X; L. t1 r# x
  5. settablesize(targetTable,1,1);+ ^  ^5 ?: L5 r2 @) f
  6. forobjecttreeunder(queue)5 f  H3 r# t9 p0 G
  7. {5 _: ]% ^% C* ^! g
  8.         string typeStr=numtostring(getitemtype(a),0,5);* X7 _+ O7 ], B( C
  9.         int col=getbundlefieldnr(targetTable, typeStr)+1;
    & \1 w6 a& e  X0 t
  10.         if (col)
    + j) j4 @9 O' C5 Q) O% M: R* q
  11.         {
    & v9 Q  U* f1 ^, D3 C
  12.                 settablenum(targetTable,1,col,gettablenum(targetTable,1,col)+1);
    8 G- K8 M8 Y1 E3 ]  b+ k
  13.         }( ?9 m; }, p, K  m
  14.         else6 {7 Y, U$ f) n/ c6 b; H2 J
  15.         {0 h. n4 f- [% F1 w! q
  16.                 addtablecol(targetTable);" J" Q2 ]$ M9 t# v  M6 Q
  17.                 int nrCols=gettablecols(targetTable);+ N- d* C1 R. _( T" m# ?' @: f8 Z
  18.                 settableheader(targetTable,2,nrCols,typeStr);
    / X8 F- G$ [( ~' s: o% Y9 Q
  19.                 settablenum(targetTable,1,nrCols,1);/ `+ \# K5 U& H! E7 H1 u$ J) R, d
  20.         }
    6 w' y. C1 o1 _  F. O: J5 p
  21. }
    : O, }( A& D6 q; A  o' n
复制代码
ps:有个小缺陷,全局表第一行第一列的内容无法加入统计。
作者: zorsite    时间: 2016-4-20 16:10
flexsim的数组功能很弱,我一直想要找一种更为灵活的工具来实现这一目的。8 e$ d) U6 O% ]; a+ _. u5 w
FFFrenk给了我新的思路,用bundle data。; Y% c  {6 ?7 |+ G; M
相比数组,bundle更灵活,但是不能放在内存中(我不知道如何放入),只能保存在全局表中。) a1 l) Z6 N" m
一下是我的代码:3 `) B! \: `( D3 p* H9 T3 ^, f
  1. treenode queue=node("Queue3", model());4 h5 U; ^$ a+ l& |
  2. treenode bundle=reftable("bundle");
    * X' P5 s9 R. f' |% K  H' Q  @6 S' m9 Z
  3. //创建两张全局表:bundle和统计结果。bundle全局表要勾选上Use Bundle。: a3 ^& a8 U0 y/ v6 }. `4 X
  4. clearbundle(bundle);//清除所有数据
    3 j- t; K2 m) h
  5. addbundlefield(bundle,"type",1);1 P: q9 z9 y% [- d) s0 ?
  6. addbundlefield(bundle,"qnt",1);//新增字段: t; B$ u6 M0 \5 r3 m2 s  V
  7. forobjecttreeunder(queue)
    & F! k, P* ?4 y9 ^6 g5 g. m8 b
  8. addbundleentry(bundle,getitemtype(a),1);//把每一个临时实体的类型写入bundle表& D1 j! k! i4 A2 D& Y( I$ u
  9. query("select type, sum(qnt) as quantity from $1 group by type order by type",bundle);//按类型分组统计数量" V3 P, ]2 C  A/ f. A7 j9 y
  10. //如果全局表勾选了Use Bundle,只能使用$来传递表名,不能使用 query("select * form bundle");
    3 C  M/ T$ A  q5 a" Q
  11. //使用as语句指定别名时,别名不能和原来的名字相同:不能使用 sum(quantity) as quantity
    2 t4 _$ n) J; J. H& ]
  12. dumpquery(reftable("统计结果"));//输出到统计结果表
复制代码

作者: xiaoling1569    时间: 2016-4-25 20:03
2# 慧娴亚伦
作者: xiaoling1569    时间: 2016-4-25 20:03
2# 慧娴亚伦
- L7 ^- Q: R# E非常感谢。
作者: FFFrenk    时间: 2016-5-29 17:41
看到加老师使用了 SQL这种「作弊」的手段,我也小试牛刀,代码如下:

  1. 7 w, }* Q/ R( s- c6 k
  2. treenode Queue=node("Queue3", model());//the queue
    7 g+ H% Y7 M4 x0 a, s, V
  3. query("select $2 as Type , count(*) as TypeNum from $1 group by Type",
    % P# z4 @5 q; V: h; _  s
  4.         /*$1*/Queue,
    : O  g$ Z1 ^$ T# K( a; a7 E7 s6 c
  5.         /*$2*/getitemtype($iter(1)));+ o, H% |# n2 Z
  6. dumpquery(reftable("ResultTable"), 1);
    4 q! j4 G0 R6 C& ^( g
复制代码

作者: lulu-luka    时间: 2016-12-1 09:59
1# zorsite
# v# o; d0 C1 h7 C. k* j都是大神级别的老师啊~我想实现一个实时的物料拉动,暂存区的实体数量一旦达到某个设定值就会触发发生器批量生产输出,如何用代码实现啊,求助求助
作者: susan    时间: 2016-12-1 13:00
10# lulu-luka - c) D/ t7 h* v  v+ }

9 X- s& V/ p. B# f  |  \) n  g% q% D7 \/ h; t$ P& J! s- r% a
您好,该问题已在其他版块回复。




欢迎光临 全球FlexSim系统仿真中文论坛 (http://www.flexsimasia.com/) Powered by Discuz! X3.3