-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy patht.py
4557 lines (4494 loc) · 214 KB
/
t.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/usr/bin/env python3.
import random
import gym
import gym.spaces
from collections import namedtuple
import numpy as np
from tensorboardX import SummaryWriter
import torch
import torch.nn as nn
import torch.optim as optim
HIDDEN_SIZE = 128
BATCH_SIZE = 100
PERCENTILE = 30
GAMMA = 0.9
class DiscreteOneHotWrapper(gym.ObservationWrapper):
def __init__(self, env):
super(DiscreteOneHotWrapper, self).__init__(env)
assert isinstance(env.observation_space, gym.spaces.Discrete)
self.observation_space = gym.spaces.Box(0.0, 1.0, (env.observation_space.n, ), dtype=np.float32)
def observation(self, observation):
res = np.copy(self.observation_space.low)
res[observation] = 1.0
return res
class Net(nn.Module):
def __init__(self, obs_size, hidden_size, n_actions):
super(Net, self).__init__()
self.net = nn.Sequential(
nn.Linear(obs_size, hidden_size),
nn.ReLU(),
nn.Linear(hidden_size, n_actions)
)
def forward(self, x):
return self.net(x)
Episode = namedtuple('Episode', field_names=['reward', 'steps'])
EpisodeStep = namedtuple('EpisodeStep', field_names=['observation', 'action'])
def iterate_batches(env, net, batch_size):
batch = []
episode_reward = 0.0
episode_steps = []
obs = env.reset()
sm = nn.Softmax(dim=1)
while True:
obs_v = torch.FloatTensor([obs])
act_probs_v = sm(net(obs_v))
act_probs = act_probs_v.data.numpy()[0]
action = np.random.choice(len(act_probs), p=act_probs)
next_obs, reward, is_done, _ = env.step(action)
episode_reward += reward
episode_steps.append(EpisodeStep(observation=obs, action=action))
if is_done:
batch.append(Episode(reward=episode_reward, steps=episode_steps))
episode_reward = 0.0
episode_steps = []
next_obs = env.reset()
if len(batch) == batch_size:
yield batch
batch = []
obs = next_obs
def filter_batch(batch, percentile):
disc_rewards = list(map(lambda s: s.reward * (GAMMA ** len(s.steps)), batch))
reward_bound = np.percentile(disc_rewards, percentile)
train_obs = []
train_act = []
elite_batch = []
for example, discounted_reward in zip(batch, disc_rewards):
if discounted_reward > reward_bound:
train_obs.extend(map(lambda step: step.observation, example.steps))
train_act.extend(map(lambda step: step.action, example.steps))
elite_batch.append(example)
return elite_batch, train_obs, train_act, reward_bound
if __name__ == "__main__":
random.seed(12345)
env = DiscreteOneHotWrapper(gym.make("FrozenLake-v0"))
# env = gym.wrappers.Monitor(env, directory="mon", force=True)
obs_size = env.observation_space.shape[0]
n_actions = env.action_space.n
net = Net(obs_size, HIDDEN_SIZE, n_actions)
objective = nn.CrossEntropyLoss()
optimizer = optim.Adam(params=net.parameters(), lr=0.001)
writer = SummaryWriter(comment="-frozenlake-tweaked")
full_batch = []
for iter_no, batch in enumerate(iterate_batches(env, net, BATCH_SIZE)):
reward_mean = float(np.mean(list(map(lambda s: s.reward, batch))))
full_batch, obs, acts, reward_bound = filter_batch(full_batch + batch, PERCENTILE)
if not full_batch:
continue
obs_v = torch.FloatTensor(obs)
acts_v = torch.LongTensor(acts)
full_batch = full_batch[-500:]
optimizer.zero_grad()
action_scores_v = net(obs_v)
loss_v = objective(action_scores_v, acts_v)
loss_v.backward()
optimizer.step()
print("%d: loss=%.3f, reward_mean=%.3f, reward_bound=%.3f, batch=%d" % (
iter_no, loss_v.item(), reward_mean, reward_bound, len(full_batch)))
writer.add_scalar("loss", loss_v.item(), iter_no)
writer.add_scalar("reward_mean", reward_mean, iter_no)
writer.add_scalar("reward_bound", reward_bound, iter_no)
if reward_mean > 0.8:
print("Solved!")
break
writer.close()
//////
#!/usr/bin/env python3
import random
import gym
import gym.spaces
import gym.wrappers
import gym.envs.toy_text.frozen_lake
from collections import namedtuple
import numpy as np
from tensorboardX import SummaryWriter
import torch
import torch.nn as nn
import torch.optim as optim
HIDDEN_SIZE = 128
BATCH_SIZE = 100
PERCENTILE = 30
GAMMA = 0.9
class DiscreteOneHotWrapper(gym.ObservationWrapper):
def __init__(self, env):
super(DiscreteOneHotWrapper, self).__init__(env)
assert isinstance(env.observation_space, gym.spaces.Discrete)
self.observation_space = gym.spaces.Box(0.0, 1.0, (env.observation_space.n, ), dtype=np.float32)
def observation(self, observation):
res = np.copy(self.observation_space.low)
res[observation] = 1.0
return res
class Net(nn.Module):
def __init__(self, obs_size, hidden_size, n_actions):
super(Net, self).__init__()
self.net = nn.Sequential(
nn.Linear(obs_size, hidden_size),
nn.ReLU(),
nn.Linear(hidden_size, n_actions)
)
def forward(self, x):
return self.net(x)
Episode = namedtuple('Episode', field_names=['reward', 'steps'])
EpisodeStep = namedtuple('EpisodeStep', field_names=['observation', 'action'])
def iterate_batches(env, net, batch_size):
batch = []
episode_reward = 0.0
episode_steps = []
obs = env.reset()
sm = nn.Softmax(dim=1)
while True:
obs_v = torch.FloatTensor([obs])
act_probs_v = sm(net(obs_v))
act_probs = act_probs_v.data.numpy()[0]
action = np.random.choice(len(act_probs), p=act_probs)
next_obs, reward, is_done, _ = env.step(action)
episode_reward += reward
episode_steps.append(EpisodeStep(observation=obs, action=action))
if is_done:
batch.append(Episode(reward=episode_reward, steps=episode_steps))
episode_reward = 0.0
episode_steps = []
next_obs = env.reset()
if len(batch) == batch_size:
yield batch
batch = []
obs = next_obs
def filter_batch(batch, percentile):
disc_rewards = list(map(lambda s: s.reward * (GAMMA ** len(s.steps)), batch))
reward_bound = np.percentile(disc_rewards, percentile)
train_obs = []
train_act = []
elite_batch = []
for example, discounted_reward in zip(batch, disc_rewards):
if discounted_reward > reward_bound:
train_obs.extend(map(lambda step: step.observation, example.steps))
train_act.extend(map(lambda step: step.action, example.steps))
elite_batch.append(example)
return elite_batch, train_obs, train_act, reward_bound
if __name__ == "__main__":
random.seed(12345)
env = gym.envs.toy_text.frozen_lake.FrozenLakeEnv(is_slippery=False)
env = gym.wrappers.TimeLimit(env, max_episode_steps=100)
env = DiscreteOneHotWrapper(env)
# env = gym.wrappers.Monitor(env, directory="mon", force=True)
obs_size = env.observation_space.shape[0]
n_actions = env.action_space.n
net = Net(obs_size, HIDDEN_SIZE, n_actions)
objective = nn.CrossEntropyLoss()
optimizer = optim.Adam(params=net.parameters(), lr=0.001)
writer = SummaryWriter(comment="-frozenlake-nonslippery")
full_batch = []
for iter_no, batch in enumerate(iterate_batches(env, net, BATCH_SIZE)):
reward_mean = float(np.mean(list(map(lambda s: s.reward, batch))))
full_batch, obs, acts, reward_bound = filter_batch(full_batch + batch, PERCENTILE)
if not full_batch:
continue
obs_v = torch.FloatTensor(obs)
acts_v = torch.LongTensor(acts)
full_batch = full_batch[-500:]
optimizer.zero_grad()
action_scores_v = net(obs_v)
loss_v = objective(action_scores_v, acts_v)
loss_v.backward()
optimizer.step()
print("%d: loss=%.3f, reward_mean=%.3f, reward_bound=%.3f, batch=%d" % (
iter_no, loss_v.item(), reward_mean, reward_bound, len(full_batch)))
writer.add_scalar("loss", loss_v.item(), iter_no)
writer.add_scalar("reward_mean", reward_mean, iter_no)
writer.add_scalar("reward_bound", reward_bound, iter_no)
if reward_mean > 0.8:
print("Solved!")
break
writer.close()
//////
#!/usr/bin/env python3
import gym
import collections
from tensorboardX import SummaryWriter
ENV_NAME = "FrozenLake-v0"
GAMMA = 0.9
ALPHA = 0.2
TEST_EPISODES = 20
class Agent:
def __init__(self):
self.env = gym.make(ENV_NAME)
self.state = self.env.reset()
self.values = collections.defaultdict(float)
def sample_env(self):
action = self.env.action_space.sample()
old_state = self.state
new_state, reward, is_done, _ = self.env.step(action)
self.state = self.env.reset() if is_done else new_state
return (old_state, action, reward, new_state)
def best_value_and_action(self, state):
best_value, best_action = None, None
for action in range(self.env.action_space.n):
action_value = self.values[(state, action)]
if best_value is None or best_value < action_value:
best_value = action_value
best_action = action
return best_value, best_action
def value_update(self, s, a, r, next_s):
best_v, _ = self.best_value_and_action(next_s)
new_val = r + GAMMA * best_v
old_val = self.values[(s, a)]
self.values[(s, a)] = old_val * (1-ALPHA) + new_val * ALPHA
def play_episode(self, env):
total_reward = 0.0
state = env.reset()
while True:
_, action = self.best_value_and_action(state)
new_state, reward, is_done, _ = env.step(action)
total_reward += reward
if is_done:
break
state = new_state
return total_reward
if __name__ == "__main__":
test_env = gym.make(ENV_NAME)
agent = Agent()
writer = SummaryWriter(comment="-q-learning")
iter_no = 0
best_reward = 0.0
while True:
iter_no += 1
s, a, r, next_s = agent.sample_env()
agent.value_update(s, a, r, next_s)
reward = 0.0
for _ in range(TEST_EPISODES):
reward += agent.play_episode(test_env)
reward /= TEST_EPISODES
writer.add_scalar("reward", reward, iter_no)
if reward > best_reward:
print("Best reward updated %.3f -> %.3f" % (best_reward, reward))
best_reward = reward
if reward > 0.80:
print("Solved in %d iterations!" % iter_no)
break
writer.close()
////
%!PS-Adobe-3.0 EPSF-3.0
%Produced by poppler pdftops version: 0.57.0 (http://poppler.freedesktop.org)
%%Creator: TeX
%%LanguageLevel: 2
%%DocumentSuppliedResources: (atend)
%%BoundingBox: 0 0 345 32
%%HiResBoundingBox: 0 0 344.711 31.428
%%DocumentSuppliedResources: (atend)
%%EndComments
%%BeginProlog
%%BeginResource: procset xpdf 3.00 0
%%Copyright: Copyright 1996-2011 Glyph & Cog, LLC
/xpdf 75 dict def xpdf begin
% PDF special state
/pdfDictSize 15 def
/pdfSetup {
/setpagedevice where {
pop 2 dict begin
/Policies 1 dict dup begin /PageSize 6 def end def
{ /Duplex true def } if
currentdict end setpagedevice
} {
pop
} ifelse
} def
/pdfSetupPaper {
% Change paper size, but only if different from previous paper size otherwise
% duplex fails. PLRM specifies a tolerance of 5 pts when matching paper size
% so we use the same when checking if the size changes.
/setpagedevice where {
pop currentpagedevice
/PageSize known {
2 copy
currentpagedevice /PageSize get aload pop
exch 4 1 roll
sub abs 5 gt
3 1 roll
sub abs 5 gt
or
} {
true
} ifelse
{
2 array astore
2 dict begin
/PageSize exch def
/ImagingBBox null def
currentdict end
setpagedevice
} {
pop pop
} ifelse
} {
pop
} ifelse
} def
/pdfStartPage {
pdfDictSize dict begin
/pdfFillCS [] def
/pdfFillXform {} def
/pdfStrokeCS [] def
/pdfStrokeXform {} def
/pdfFill [0] def
/pdfStroke [0] def
/pdfFillOP false def
/pdfStrokeOP false def
/pdfLastFill false def
/pdfLastStroke false def
/pdfTextMat [1 0 0 1 0 0] def
/pdfFontSize 0 def
/pdfCharSpacing 0 def
/pdfTextRender 0 def
/pdfPatternCS false def
/pdfTextRise 0 def
/pdfWordSpacing 0 def
/pdfHorizScaling 1 def
/pdfTextClipPath [] def
} def
/pdfEndPage { end } def
% PDF color state
/cs { /pdfFillXform exch def dup /pdfFillCS exch def
setcolorspace } def
/CS { /pdfStrokeXform exch def dup /pdfStrokeCS exch def
setcolorspace } def
/sc { pdfLastFill not { pdfFillCS setcolorspace } if
dup /pdfFill exch def aload pop pdfFillXform setcolor
/pdfLastFill true def /pdfLastStroke false def } def
/SC { pdfLastStroke not { pdfStrokeCS setcolorspace } if
dup /pdfStroke exch def aload pop pdfStrokeXform setcolor
/pdfLastStroke true def /pdfLastFill false def } def
/op { /pdfFillOP exch def
pdfLastFill { pdfFillOP setoverprint } if } def
/OP { /pdfStrokeOP exch def
pdfLastStroke { pdfStrokeOP setoverprint } if } def
/fCol {
pdfLastFill not {
pdfFillCS setcolorspace
pdfFill aload pop pdfFillXform setcolor
pdfFillOP setoverprint
/pdfLastFill true def /pdfLastStroke false def
} if
} def
/sCol {
pdfLastStroke not {
pdfStrokeCS setcolorspace
pdfStroke aload pop pdfStrokeXform setcolor
pdfStrokeOP setoverprint
/pdfLastStroke true def /pdfLastFill false def
} if
} def
% build a font
/pdfMakeFont {
4 3 roll findfont
4 2 roll matrix scale makefont
dup length dict begin
{ 1 index /FID ne { def } { pop pop } ifelse } forall
/Encoding exch def
currentdict
end
definefont pop
} def
/pdfMakeFont16 {
exch findfont
dup length dict begin
{ 1 index /FID ne { def } { pop pop } ifelse } forall
/WMode exch def
currentdict
end
definefont pop
} def
% graphics state operators
/q { gsave pdfDictSize dict begin } def
/Q {
end grestore
/pdfLastFill where {
pop
pdfLastFill {
pdfFillOP setoverprint
} {
pdfStrokeOP setoverprint
} ifelse
} if
} def
/cm { concat } def
/d { setdash } def
/i { setflat } def
/j { setlinejoin } def
/J { setlinecap } def
/M { setmiterlimit } def
/w { setlinewidth } def
% path segment operators
/m { moveto } def
/l { lineto } def
/c { curveto } def
/re { 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto
neg 0 rlineto closepath } def
/h { closepath } def
% path painting operators
/S { sCol stroke } def
/Sf { fCol stroke } def
/f { fCol fill } def
/f* { fCol eofill } def
% clipping operators
/W { clip newpath } def
/W* { eoclip newpath } def
/Ws { strokepath clip newpath } def
% text state operators
/Tc { /pdfCharSpacing exch def } def
/Tf { dup /pdfFontSize exch def
dup pdfHorizScaling mul exch matrix scale
pdfTextMat matrix concatmatrix dup 4 0 put dup 5 0 put
exch findfont exch makefont setfont } def
/Tr { /pdfTextRender exch def } def
/Tp { /pdfPatternCS exch def } def
/Ts { /pdfTextRise exch def } def
/Tw { /pdfWordSpacing exch def } def
/Tz { /pdfHorizScaling exch def } def
% text positioning operators
/Td { pdfTextMat transform moveto } def
/Tm { /pdfTextMat exch def } def
% text string operators
/xyshow where {
pop
/xyshow2 {
dup length array
0 2 2 index length 1 sub {
2 index 1 index 2 copy get 3 1 roll 1 add get
pdfTextMat dtransform
4 2 roll 2 copy 6 5 roll put 1 add 3 1 roll dup 4 2 roll put
} for
exch pop
xyshow
} def
}{
/xyshow2 {
currentfont /FontType get 0 eq {
0 2 3 index length 1 sub {
currentpoint 4 index 3 index 2 getinterval show moveto
2 copy get 2 index 3 2 roll 1 add get
pdfTextMat dtransform rmoveto
} for
} {
0 1 3 index length 1 sub {
currentpoint 4 index 3 index 1 getinterval show moveto
2 copy 2 mul get 2 index 3 2 roll 2 mul 1 add get
pdfTextMat dtransform rmoveto
} for
} ifelse
pop pop
} def
} ifelse
/cshow where {
pop
/xycp {
0 3 2 roll
{
pop pop currentpoint 3 2 roll
1 string dup 0 4 3 roll put false charpath moveto
2 copy get 2 index 2 index 1 add get
pdfTextMat dtransform rmoveto
2 add
} exch cshow
pop pop
} def
}{
/xycp {
currentfont /FontType get 0 eq {
0 2 3 index length 1 sub {
currentpoint 4 index 3 index 2 getinterval false charpath moveto
2 copy get 2 index 3 2 roll 1 add get
pdfTextMat dtransform rmoveto
} for
} {
0 1 3 index length 1 sub {
currentpoint 4 index 3 index 1 getinterval false charpath moveto
2 copy 2 mul get 2 index 3 2 roll 2 mul 1 add get
pdfTextMat dtransform rmoveto
} for
} ifelse
pop pop
} def
} ifelse
/Tj {
fCol
0 pdfTextRise pdfTextMat dtransform rmoveto
currentpoint 4 2 roll
pdfTextRender 1 and 0 eq {
2 copy xyshow2
} if
pdfTextRender 3 and dup 1 eq exch 2 eq or {
3 index 3 index moveto
2 copy
currentfont /FontType get 3 eq { fCol } { sCol } ifelse
xycp currentpoint stroke moveto
} if
pdfTextRender 4 and 0 ne {
4 2 roll moveto xycp
/pdfTextClipPath [ pdfTextClipPath aload pop
{/moveto cvx}
{/lineto cvx}
{/curveto cvx}
{/closepath cvx}
pathforall ] def
currentpoint newpath moveto
} {
pop pop pop pop
} ifelse
0 pdfTextRise neg pdfTextMat dtransform rmoveto
} def
/TJm { 0.001 mul pdfFontSize mul pdfHorizScaling mul neg 0
pdfTextMat dtransform rmoveto } def
/TJmV { 0.001 mul pdfFontSize mul neg 0 exch
pdfTextMat dtransform rmoveto } def
/Tclip { pdfTextClipPath cvx exec clip newpath
/pdfTextClipPath [] def } def
/Tclip* { pdfTextClipPath cvx exec eoclip newpath
/pdfTextClipPath [] def } def
% Level 2/3 image operators
/pdfImBuf 100 string def
/pdfImStr {
2 copy exch length lt {
2 copy get exch 1 add exch
} {
()
} ifelse
} def
/skipEOD {
{ currentfile pdfImBuf readline
not { pop exit } if
(%-EOD-) eq { exit } if } loop
} def
/pdfIm { image skipEOD } def
/pdfImM { fCol imagemask skipEOD } def
/pr { 2 index 2 index 3 2 roll putinterval 4 add } def
/pdfImClip {
gsave
0 2 4 index length 1 sub {
dup 4 index exch 2 copy
get 5 index div put
1 add 3 index exch 2 copy
get 3 index div put
} for
pop pop rectclip
} def
/pdfImClipEnd { grestore } def
% shading operators
/colordelta {
false 0 1 3 index length 1 sub {
dup 4 index exch get 3 index 3 2 roll get sub abs 0.004 gt {
pop true
} if
} for
exch pop exch pop
} def
/funcCol { func n array astore } def
/funcSH {
dup 0 eq {
true
} {
dup 6 eq {
false
} {
4 index 4 index funcCol dup
6 index 4 index funcCol dup
3 1 roll colordelta 3 1 roll
5 index 5 index funcCol dup
3 1 roll colordelta 3 1 roll
6 index 8 index funcCol dup
3 1 roll colordelta 3 1 roll
colordelta or or or
} ifelse
} ifelse
{
1 add
4 index 3 index add 0.5 mul exch 4 index 3 index add 0.5 mul exch
6 index 6 index 4 index 4 index 4 index funcSH
2 index 6 index 6 index 4 index 4 index funcSH
6 index 2 index 4 index 6 index 4 index funcSH
5 3 roll 3 2 roll funcSH pop pop
} {
pop 3 index 2 index add 0.5 mul 3 index 2 index add 0.5 mul
funcCol sc
dup 4 index exch mat transform m
3 index 3 index mat transform l
1 index 3 index mat transform l
mat transform l pop pop h f*
} ifelse
} def
/axialCol {
dup 0 lt {
pop t0
} {
dup 1 gt {
pop t1
} {
dt mul t0 add
} ifelse
} ifelse
func n array astore
} def
/axialSH {
dup 0 eq {
true
} {
dup 8 eq {
false
} {
2 index axialCol 2 index axialCol colordelta
} ifelse
} ifelse
{
1 add 3 1 roll 2 copy add 0.5 mul
dup 4 3 roll exch 4 index axialSH
exch 3 2 roll axialSH
} {
pop 2 copy add 0.5 mul
axialCol sc
exch dup dx mul x0 add exch dy mul y0 add
3 2 roll dup dx mul x0 add exch dy mul y0 add
dx abs dy abs ge {
2 copy yMin sub dy mul dx div add yMin m
yMax sub dy mul dx div add yMax l
2 copy yMax sub dy mul dx div add yMax l
yMin sub dy mul dx div add yMin l
h f*
} {
exch 2 copy xMin sub dx mul dy div add xMin exch m
xMax sub dx mul dy div add xMax exch l
exch 2 copy xMax sub dx mul dy div add xMax exch l
xMin sub dx mul dy div add xMin exch l
h f*
} ifelse
} ifelse
} def
/radialCol {
dup t0 lt {
pop t0
} {
dup t1 gt {
pop t1
} if
} ifelse
func n array astore
} def
/radialSH {
dup 0 eq {
true
} {
dup 8 eq {
false
} {
2 index dt mul t0 add radialCol
2 index dt mul t0 add radialCol colordelta
} ifelse
} ifelse
{
1 add 3 1 roll 2 copy add 0.5 mul
dup 4 3 roll exch 4 index radialSH
exch 3 2 roll radialSH
} {
pop 2 copy add 0.5 mul dt mul t0 add
radialCol sc
encl {
exch dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add
0 360 arc h
dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add
360 0 arcn h f
} {
2 copy
dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add
a1 a2 arcn
dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add
a2 a1 arcn h
dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add
a1 a2 arc
dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add
a2 a1 arc h f
} ifelse
} ifelse
} def
end
%%EndResource
%%EndProlog
%%BeginSetup
xpdf begin
%%BeginResource: font YQYTWD+CMMI10
%!PS-AdobeFont-1.0: CMMI10 003.002
%%Title: CMMI10
%Version: 003.002
%%CreationDate: Mon Jul 13 16:17:00 2009
%%Creator: David M. Jones
%Copyright: Copyright (c) 1997, 2009 American Mathematical Society
%Copyright: (<http://www.ams.org>), with Reserved Font Name CMMI10.
% This Font Software is licensed under the SIL Open Font License, Version 1.1.
% This license is in the accompanying file OFL.txt, and is also
% available with a FAQ at: http://scripts.sil.org/OFL.
%%EndComments
FontDirectory/CMMI10 known{/CMMI10 findfont dup/UniqueID known{dup
/UniqueID get 5087385 eq exch/FontType get 1 eq and}{pop false}ifelse
{save true}{false}ifelse}{false}ifelse
11 dict begin
/FontType 1 def
/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
/FontName /YQYTWD+CMMI10 def
/FontBBox {-32 -250 1048 750 }readonly def
/PaintType 0 def
/FontInfo 10 dict dup begin
/version (003.002) readonly def
/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMMI10.) readonly def
/FullName (CMMI10) readonly def
/FamilyName (Computer Modern) readonly def
/Weight (Medium) readonly def
/ItalicAngle -14.04 def
/isFixedPitch false def
/UnderlinePosition -100 def
/UnderlineThickness 50 def
/ascent 750 def
end readonly def
/Encoding 256 array
0 1 255 {1 index exch /.notdef put} for
dup 65 /A put
dup 71 /G put
dup 80 /P put
dup 82 /R put
dup 83 /S put
dup 86 /V put
dup 97 /a put
dup 13 /gamma put
dup 58 /period put
dup 25 /pi put
dup 115 /s put
readonly def
currentdict end
currentfile eexec
d9d66f633b846ab284bcf8b0411b772de5ce3c05ef98f858322dcea45e0874c5
45d25fe192539d9cda4baa46d9c431465e6abf4e4271f89eded7f37be4b31fb4
7934f62d1f46e8671f6290d6fff601d4937bf71c22d60fb800a15796421e3aa7
72c500501d8b10c0093f6467c553250f7c27b2c3d893772614a846374a85bc4e
bec0b0a89c4c161c3956ece25274b962c854e535f418279fe26d8f83e38c5c89
974e9a224b3cbef90a9277af10e0c7cac8dc11c41dc18b814a7682e5f0248674
11453bc81c443407af56dca20efc9fa776eb9a127b62471340eb64c5abdf2996
f8b24ef268e4f2eb5d212894c037686094668c31ec7af91d1170dc14429872a0
a3e68a64db9e871f03b7c73e93f77356c3996948c2deade21d6b4a87854b79da
d4c3d1e0fc754b97495bcfc684282c4d923dfeace4ec7db525bd8d76668602ba
27b09611e4452b169c29ea7d6683a2c6246c9ddcf62885d457325b389868bc54
3ea6dc3984ba80581133330d766998ae550e2fb5e7c707a559f67b7a34fea2f3
bebe4226da71af8b6e8d128c7ae0b3dc7c9aa4a1faef312fc9b46399b18c437a
776de1f67caf78e15d4cc76d6fa57dad7abc6d35ede0d7118e8c6f3a201f9ea9
eabf8a848d182eba8922addbe3c488f51eac02906400a84ea0abfaf48116cdc6
6fbc00330a76a8818cfaeb7afdeb029a204e0a70b47a05aa50153b56d2bf6736
c7a2c50b023ed92cfff13eba974f804a346d4130ccfd5233b6d6b92a14c87bbe
2ba216bae4123911e1856975e5cf4d94e44f400f687d2d13db288e0d821451c8
83e9928f8cbc41e0f4b99f8b29d3b11bd4ed0cbca83d81082e39a9e79cebf433
671b1af39c3d0e1f5bbe5f1fff62ff6f5f15f0421c56a4dffac682cb07b6f257
221fed1902e4b69d9bc2e061f2e96f5a46734f91298494a425ef6432f2b9778c
4ebbadd3483ef5447df5f008db9d91c559950ebcedb4b1316a5aae8367a80e06
bf3162beb99c4aaa617c60be688da7627f29c1775983ef635b26306a94f0b258
003779f8670a1398681953b785a226057f7d1270fe2dd2ea66d65e2061fbd65f
0ac51b6c347a56e9f3e86e52f3e0bf1d5f8d6540afb32a027a7c96919557692e
b739cc298ec7999b4286538edf7333cf8f8f6ba02c5e8c62929af07acbb90861
0bcb85345f4206e3ea130512dcfbc6cefa31ef2bd1da11d3010fec57b5b232ca
706f9c44fb9cab8903be783eca66d748b3fa5b1f5d5445f6c16a9a52c88a7e2f
2bfb0be4e416ea209a9810dd6c38e47a58dc9270b2f49f9b9d482156f7dc8164
b621b6803b6434a2a354a50fd9353a2ce3fa761423634b8f2adcd63b2b7acf15
07588caf127a0d6b2017a451d3df77c53e6171c66236e5318d49fab9ce4b1026
853f65d0d5f7913d88ea66b9b63cf06a4bfc8ed3246bb86cf6de255ff46d245d
109939e32dc483a0e5176b614ccb7f1adcf99854cf50317bd081131a146ea089
8ed59e46da7b6254bdccbc660686e2eda0ad7b894cd2eb2688c0c00aca589d39
e3caa6e0faf7eeb5df3e3f8113dae4b454a0d8c86fee52779ad3e13a0a871e9b
65b9ef0a2ff20989bae81d1cc1181679fbedb80e7d84a08774e6da58a283ba22
3780f2717484e066fa7dc012e6d19429b08638045352d358957917123c9c73b4
326a954f5ebce183ba1025c00c8f559dba85e07b3ed48d2fa0acafa9436d6fdf
e530ce25ac7da170db1764e77b6816343e8a128a075e7744a6f0406551f4640e
c403ea61696459d15ee040bfb53f08700c69333b1cb28142c5b9411d65fbfb1e
c7f4f50c03d122ad4b63e9e65f0a0af43efcc9fc546fd13da42a1c13b8c9cbfa
79a480d923701306249955ce1c61a680b2809d3551325a333a189db71bc83c59
47d17b31f8ff63564919b00336285f724d22f889748564808083ddaa4eeb8632
5d636961e1f634f3ff3def1dcd7299bb7679dbaf685e2ac1484bd9b17c5cf4d8
59897713b51a4deba3332c2ab5c48a76357d2eaaa539a617b09f223661bcb411
0e6559e99a7d900336a9327d4b8330ee5f56b016cebb8c07dbcc2fa736c07ecb
8930f26b429288c6fe6cee3e7792de58ea3ce248598db0c604787612bd137d80
e4462d249b229b62142128b57a6b44515262743bb3c70ee96aa4b8c49d6b0be4
4e19f634add30634f999f4dfb3dcff6a412a9b6067d28751aab1b20928a6e73b
cb81b0510d551f84437062e8cd403bf8c343003965e926465b288b0aa2fc85f9
90f9a63fce188d72008aed98bcba5ff4ae850711d2664f0857ded002e3a89fa8
75f930ddf7918d6b2f92ae26af35f50cc9d2a8f9b5d5d80981b12ddf4c59565a
aa62ec34589e5bcc3075cc6a163e45d46bb280b22158c5c04c90beb6f8a1c791
5597b0f69be3204d876cfa54481cc86ed2fe799bc46555c6c6fffc73854104dc
9c8a6f85331fce7c5d1f20af5d99e4e61b7ab981dd4eae26951a9447d5553140
b5862e2f39023bc7d14901eacf467a9424a6be8055d82f4b02036cd766367871
e0a01d09790ab2777db18248482fb32a25fadb62956b93affc59b1796f78d0b6
6aaeee9778a3b253bd98035c79b5296e173fba9e56e8824ab6191ef9062b1fc8
1b6b6185a05b167adccc6698b1801297d766492add5b66193d024d121633d329
25bcf1a9ae109371aaaeb64f2805bf5c2d5a218c191e9eeb4ac30a48291c7251
f690b51d5135f6a37f5418624c7d2f3ece356b12ec18f73d5177a24ffe371635
fc88231b3a95d72ca2555f164c503f91b5c7ca174e43aee6534df6d569efd50d
da3e950e11c6cff788e50ce5f1332ad76a2357c39d44ea38e88b24f2d37cf29e
21b7468adfcacc8ab8fe1ae9da4c933b5f7f0a6451964a4924b6ba96c359c828
d818166d5271e813f7a34a5b18927e66d61003392c96ab36b3e2175f31faa3d3
7e77200bbbeba91c532c053f318f3f83080bf3d641d4c5df796c2882e34c01b9
cf74bba01f03ef559012eeece809c019ab6d40d22a16fb9054143990db45b902
a5574f672dda96d6c18c0fb048e970e6180e6148061e22085c7aa4fdc2102fd2
d31e84456a56057b9d3189f331cc8354b195564cfdd23579574b7c7a80d2f3e3
97f07cdab67407a46a4264e985563dae7ad933dac054d64a7ebce65bb2beb5fe
d53360fd76a0fe706e7283550c4d5657aa9bf62ee713592d74e89998e9b0adb2
327a9dd5f19184a500870a3c53367431b56cc4dd60bb629ae68a009fba0049eb
16d11d5f299d5a99f3d45f6510450e53740da5556335eccd43e1408b826fc535
10c7784c44cdbf41988ab67ffdc54ea61dd05208204c8bed9c66c678e6324428
9682cc6ea0b2dad69cdb69dc8daacfd1a98c730dc3d9bc8d83e2fa2e72de08b0
031ef3455ba92d03acfdb7ecf50ee883a8817abd96e58f72ae050feae0d224a5
42aa0b4c022f8a90e73ab84216f520d6ded72680471b9ed2ce317536305d7360
810a92f4957c9aba9328b116349fdfa728e9f042b2fd2d116bbcbbb99ec6966b
a5e1f4fbbb4b1eae6d8bdd40de5fa44127e6d7c05abad3c012082c245265096d
d4445b03ad8dc08d707ecbf0aef0890b0658dc9341fd386d417ad9f5e79c0464
be4e3b22e4997e1806d192a8be70dfbcf69715b8194347a60e80934ed09fb08e
c4df7c3b204b07ee3610c041dff7d4c76060e4be6a3a2f0b0217005ab38f80ff
fe55a6252afa361b5cd8f3b642e6e193da913ccaeae5508c2470036aad80c0c6
e977c374852b69a8de69aea44aaad49eb7fcd420bd55a5c5cbf073e859ba9d6a
857da20a5cc2744843ea07efcaf91e992f0a44e1e520bbca097b6965c4e30c99
03ac3ca1af1bbeeacffd7cc22e7b9763b0876cf8308ea38828a716da7f430898
2beecd1cb81cd95ab8fe70242026f11061a70fb42445aa9246488d6d0029df17
dea43305ac74df52e5699b6c243025786b21fd43993a8039e9e75fce2dbb7d6b
7e4cd140e7edacc20dcb473dc45eab68d8ea296baf9bb969093862d391f84073
5e17f87847ff2e9186080feb184ff7869a5a8bee6aafe3461454dcbcd00d2c24
61ef831a52dbb0fa736694b4a3a4d85c6d80636b316fb12be67f0887cce6df04
80c145ea8762ef8b2c43ae71f3c32686fd5813eb49a39bc6d4980472bd5cdbb6
c282c9ffe2fb52656f607692e1ba726417703feccfd4aeaf9c66d543ce1506b1
a9d6b95705f67086d4f36b06a283cec841a01f1028d95d4de419d7110f091014
f6dc905e81add1d54f95b16cddcfd0793d1cf4a85e7a35458c81197a24fe82cb
63edde30cb6b538a708fbd41f00268a772730b85bd8860054acd93fe6b8bbcb9
cc474568d426e83f15838520a313e0ae1b60959de340398b21986f5c404c9361
54975d52740bec0f7abfaf271a2ac1f7553b862d45d11ae585936fbb5462e2dd
bf35e4afb7bffcbd3294be3eabec4b787133c3a5e0c95f74a71dad9be990d07c
d157d7258830a3cc3de6459140afba942eef325ee072b3a53a9f281d483eac65
e8da50ccddb3d43baff7d8c7d7a1847d6d579ce92df1b54de141ce7a73607362
7d909e8cd9fdc373b840145f9373bc2f02979ee34688bf840f4f9245c2ab976c
ee8bde685c47606201f6611e38a49ab72428def2c85e553313af719ab4d4f5ef
e3f3430522abff76bf8bb8f56afe11008d3f989ffadccb411dd3b7e6352ea873
3abe5dc71b3b4832ae85bdb23f6cbfb4b2631412e4fe0050a5f7f4216508a3db
ea2d74318ed82f1a2fc791623c869593dcfd6bfb2fe57bdf06e9d1946f9bcea0
13848fcdc603e3eca5384725118970cebcc9ebc6b74df13ad395fa6efdc22463
5380eb1b3521aa929eba30958ae2da40852196b67ee44409d323383b0c7fa1f2
b4fff373041d9f5eeab03d6743f0a291b481dd3ff9e8ebd77a073b8d5f5d93bc
727e6566204893af892f74fc0bc3f3e83643a93747678eb998f9c91b3a0ff942
3d3924f507f1c7eb18249b2ab73691f5fac868720ff52183091f65ac3be8cb0e
80d257c52ea8647ef747fe304598e1ce0900a4de4031e4b6a58d7869b08a56aa
710c91ccb8afab94ad10d670e767a44e0177795ddfd65c9cdc7332716deefe3f
9e2ed8a54bb6faf63b7bf5f554b934821086c09fc28fa74ea2efd410e006be6b
ebe0c464e078c14968453dc783a788a55d925d72205492c07d0dbaee4982fbed
9b32dd19ae230da5870499feeac55b09b0970ad5926375fd79b95552816be003
90515262b5ca891babcd81bf86847cbc5850d4a056bdc528e97aded1ea6d7b76
bd8ec34e742a9fccf19a6310004499b1cc1a920b5f3b746bd4de2d9b9dea341d
25a7a7b60546a8f9ef99190cf8ddedb21a0103414f9f28ae8673c966b12528dc
fb70ce44db4822322605982d708a0b4bef7eb08962e3f433213d7545f351e994
970828eb443c3bb36ab0c4cab7fadfd949e5f93273141da2b6dffb41b4678647
93cd4e53c78a63c632d4fcbad772122e86dde337d5438e5e4342a0e18be8b014
3ddd7290d16096f2149c6c71ad28325dddbf994e651b9d4be89430b31dec3fa7
d2703196f7f10b5e8d98f20e14151160507e53ff1f3d4bddff3f45f9e64b1b9b
9b26b32bf389a3725c243209245bd78c2f78d67033be00ebe25955a1ac718305
b52a0260a07220a9f7410bad935538c6c7c56f902a70730c1cf90d45a5f66c6b
a762406e512bf3cc3b52918c6e9e92893279cf86af1684d9b67d1ebbe84be9d8
4b56548323ab381ae18c9e9570453abe77ca9d9ed1164563120b939fc3acc33d
49f5e989a74ac760f0c99458295278efde92e99003c4780935d12eda68a82308
ba444819ea9fd930c80263b57ec1b9164aa50ce386b8ef81a53a710416c6c868
794bddb4fe463b3c59ff9fd085fc7ec37cf2abb7df09d41113f4542f72bffda6
1fafef41c462eabcc7a3b4fbe46cac256c7af4309a617e73e7934450434e344b
5cb6ddf2e63f4523f1526ed2f79522eae16b23dd9ff4924053a0fa7c4a0b29ff
f4485c041b06147d2c94d276553f443c2980cb96ef5da49bfda4ee95bbf092ac
e2dee947d0c711c1930500b79a5424e8494df6e1798b009a3816342f4d1d7cb0
b7bf239f3d60361ac605020591740d13ce386bca1e69a2e8063c62f9959c9fb9
010ae39f18882b1e3b3d0d9b0447db7f7f7a3810375372702686b224896bf5e4
cd40e308b5a6988b614d8088c296171423cab2657cfb98f462afe21e990b0c74
4c8738d1b13097ca887ccfd3eabe4f1e29df71d0e51046957409964f9f02a33d
78b2a5bac5058bda0dd8a65fe6c53dff9310fd2b97afd24f39e586417dcc18a1
5c0be1795e0f2c3d785f8cc1ab5505bb8fc0dfa1364f08876a42dae3383f853f
84e7e54405bb8d00911c5b8ef4794494d9bf076d57a65f2392628b61ff967c77
29114960e00fadc36961617c61c673bd2d2e4a9d54702233c8414026e67940bd
ed16e2d3822f06068502c0966f2ff68f74d11a0b780b95f3f52bcc162a37b6ef
48cf5ff8513cf4183176734f80b9835401b3db6bd53597645873fa96488eb183
646b577037e5717952d23cc71ee1780b3df42d9c768804fc47cf147db059b9ee
7a6399d4f4afcf2d296902f16d56d6df28ac4c9a96e357678ba901fe72ce3d2f
b10fbf263146547d455df1bc33a1dfa753251c264db8798da35943a4940962f9
e3b8a68d2b094177154ba30af7bd201cad919c09a34536e41d6c5772873c0634
fef84dca5f1a5d5488997e279876af1dfb3f51790a6ae085d09ea4e1947fc10b
987c2db0634c100484f4b45404119fee7a7ec81111029cff1b4cfa1a8637d4a5
ad472b5ac0cb9f428cb1df8abfea3db8082a26cc815437ab387e7f87902398d2
e0c6bf6c95c2381f15b61fb2c5bdb8684afbb7a6c1a01ca2286a8dff62e52a16
3d7c748c1b2c63d2933012c5306cb7efb0b4cd733c56ba7700acc731d294f7a1
1f2a1f8f461983f2972da8c3dbb3f9117f7a6f3583c8a5dcabb364ac0310457f
93fbca26c31482d806c6a7a4f87f4cb92e3f30b4dd2dd5e3da5360430c008237
7165549aa416a73c62a50b707074b2b7ded2b07454574f60861cd2f0342e4f78
24789278e711f18ef858b819a0accb67384b47145fee30b32181d66ff47aa657
83f0cccb693ac70657bc2bf204974bb3bcbffcd6540477e7a973718754acbe68
823672daeaf24c93263a57598ac4bc999120e367aaa4b54c643e8c8987024b07
9b0d40fb33d55cee534e3a38a1a316276704e9a6df08553fde29e4d4526225d1
fbda6f8cb78098e83e8a360de3c4c77e2998094f920aaba9c7587735cd2f22cb
e17c6b99a8286519242f18de4aabbe470bb8e0931ec7f5c19e1c304df56f2368
70d154e925c4f2e5012d52a0283ea52acefa09d2a8ecc832358868bce8efba7c
492e3575c1605150a3f7d6822960f1a9975151c7b6e928fc07f73493351895b3
5ea783de8482144ddfaf6f881d0835472a603fcd52464da80de0c380fed5cc67