-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathrsmi_aux.f
3387 lines (3332 loc) · 116 KB
/
rsmi_aux.f
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
C]
C->>> ------------------------------------------> ems_rm_rhs_ix_o_ze <<<
c Removes the indices of zeros and repeated entries in pi
c
subroutine ems_rm_rhs_ix_o_ze(rhs_v, rhs_ix, i_wk_a)
implicit none
include 'EMSV.INC'
include 'EMSPM.INC'
include 'ICTVR.INC'
CM IF (emsol_tt .EQ. 1) THEN
C? include 'EMSTT.INC'
CM ENDIF
double precision rhs_v(0:n_r)
integer rhs_ix(0:n_r)
integer i_wk_a(0:n_r)
integer rhs_n_ix, ix_n, r_n
if (rhs_ix(0) .gt. n_r) goto 7000
CM IF (emsol_tt .EQ. 1) THEN
C? if (g_tt_da .gt. 0) call ems_tt_rec(rm_rhs_ix_o_ze_tt, n_bs)
CM ENDIF
do 10, ix_n = 1, rhs_ix(0)
i_wk_a(rhs_ix(ix_n)) = 1
10 continue
rhs_n_ix = 0
do 20, ix_n = 1, rhs_ix(0)
r_n = rhs_ix(ix_n)
if (i_wk_a(r_n) .ne. 0) then
if (rhs_v(r_n) .ne. zero) then
rhs_n_ix = rhs_n_ix + 1
rhs_ix(rhs_n_ix) = r_n
endif
i_wk_a(r_n) = 0
endif
20 continue
c if (rhs_ix(0) .ne. rhs_n_ix)
c & print*, 'Iteration ', n_si_it,
c & ': Removed ', rhs_ix(0)-rhs_n_ix,
c & ' zeros and repeated entries from RHS'
rhs_ix(0) = rhs_n_ix
CM IF (emsol_tt .EQ. 1) THEN
C? if (g_tt_da .gt. 0) call ems_tt_rec(-rm_rhs_ix_o_ze_tt, n_bs)
CM ENDIF
7000 continue
return
end
C->>> -----------------------------------------> ems_ca_g_ml_ob_fn_v <<<
c Black box call to get the current objective value.
c
subroutine ems_ca_g_ml_ob_fn_v(lc_ob_fn_v, ds, is)
implicit none
include 'EMSV.INC'
include 'EMSPM.INC'
include 'EMSMMGR.INC'
include 'EMSMEM.INC'
include 'EMSP.INC'
include 'ICTVR.INC'
include 'RLCTVR.INC'
integer is(0:is_n_en_m1)
double precision ds(0:ds_n_en_m1)
double precision lc_ob_fn_v
double precision ems_g_ml_ob_fn_v
lc_ob_fn_v = ems_g_ml_ob_fn_v(
& is(p_st),
& ds(p_rsmi_lb),
& ds(p_rsmi_co),
& ds(p_rsmi_ub),
& ds(p_pr_act), ds, is)
return
end
C->>> -------------------------------------> ems_ca_g_n_su_mx_pr_ifs <<<
c Black box call to get the current number, sum and max of primal
c infeasibilities.
c
subroutine ems_ca_g_n_su_mx_pr_ifs(
& lc_n_pr_ifs, lc_su_pr_ifs, mx_pr_ifs, mx_rlv_pr_ifs,
& ds, is)
implicit none
include 'EMSV.INC'
include 'EMSPM.INC'
include 'EMSMMGR.INC'
include 'EMSMEM.INC'
include 'EMSP.INC'
include 'ICTVR.INC'
integer is(0:is_n_en_m1)
double precision ds(0:ds_n_en_m1)
integer lc_n_pr_ifs
double precision lc_su_pr_ifs, mx_pr_ifs, mx_rlv_pr_ifs
call ems_g_n_su_mx_pr_ifs(
& ds(p_rsmi_lb),
& ds(p_rsmi_ub),
& ds(p_pr_act),
& is(p_st),
& lc_n_pr_ifs, lc_su_pr_ifs, mx_pr_ifs, mx_rlv_pr_ifs)
return
end
C->>> -------------------------------------> ems_ca_g_n_su_mx_du_ifs <<<
c Black box call to get the current number, sum and max of dual
c infeasibilities.
c
subroutine ems_ca_g_n_su_mx_du_ifs(
& lc_n_du_ifs, lc_su_du_ifs, mx_du_ifs, mx_rlv_du_ifs,
& ds, is)
implicit none
include 'EMSV.INC'
include 'EMSPM.INC'
include 'EMSMMGR.INC'
include 'EMSMEM.INC'
include 'EMSP.INC'
include 'ICTVR.INC'
integer is(0:is_n_en_m1)
double precision ds(0:ds_n_en_m1)
integer lc_n_du_ifs
double precision lc_su_du_ifs, mx_du_ifs, mx_rlv_du_ifs
call ems_g_n_su_mx_du_ifs(
& is(p_vr_in_c),
& ds(p_rsmi_lb),
& ds(p_rsmi_co),
& ds(p_rsmi_ub),
& ds(p_du_act),
& lc_n_du_ifs, lc_su_du_ifs, mx_du_ifs, mx_rlv_du_ifs)
return
end
C->>> ----------------------------------------------> ems_du_act_atr <<<
c Determines whether a dual activity is attractive.
c
logical function ems_du_act_atr(vr_st, du_act, tl_du_ifs)
implicit none
include 'EMSV.INC'
include 'EMSPM.INC'
integer vr_st
double precision du_act, tl_du_ifs
logical du_act_atr
if (iand(vr_st, ifs_bt) .ne. 0) then
c
c Infeasible nonbasic variables are always free to move up or down
c so the up and down bits are used to indicate the bound which is
c violated---as for basic variables. This means that the up/down
c bits of the entering variable are interpreted correctly in the
c ratio test.
c
du_act_atr = abs(du_act) .gt. tl_du_ifs
else
du_act_atr =
& (iand(vr_st, dn_bt) .ne. 0 .and. du_act .gt. tl_du_ifs)
& .or.
& (iand(vr_st, up_bt) .ne. 0 .and. du_act .lt. -tl_du_ifs)
endif
ems_du_act_atr = du_act_atr
return
end
C->>> ------------------------------------------------> ems_rsmi_inv <<<
c Perform an INVERT
c
subroutine ems_rsmi_inv(ds, is)
implicit none
include 'EMSV.INC'
include 'EMSPM.INC'
include 'EMSMMGR.INC'
include 'EMSMEM.INC'
include 'EMSP.INC'
include 'RSMICS.INC'
include 'RSMICOM.INC'
include 'ICTVR.INC'
include 'RLCTVR.INC'
include 'EMSMSG.INC'
include 'MORSMI.INC'
CM IF (emsol_epc .EQ. 1) THEN
C? logical ems_i1_eq_i2
CM ENDIF
double precision ds(0:ds_n_en_m1)
integer is(0:is_n_en_m1)
c logical ems_rq_nw_u_eta_grp
integer ems_g_bs_mtx_n_a_en
integer bs_mtx_n_a_en
integer p_hdl_eta_grp, p_eta_grp
double precision v
integer mem_mgr_rt_cod
integer rt_cod
c
c Perform an INVERT.
c
c if (iand(rsmi_msg_msk, rsmi_inv_li_bt) .ne. 0) then
pre_eta_fi_n_eta = eta_fi_n_eta
pre_eta_fi_n_ix = eta_fi_n_ix
c endif
c
c Remove the blocks associated with the previous INVERT.
c
call ems_rm_inv(is)
if (iand(ml_blk_st_msk, ml_blk_st_ml_bs_inv_p) .eq. 0) then
c
c Allocate space for INVERT pointers.
c
call ems_iz_blk_ml_bs_inv_p(is)
if (ems_msg_cod .ge. ems_msg_lvl_serious) go to 7000
is(p_lo_eta_pv_in_r) = n_r
endif
call ems_inv(ds, is)
if (ems_msg_cod .ge. ems_msg_lvl_serious) go to 7000
CM IF (emsol_da .EQ. 1) THEN
C? if (iand(inv_msg_msk, bt3) .ne. 0)
C? & call ems_wr_inv_da(inv_log_msk, ds, is)
CM ENDIF
p_hdl_eta_grp = p_ml_bs_blk + (cu_ml_n-1)*ml_bs_blk_n_wo +
& ml_bs_blk_os_hdl + ix_eta_fi_hdl + (eta_fi_n_grp-1)*hdl_z
call ems_mem_mgr_g_p4(mem_mgr_rt_cod, is,
& is(p_hdl_eta_grp), p_eta_grp)
if (mem_mgr_rt_cod .ne. mem_mgr_rt_cod_ok) goto 8800
eta_fi_n_inv_grp = eta_fi_n_grp
eta_fi_n_inv_se = eta_fi_n_se
eta_fi_n_inv_eta = eta_fi_n_eta
eta_fi_n_inv_v = eta_fi_n_v
eta_fi_n_inv_ix = eta_fi_n_ix
if (av_eta_dse .lt. zero) then
av_eta_dse = float(n_a_el)/(float(n_r)*float(n_c))
if (eta_fi_n_inv_eta .gt. 0) then
v = float(eta_fi_n_inv_ix)/float(n_r*eta_fi_n_inv_eta)
av_eta_dse = max(av_eta_dse, v)
endif
endif
bs_mtx_n_a_en =
& ems_g_bs_mtx_n_a_en(is(p_vr_in_r), is(p_mtx_c_sa))
CM IF (emsol_dev .EQ. 1) THEN
CM IF (emsol_epc .EQ. 1) THEN
C?c
C?c Have to use a function compiled without unassigned variable
C?c checking in order to test values which may be unassigned.
C?c
C? if (ems_i1_eq_i2(ca_iz_mo_rsmi_fg1, ca_iz_mo_rsmi_fg2))
CM ELSE
C? if (ca_iz_mo_rsmi_fg1 .eq. ca_iz_mo_rsmi_fg2)
CM ENDIF
C? & call ems_iz_mo_rsmi(11, 2, 0)
C? call ems_mo_rsmi_inv(n_si_it, rq_inv,
C? & eta_fi_n_eta, eta_fi_n_ix, av_eta_dse,
C? & pre_eta_fi_n_eta, pre_eta_fi_n_ix, bs_mtx_n_a_en)
CM ENDIF
c
c If the maximum number of updates has increased then re-allocate
c the space for any dense data structures used for UPDATE.
c
mx_n_u = usr_mx_n_u
if (u_bs_mode .eq. u_bs_pf_r_cp) then
c
c Take a copy of u_bs_mode:
c u_bs may be changed by RSMI
c u_bs_mode may be changed by the user
c
u_bs = u_bs_mode
if (iand(ml_blk_st_msk, ml_blk_st_ml_u_bs) .ne. 0) then
if (mx_n_u .gt. is(p_u_bs_skt_pv_r)) then
c
c Remove the dense block if the user has pushed up the reinversion
c frequency.
c
call ems_rm_blk_ml_u_bs(is)
if (ems_msg_cod .ge. ems_msg_lvl_serious) goto 7000
endif
endif
c
c NB Don't combine these IF statements: ems_rm_blk_ml_u_bs will
c change iand(ml_blk_st_msk, ml_blk_st_ml_u_bs)
c
if (iand(ml_blk_st_msk, ml_blk_st_ml_u_bs) .eq. 0) then
c
c Allocate space for the dense block if it does not exist.
c
call ems_iz_blk_ml_u_bs(is)
if (ems_msg_cod .ge. ems_msg_lvl_serious) goto 7000
endif
endif
c if (ems_rq_nw_u_eta_grp(is(p_eta_grp))) then
c
c Open an eta group for updates if there is not enough space in the
c group declared for INVERT.
c
p_hdl_eta_grp = p_hdl_eta_grp + hdl_z
call ems_ope_u_eta_grp(is(p_hdl_eta_grp), ds, is)
if (ems_msg_cod .ge. ems_msg_lvl_serious) go to 7000
eta_fi_n_grp = eta_fi_n_grp + 1
c endif
call ems_g_inv_p(rt_cod, is)
if (rt_cod .ne. 0) goto 8020
CM IF (emsol_da .EQ. 1) THEN
C?c if (n_r .gt. 40000)
C?c & call ems_wr_eta_grp_n_wo(is(p_hdl_eta_grp), is)
CM ENDIF
c
c Maybe write a log line reporting on the INVERT.
c
if (iand(rsmi_msg_msk, rsmi_inv_li_bt) .ne. 0)
& call ems_wr_rsmi_lg_li(rsmi_lg_li_mode_inv, ds, is)
rq_inv = rq_inv_no_rq_inv
ml_da_st_msk = ior(ml_da_st_msk, ml_da_st_inv)
c
c Indicate that the indices of the new eta are not known. With
c steepest edge, the pivotal column needs to be zeroed after an
c INVERT following the detection in cz_r of potential growth.
c
nw_eta_l_ix = n_r+1
7000 continue
7100 continue
return
8800 continue
ems_msg_cod = ems_msg_lvl_serious
goto 7100
8020 continue
if (ems_msg_no_prt_fm .ge. 1) write(ems_li, 9802)
call ems_msg_wr_li(bug_msg_n)
goto 7000
9802 format('Error in ems_g_inv_p')
end
C->>> -------------------------------------------> ems_un_bd_aux_sol <<<
c Put the ray of unboundedness into the auxiliary solve region.
c ?? Implications when solving DUAL
c
subroutine ems_un_bd_aux_sol(
& vr_in_r, nw_eta_v, nw_eta_ix, r_aux_sol, c_aux_sol)
implicit none
include 'EMSV.INC'
include 'EMSPM.INC'
include 'RSMICOM.INC'
include 'ICTVR.INC'
integer vr_in_r(0:n_r), nw_eta_ix(0:nw_eta_l_ix)
double precision nw_eta_v(0:n_r)
double precision r_aux_sol(0:n_r), c_aux_sol(0:n_c)
integer ix_n, r_n, c_n, vr_n
do 10, r_n = 1, n_r
r_aux_sol(r_n) = zero
10 continue
do 20, c_n = 1, n_c
c_aux_sol(c_n) = zero
20 continue
do 30, ix_n = nw_eta_l_ix, nw_eta_f_ix, -1
vr_n = vr_in_r(nw_eta_ix(ix_n))
if (vr_n .gt. mx_n_c) then
r_aux_sol(vr_n-mx_n_c) = mv_dir*nw_eta_v(ix_n)
else
c_aux_sol(vr_n) = mv_dir*nw_eta_v(ix_n)
endif
30 continue
return
end
C->>> ------------------------------------------------> ems_u_pr_act <<<
subroutine ems_u_pr_act(
& nw_eta_sgn,
& pr_act,
& vr_in_r,
& nw_eta_v,
& nw_eta_ix)
implicit none
include 'EMSV.INC'
include 'EMSPM.INC'
include 'ICTVR.INC'
include 'RLCTVR.INC'
include 'RSMICS.INC'
include 'RSMICOM.INC'
CM IF (emsol_da .EQ. 1) THEN
C? include 'EMSDA.INC'
CM ENDIF
CM IF (emsol_tt .EQ. 1) THEN
C? include 'EMSTT.INC'
CM ENDIF
integer nw_eta_sgn
integer vr_in_r(0:n_r), nw_eta_ix(0:nw_eta_l_ix)
double precision pr_act(0:mx_n_c+n_r)
double precision nw_eta_v(0:n_r)
integer vr_n, ix_n
double precision mu
if (aa .eq. zero) goto 7000
CM IF (emsol_tt .EQ. 1) THEN
C? if (ems_tt_u_lvl1) call ems_tt_rec(u_rhs_tt, n_bs)
CM ENDIF
pr_act(vr_t_en_bs) = pr_act(vr_t_en_bs) + aa
mu = nw_eta_sgn*aa
do 10, ix_n = nw_eta_f_ix, nw_eta_l_ix
vr_n = vr_in_r(nw_eta_ix(ix_n))
pr_act(vr_n) = pr_act(vr_n) + mu*nw_eta_v(ix_n)
10 continue
CM IF (emsol_tt .EQ. 1) THEN
C? if (ems_tt_u_lvl1) call ems_tt_rec(-u_rhs_tt, n_bs)
CM ENDIF
7000 continue
return
end
C->>> --------------------------------------------------> ems_cz_1_c <<<
c Returns the best candidate variable from the set of candidates.
c If bst_vr_n = 0 then none of the candidates is attractive.
c
subroutine ems_cz_1_c(vr_in_c, ds, is)
implicit none
include 'EMSV.INC'
include 'EMSPM.INC'
include 'EMSMMGR.INC'
include 'EMSMEM.INC'
include 'EMSP.INC'
include 'RSMICS.INC'
include 'RSMICOM.INC'
include 'ICTVR.INC'
include 'EMSMSG.INC'
include 'RLCTVR.INC'
CM IF (emsol_tt .EQ. 1) THEN
C? include 'EMSTT.INC'
CM ENDIF
include 'EMSRTCOD.INC'
integer vr_in_c(-vr_in_c_n_sn:n_c)
double precision ds(0:ds_n_en_m1)
integer is(0:is_n_en_m1)
integer vr_n
double precision vr_du_act
integer bp_swp_sd, en_c_n, en_sn_n, vr_st
logical ab_t_bw
integer ems_rt_cod, ca_ems_rt_cod
CM IF (emsol_tt .EQ. 1) THEN
C? if (ems_tt_cz_c_lvl0) call ems_tt_rec(cz_c_tt, n_bs)
CM ENDIF
nx_vr_t_en_bs = 0
bp_swp_sd = 0
if (pc_alg .eq. pc_alg_sed) then
call ems_sq_ed_wt_cz_1_c(
& bp_swp_sd, en_c_n, en_sn_n,
& ds(p_rsmi_lb), ds(p_rsmi_ub), is(p_st),
& vr_in_c, ds(p_du_act), ds(p_ed_wt))
else if (pc_alg .eq. pc_alg_exact_dvx .or.
& pc_alg .eq. pc_alg_approx_dvx) then
call ems_ed_wt_cz_1_c(
& bp_swp_sd, en_c_n, en_sn_n,
& ds(p_rsmi_lb), ds(p_rsmi_ub), is(p_st),
& vr_in_c, ds(p_du_act), ds(p_ed_wt))
else
call ems_dan_cz_1_c(
& bp_swp_sd, en_c_n, en_sn_n,
& ds(p_rsmi_lb), ds(p_rsmi_ub), is(p_st),
& vr_in_c, ds(p_du_act))
endif
if (ems_msg_cod .ge. ems_msg_lvl_serious) goto 7000
if (nx_vr_t_en_bs .gt. 0) then
c
c Get the basis change section for the entering variable.
c
call ems_g_bs_cg_st(ca_ems_rt_cod, 0, nx_vr_t_en_bs,
& is(p_st+nx_vr_t_en_bs),
& vr_in_c,
& en_vr_fm_bs_cg_st)
if (ca_ems_rt_cod .ne. ems_rt_cod_ok) then
ems_rt_cod = max(ca_ems_rt_cod, ems_rt_cod)
c if (ems_rt_cod .ge. ems_rt_lvl_serious) goto 7100
if (ems_rt_cod .ge. ems_rt_lvl_serious) goto 8950
endif
endif
c
c Determine whether a variable has been chosen so that it breaks
c through its bound.
c
en_vr_bk_bd = 0
if (nx_vr_t_en_bs .gt. 0) then
vr_n = nx_vr_t_en_bs
vr_st = is(p_st+vr_n)
if (iand(vr_st, alt_bt) .ne. 0 .and. bp_swp_sd .ne. 0) then
ab_t_bw = bp_swp_sd .eq. -1
call ems_bp_swp_sd(
& ab_t_bw, vr_n, en_c_n, en_sn_n,
& ds(p_rsmi_lb+vr_n),
& ds(p_rsmi_co+vr_n),
& ds(p_rsmi_ub+vr_n),
& ds(p_du_act+vr_n),
& is(p_st), vr_in_c)
else if (lp_ph .eq. 1 .and.
& iand(cz_c_msk, cz_c_bk_bd_bt) .ne. 0) then
vr_du_act = ds(p_du_act+vr_n)
if (iand(vr_st, up_bt) .ne. 0) then
c
c Identify whether the entering variable is breaking through its
c lower bound.
c
if (vr_du_act .gt. zero) en_vr_bk_bd = -1
else if (iand(vr_st, dn_bt) .ne. 0) then
c
c Identify whether the entering variable is breaking through its
c upper bound.
c
if (vr_du_act .lt. zero) en_vr_bk_bd = 1
else
c
c Identify which way the entering variable is moving from a fixed
c value.
c
if (vr_du_act .gt. zero) then
en_vr_bk_bd = -1
else
en_vr_bk_bd = 1
endif
endif
endif
endif
c
c Indicate that CHUZC has been performed with the current dual
c activities and bounds on non-basic variables.
c
rsmi_op_st_msk = ior(rsmi_op_st_msk, rsmi_op_st_cz_c)
7000 continue
7100 continue
CM IF (emsol_tt .EQ. 1) THEN
C? if (ems_tt_cz_c_lvl0) call ems_tt_rec(-cz_c_tt, n_bs)
CM ENDIF
return
8950 continue
ems_msg_cod = max(ems_msg_lvl_serious, ems_msg_cod)
goto 7100
end
C->>> -------------------------------------------> ems_wr_rsmi_lg_li <<<
c Write out a log line. Only local values of objective value and
c number/sum of primal/dual infeasibilities are calculated so that
c the global values are not affected by a call to this routine.
c
subroutine ems_wr_rsmi_lg_li(rsmi_lg_li_mode, ds, is)
implicit none
include 'EMSV.INC'
include 'EMSPM.INC'
include 'EMSMMGR.INC'
include 'EMSMEM.INC'
include 'EMSP.INC'
include 'RSMICS.INC'
include 'RSMIHDL.INC'
include 'RSMICOM.INC'
include 'ICTVR.INC'
include 'RLCTVR.INC'
include 'EMSMSG.INC'
integer rsmi_lg_li_mode, is(0:is_n_en_m1)
double precision ds(0:ds_n_en_m1)
integer lc_n_pr_ifs, lc_n_du_ifs
double precision lc_ob_fn_v
double precision lc_su_pr_ifs, mx_pr_ifs, mx_rlv_pr_ifs
double precision lc_su_du_ifs, mx_du_ifs, mx_rlv_du_ifs
if (rsmi_msg_msk .eq. 0) goto 7000
call ems_ca_g_ml_ob_fn_v(
& lc_ob_fn_v, ds, is)
call ems_ca_g_n_su_mx_pr_ifs(
& lc_n_pr_ifs, lc_su_pr_ifs, mx_pr_ifs, mx_rlv_pr_ifs,
& ds, is)
call ems_ca_g_n_su_mx_du_ifs(
& lc_n_du_ifs, lc_su_du_ifs, mx_du_ifs, mx_rlv_du_ifs,
& ds, is)
if (rsmi_lg_li_mode .eq. rsmi_lg_li_mode_fq) then
if (iand(rsmi_msg_msk, rsmi_pv_li_bt) .ne. 0) then
if (vr_t_lv_bs .ne. vr_t_en_bs) then
if (ems_msg_no_prt_fm .ge. 1) write(ems_li, 9300)
& n_si_it, lc_ob_fn_v,
& lc_su_pr_ifs, lc_n_pr_ifs,
& lc_su_du_ifs, lc_n_du_ifs,
& du_act_o_vr_t_en_bs, vr_t_en_bs, aa, vr_t_lv_bs, pv
else
if (ems_msg_no_prt_fm .ge. 1) write(ems_li, 9300)
& n_si_it, lc_ob_fn_v,
& lc_su_pr_ifs, lc_n_pr_ifs,
& lc_su_du_ifs, lc_n_du_ifs,
& du_act_o_vr_t_en_bs, vr_t_en_bs, aa
endif
else
if (ems_msg_no_prt_fm .ge. 1) write(ems_li, 9300)
& n_si_it, lc_ob_fn_v,
& lc_su_pr_ifs, lc_n_pr_ifs,
& lc_su_du_ifs, lc_n_du_ifs
endif
else if (rsmi_lg_li_mode .eq. rsmi_lg_li_mode_inv) then
if (ems_msg_no_prt_fm .ge. 1) write(ems_li, 9300)
& n_si_it, lc_ob_fn_v,
& lc_su_pr_ifs, lc_n_pr_ifs,
& lc_su_du_ifs, lc_n_du_ifs
else if (rsmi_lg_li_mode .eq. rsmi_lg_li_mode_dvx) then
if (ems_msg_no_prt_fm .ge. 1) write(ems_li, 9320)
& n_si_it, lc_ob_fn_v,
& lc_su_pr_ifs, lc_n_pr_ifs,
& lc_su_du_ifs, lc_n_du_ifs,
& n_dvx_it
else if (rsmi_lg_li_mode .eq. rsmi_lg_li_mode_reset) then
if (ems_msg_no_prt_fm .ge. 1) write(ems_li, 9330)
& n_si_it, lc_ob_fn_v,
& lc_su_pr_ifs, lc_n_pr_ifs,
& lc_su_du_ifs, lc_n_du_ifs,
& eta_fi_n_eta, eta_fi_n_ix,
& n_reset
endif
call ems_msg_wr_li(80)
call ems_flush(ems_wr_cn)
7000 continue
return
9300 format(i7, 1x, g15.8, 2x, 2(1x, g11.4, '(', i7, ')'),
& 2(1x, g11.4, 2x, i7), 1x, g11.4)
9320 format(i7, 1x, g15.8, 2x, 2(1x, g11.4, '(', i7, ')'),
& ': Number of Devex iterations = ', i5)
9330 format(i7, 1x, g15.8, 2x, 2(1x, g11.4, '(', i7, ')'),
& ': Eta file (', i7, ', ', i9, '): Reset ', i5)
end
integer function ems_g_bs_mtx_n_a_en(vr_in_r, mtx_c_sa)
implicit none
include 'EMSV.INC'
include 'EMSPM.INC'
include 'ICTVR.INC'
integer vr_in_r(0:n_r)
integer mtx_c_sa(0:n_c+1)
integer r_n, vr_n
integer bs_mtx_n_a_en
bs_mtx_n_a_en = 0
do 10, r_n = 1, n_r
vr_n = vr_in_r(r_n)
if (vr_n .le. n_c) bs_mtx_n_a_en =
& bs_mtx_n_a_en + mtx_c_sa(vr_n+1) - mtx_c_sa(vr_n)
10 continue
ems_g_bs_mtx_n_a_en = bs_mtx_n_a_en
return
end
double precision function ems_g_ml_ob_fn_v(
& st,
& rsmi_lb,
& rsmi_co,
& rsmi_ub,
& pr_act, ds, is)
implicit none
include 'EMSV.INC'
include 'EMSPM.INC'
include 'ICTVR.INC'
include 'RLCTVR.INC'
integer st(0:mx_n_c+n_r)
integer is(0:is_n_en_m1)
double precision rsmi_lb(0:mx_n_c+n_r)
double precision rsmi_co(0:mx_n_c+n_r)
double precision rsmi_ub(0:mx_n_c+n_r)
double precision pr_act(0:mx_n_c+n_r)
double precision ds(0:ds_n_en_m1)
double precision ems_scpr
integer ix_n, vr_n, vr_st
double precision ml_ob_fn_v
c write(*, *)
c write(*, *)'Analysing the function evaluation:'
if (iand(ml_da_st_msk, ml_da_st_alt_lp) .eq. 0) then
ml_ob_fn_v = ems_scpr(ob_fn_cs, rsmi_co, pr_act, n_c)
ml_ob_fn_v = ems_scpr(ml_ob_fn_v,
& rsmi_co(mx_n_c), pr_act(mx_n_c), n_r)
c ml_ob_fn_v = ob_fn_cs
c mx_x = 0d0
c mx_c = 0d0
c mx_dl_f = 0d0
c mx_f = 0d0
c do 1, ix_n = 1, n_c+n_r
c if (ix_n .le. n_c) then
c vr_n = ix_n
c else
c vr_n = (mx_n_c-n_c) + ix_n
c endif
c ml_ob_fn_v = ml_ob_fn_v + rsmi_co(vr_n)*pr_act(vr_n)
c dl_f = pr_act(vr_n)*rsmi_co(vr_n)
c if (abs(dl_f) .gt. zero) then
c if (iand(st(vr_n), bc_bt) .ne. 0) then
c ch8 = ' Basic'
c else
c ch8 = 'NonBasic'
c endif
c write(*, 9000) ch8, ix_n,
c & pr_act(vr_n), rsmi_co(vr_n), dl_f, ml_ob_fn_v
c mx_x = max(abs(pr_act(vr_n)), mx_x)
c mx_c = max(abs(rsmi_co(vr_n)), mx_c)
c mx_dl_f = max(abs(dl_f), mx_dl_f)
c mx_f = max(abs(ml_ob_fn_v), mx_f)
c endif
c 1 continue
c write(*, 9000)' ', -1, mx_x, mx_c, mx_dl_f, mx_f
goto 7000
endif
ml_ob_fn_v = ob_fn_cs
do 10, ix_n = 1, n_c+n_r
if (ix_n .le. n_c) then
vr_n = ix_n
else
vr_n = (mx_n_c-n_c) + ix_n
endif
vr_st = st(vr_n)
if (iand(vr_st, alt_bt) .eq. 0) then
ml_ob_fn_v = ml_ob_fn_v + rsmi_co(vr_n)*pr_act(vr_n)
else if (iand(vr_st, bp_bt) .ne. 0) then
if (iand(vr_st, lb_bt) .ne. 0) then
ml_ob_fn_v = ml_ob_fn_v +
& rsmi_co(vr_n)*(pr_act(vr_n)-rsmi_lb(vr_n))
else
ml_ob_fn_v = ml_ob_fn_v +
& rsmi_co(vr_n)*(pr_act(vr_n)-rsmi_ub(vr_n))
endif
else
endif
10 continue
7000 continue
ems_g_ml_ob_fn_v = ml_ob_fn_v
return
c 9000 format(a8, i5, 4(2x, g11.4))
end
C->>> ----------------------------------------------> ems_u_ml_bs_cg <<<
c A black box shell for u_bs_cg.
c
subroutine ems_u_ml_bs_cg(ds, is)
implicit none
include 'EMSV.INC'
include 'EMSPM.INC'
include 'EMSMMGR.INC'
include 'EMSMEM.INC'
include 'EMSP.INC'
include 'ICTVR.INC'
integer is(0:is_n_en_m1)
double precision ds(0:ds_n_en_m1)
call ems_u_bs_cg(is(p_st), is(p_vr_in_r), ds, is)
return
end
C->>> -------------------------------------------------> ems_u_bs_cg <<<
c Resolve any undresolved basis changes.
c
subroutine ems_u_bs_cg(st, vr_in_r, ds, is)
implicit none
include 'EMSV.INC'
include 'EMSPM.INC'
include 'EMSMMGR.INC'
include 'EMSMEM.INC'
include 'EMSP.INC'
include 'RSMICS.INC'
CM IF (emsol_da .EQ. 1) THEN
C? include 'EMSDA.INC'
CM ENDIF
include 'RSMICOM.INC'
include 'ICTVR.INC'
include 'RLCTVR.INC'
include 'EMSMSG.INC'
include 'EMSRTCOD.INC'
integer ems_rt_cod
double precision ds(0:ds_n_en_m1)
integer st(0:mx_n_c+n_r), vr_in_r(0:n_r)
integer is(0:is_n_en_m1)
integer lv_vr_ix, en_vr_ix, lv_vr_n, en_vr_n
integer ca_ems_rt_cod
integer lc_st
ems_rt_cod = ems_rt_cod_ok
if (u_bs_cg .eq. 0) goto 7000
en_vr_ix = 0
c
c Look for a variable which has the u_bs_cg bit set and is nonbasic.
c
do 40, lv_vr_ix = 1, n_r+n_c
if (lv_vr_ix .le. n_c) then
lv_vr_n = lv_vr_ix
else
lv_vr_n = lv_vr_ix + mx_n_c - n_c
endif
if (iand(st(lv_vr_n), u_bs_cg_bt) .ne. 0 .and.
& iand(st(lv_vr_n), bc_bt) .eq. 0) then
c
c Look for a variable which has the u_bs_cg bit set and is basic.
c
do 20, en_vr_ix = en_vr_ix+1, n_r+n_c
if (en_vr_ix .le. n_c) then
en_vr_n = en_vr_ix
else
en_vr_n = en_vr_ix + mx_n_c - n_c
endif
if (iand(st(en_vr_n), u_bs_cg_bt) .ne. 0 .and.
& iand(st(en_vr_n), bc_bt) .ne. 0) goto 30
20 continue
goto 8010
30 continue
CM IF (emsol_da .EQ. 1) THEN
C? n_sing_bs_cg = n_sing_bs_cg + 1
CM ENDIF
if (ems_msg_no_prt_fm .ge. 1) write(ems_li, 9000)
& en_vr_n, lv_vr_n
call ems_msg_wr_li(info_msg_n)
st(lv_vr_n) = st(lv_vr_n) - u_bs_cg_bt
st(en_vr_n) = st(en_vr_n) - u_bs_cg_bt
c
c Get the basis change sections for the entering variables
c
c Because the entering variable is already in vr_in_r, its status
c is already basic and the index stored within the status points
c into vr_in_r. However, to get ems_g_bs_cg_st to treat the variable
c as nonbasic, the basic bit is removed from a copy of the status.
c ems_og_g_bs_cg_st finds the variable in vr_in_c by searching.
c
lc_st = st(en_vr_n) - iand(st(en_vr_n), bc_bt)
c call ems_og_g_bs_cg_st(ca_ems_rt_cod, 1, en_vr_n,
c & lc_st,
c & ds(p_pr_act+en_vr_n),
c & ds(p_rsmi_lb+en_vr_n),
c & ds(p_rsmi_ub+en_vr_n),
c & en_vr_fm_bs_cg_st)
call ems_g_bs_cg_st(ca_ems_rt_cod, 1, en_vr_n,
& lc_st,
& is(p_vr_in_c),
& en_vr_fm_bs_cg_st)
if (ca_ems_rt_cod .ne. ems_rt_cod_ok) then
ems_rt_cod = max(ca_ems_rt_cod, ems_rt_cod)
if (ems_rt_cod .ge. ems_rt_lvl_serious) goto 7100
endif
call ems_u_vr_in_r(
& en_vr_n, lv_vr_n, is(p_st), is(p_vr_in_r))
endif
40 continue
c
c Look for any more variables which have the u_bs_cg bit set.
c
do 110, en_vr_ix = en_vr_ix+1, n_r+n_c
if (en_vr_ix .le. n_c) then
en_vr_n = en_vr_ix
else
en_vr_n = en_vr_ix + mx_n_c - n_c
endif
if (iand(st(lv_vr_n), u_bs_cg_bt) .ne. 0) goto 8020
110 continue
u_bs_cg = 0
7000 continue
7100 continue
return
8010 continue
if (ems_msg_no_prt_fm .ge. 1) write(ems_li, 9801)lv_vr_n
call ems_msg_wr_li(bug_msg_n)
goto 7000
8020 continue
if (ems_msg_no_prt_fm .ge. 1) write(ems_li, 9802)en_vr_n
call ems_msg_wr_li(bug_msg_n)
goto 7000
9000 format('Resolved basis change: ', i7, ' replaces ', i7)
9801 format('No unresolved basic variable for nonbasic variable ', i7)
9802 format('No unresolved nonbasic variable for basic variable ', i7)
end
C->>> ------------------------------------------------> ems_ml_bs_cg <<<
c A black box shell for u_vr_in_r.
c
subroutine ems_ml_bs_cg(lc_vr_t_en_bs, lc_vr_t_lv_bs, ds, is)
implicit none
include 'EMSV.INC'
include 'EMSPM.INC'
include 'EMSMMGR.INC'
include 'EMSMEM.INC'
include 'EMSP.INC'
include 'ICTVR.INC'
integer lc_vr_t_en_bs, lc_vr_t_lv_bs, is(0:is_n_en_m1)
double precision ds(0:ds_n_en_m1)
call ems_u_vr_in_r(
& lc_vr_t_en_bs, lc_vr_t_lv_bs, is(p_st), is(p_vr_in_r))
return
end
C->>> -----------------------------------------------> ems_u_vr_in_r <<<
c If lc_vr_t_en_bs=0 or lc_vr_t_lv_bs=0 then just set/unset the
c basic bit.
c Update vr_in_r corresponding to lc_vr_t_en_bs and lc_vr_t_lv_bs,
c maintaining the cross-referencing information in the status
c vector.
c
subroutine ems_u_vr_in_r(
& lc_vr_t_en_bs, lc_vr_t_lv_bs, st, vr_in_r)
implicit none
include 'EMSV.INC'
include 'EMSPM.INC'
include 'EMSMSG.INC'
include 'EMSRTCOD.INC'
include 'RSMICOM.INC'
include 'RSMICS.INC'
include 'ICTVR.INC'
CM IF (emsol_tt .EQ. 1) THEN
C? include 'EMSTT.INC'
CM ENDIF
integer ems_rt_cod
integer st(0:mx_n_c+n_r)
integer vr_in_r(0:n_r)
integer lc_vr_t_en_bs, lc_vr_t_lv_bs
integer ca_ems_rt_cod
CM IF (emsol_tt .EQ. 1) THEN
C? if (ems_tt_u_lvl1) call ems_tt_rec(u_vr_in_r_tt, n_bs)
CM ENDIF
ems_rt_cod = ems_rt_cod_ok
c
c Ensure that the basic bit is set for the entering variable.
c
if (lc_vr_t_en_bs .gt. 0) then
st(lc_vr_t_en_bs) = ior(st(lc_vr_t_en_bs), bc_bt)
endif
c
c Ensure that the basic bit is not set for the leaving variable.
c
if (lc_vr_t_lv_bs .gt. 0) then
st(lc_vr_t_lv_bs) =
& st(lc_vr_t_lv_bs) - iand(st(lc_vr_t_lv_bs), bc_bt)
endif
c
c If a variable is entering/leaving the basis but there is nothing
c to remove/replace it. Set a flag to indicate that such anomalies
c must be resolved and put a marker on each such variable.
c
if (lc_vr_t_en_bs .le. 0 .or. lc_vr_t_lv_bs .le. 0) then
if (lc_vr_t_en_bs .gt. 0)
& st(lc_vr_t_en_bs) = st(lc_vr_t_en_bs) -
& iand(st(lc_vr_t_en_bs), u_bs_cg_bt) + u_bs_cg_bt
if (lc_vr_t_lv_bs .gt. 0)
& st(lc_vr_t_lv_bs) = st(lc_vr_t_lv_bs) -
& iand(st(lc_vr_t_lv_bs), u_bs_cg_bt) + u_bs_cg_bt
u_bs_cg = 1
goto 7000
endif
c
c Save the basis change so that reset loops can be detected.
c
call ems_sv_bs_cg(ca_ems_rt_cod,
& lc_vr_t_en_bs, lc_vr_t_lv_bs,
& en_vr_fm_bs_cg_st, bs_cg_st_bc)
if (ca_ems_rt_cod .ne. ems_rt_cod_ok) then
ems_rt_cod = max(ca_ems_rt_cod, ems_rt_cod)
c if (ems_rt_cod .ge. ems_rt_lvl_serious) goto 7100
if (ems_rt_cod .ge. ems_rt_lvl_serious) goto 8950
endif
c
c Get pv_c_n and pv_r_n from the corresponding statuses.
c
pv_c_n = iand(st(lc_vr_t_en_bs), mx_mx_ml_a_dim)
if (lc_vr_t_lv_bs .ne. lc_vr_t_en_bs) then
pv_r_n = iand(st(lc_vr_t_lv_bs), mx_mx_ml_a_dim)
c
c Update the record of which variable is solved for in which row.
c
vr_in_r(pv_r_n) = lc_vr_t_en_bs
st(lc_vr_t_en_bs) = st(lc_vr_t_en_bs) -
& iand(st(lc_vr_t_en_bs), mx_mx_ml_a_dim) + pv_r_n
else
pv_r_n = 0
endif
7000 continue
7100 continue
CM IF (emsol_tt .EQ. 1) THEN
C? if (ems_tt_u_lvl1) call ems_tt_rec(-u_vr_in_r_tt, n_bs)
CM ENDIF
return
8950 continue
ems_msg_cod = ems_msg_lvl_serious
goto 7100
end
C->>> -------------------------------------------------> ems_u_bc_co <<<
c Update the costs of the basic variables.
c
subroutine ems_u_bc_co(
& rsmi_lb,
& rsmi_ub,
& st,
& rsmi_co,
& pr_act,
& vr_in_r,
& bc_co_v,
& bc_co_ix,
& bc_co_ix_bar,
& pi_v,
& pi_ix,
& du_act,
& cdd_r,
& vr_in_c,
& ds, is)
implicit none
include 'EMSV.INC'
include 'EMSPM.INC'
include 'EMSMMGR.INC'
include 'EMSMEM.INC'
include 'EMSP.INC'
include 'RSMICOM.INC'
include 'ICTVR.INC'
include 'EMSMSG.INC'
include 'RLCTVR.INC'
CM IF (emsol_tt .EQ. 1) THEN
C? include 'EMSTT.INC'
CM ENDIF
integer bc_co_ix(0:n_r)
integer bc_co_ix_bar(0:n_r)
integer pi_ix(0:n_r)
integer st(0:mx_n_c+n_r), vr_in_r(0:n_r)
integer cdd_r(0:n_r)
integer vr_in_c(*), is(0:is_n_en_m1)