mgmg 1.7.0 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/lib/mgmg/option.rb +6 -6
- data/lib/mgmg/search.rb +39 -169
- data/lib/mgmg/version.rb +1 -1
- data/reference.md +5 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 79211ca6cd5422500f7dc957eadfb2c1812459c98fd39b84fc9a3ebf178174ec
|
4
|
+
data.tar.gz: efa0254194363114aee22993e78cab9359e9a7c92f454d5fffc12b1d14368e6c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 822a754eeeec7b9b9e8d6f1497041c153a56b62d190da8101f798e9b78334cc64406f35167623387c346b9f2453027a7e17a3ebaefc2ec4d38cbfcbe381b01e6
|
7
|
+
data.tar.gz: f43028c621ea4025123c1ca338f46c8965d545a8f6a92569cc5bb7f5279d11ea01be0dbe6453c1ffe06c831c55be1cdf439ed66b81fa8e08a4d01ac994348e5f
|
data/CHANGELOG.md
CHANGED
@@ -184,3 +184,8 @@
|
|
184
184
|
- `Mgmg.#find_upperbound`のアルゴリズムに誤りがあり,大きく間違えた解を返していた問題を修正.
|
185
185
|
- `Mgmg::IR#attack`等において,引数が`nil`(製作Lvを指定せず,多項式を返す)の場合に,例外となっていたバグを修正.
|
186
186
|
- オブション`smith/armor/comp_max`のデフォルト値を10^9に変更.
|
187
|
+
|
188
|
+
## 1.8.0 2022/11/14
|
189
|
+
- オプション`comp_ext`を`fib_ext`に変更し,追加探索の範囲を修正.
|
190
|
+
- オプション`smith/armor/comp_max`の扱い方を修正し,デフォルト値を10^5に変更.
|
191
|
+
- `Enumerable#find_max`,`Mgmg.#find_lowerbound`のバグを修正.
|
data/lib/mgmg/option.rb
CHANGED
@@ -2,13 +2,13 @@ module Mgmg
|
|
2
2
|
class Option
|
3
3
|
Defaults = {
|
4
4
|
left_associative: true, include_system_equips: true,
|
5
|
-
smith_max:
|
6
|
-
|
5
|
+
smith_max: 100_000, armor_max: 100_000, comp_max: 100_000,
|
6
|
+
fib_ext: [4, 10]
|
7
7
|
}
|
8
8
|
def initialize(
|
9
9
|
left_associative: Defaults[:left_associative],
|
10
10
|
smith_min: nil, armor_min:nil, comp_min: nil, smith_max: Defaults[:smith_max], armor_max: Defaults[:armor_max], comp_max: Defaults[:comp_max],
|
11
|
-
|
11
|
+
fib_ext: Defaults[:fib_ext],
|
12
12
|
magdef_maximize: true,
|
13
13
|
target_weight: 0, reinforcement: [], buff: nil,
|
14
14
|
irep: nil, cut_exp: Float::INFINITY,
|
@@ -21,7 +21,7 @@ module Mgmg
|
|
21
21
|
@smith_max = smith_max
|
22
22
|
@armor_max = armor_max
|
23
23
|
@comp_max = comp_max
|
24
|
-
@
|
24
|
+
@fib_ext = fib_ext
|
25
25
|
@magdef_maximize = magdef_maximize
|
26
26
|
@target_weight = target_weight
|
27
27
|
@reinforcement = reinforcement
|
@@ -37,7 +37,7 @@ module Mgmg
|
|
37
37
|
@include_system_equips = include_system_equips
|
38
38
|
@system_equips_checked = false
|
39
39
|
end
|
40
|
-
attr_accessor :left_associative, :smith_min, :armor_min, :comp_min, :smith_max, :armor_max, :comp_max, :
|
40
|
+
attr_accessor :left_associative, :smith_min, :armor_min, :comp_min, :smith_max, :armor_max, :comp_max, :fib_ext
|
41
41
|
attr_accessor :magdef_maximize, :target_weight, :reinforcement, :irep, :cut_exp, :include_system_equips, :system_equips_checked
|
42
42
|
def initialize_copy(other)
|
43
43
|
@left_associative = other.left_associative
|
@@ -47,7 +47,7 @@ module Mgmg
|
|
47
47
|
@smith_max = other.smith_max
|
48
48
|
@armor_max = other.armor_max
|
49
49
|
@comp_max = other.comp_max
|
50
|
-
@
|
50
|
+
@fib_ext = other.fib_ext.dup
|
51
51
|
@magdef_maximize = other.magdef_maximize
|
52
52
|
@target_weight = other.target_weight
|
53
53
|
@reinforcement = other.reinforcement.dup
|
data/lib/mgmg/search.rb
CHANGED
@@ -34,7 +34,7 @@ class String
|
|
34
34
|
if target <= opt.irep.para_call(para, smith, opt.comp_min)
|
35
35
|
return opt.comp_min
|
36
36
|
elsif opt.irep.para_call(para, smith, opt.comp_max) < target
|
37
|
-
raise Mgmg::SearchCutException
|
37
|
+
raise Mgmg::SearchCutException, "given comp_max=#{opt.comp_max} does not satisfies the target"
|
38
38
|
end
|
39
39
|
while 1 < opt.comp_max - opt.comp_min do
|
40
40
|
comp = (opt.comp_max - opt.comp_min).div(2) + opt.comp_min
|
@@ -71,7 +71,12 @@ class String
|
|
71
71
|
def search(para, target, opt: Mgmg::Option.new)
|
72
72
|
opt = opt.dup.set_default(self)
|
73
73
|
opt_nocut = opt.dup; opt_nocut.cut_exp = Float::INFINITY
|
74
|
-
|
74
|
+
begin
|
75
|
+
opt.comp_min = comp_search(para, target, opt.smith_max, opt:)
|
76
|
+
rescue Mgmg::SearchCutException
|
77
|
+
foo = opt.irep.para_call(para, opt.smith_max, opt.comp_max)
|
78
|
+
raise Mgmg::SearchCutException, "#{self} could not reach target=#{target} until (smith_max, comp_max)=(#{opt.smith_max}, #{opt.comp_max}), which yields #{foo.comma3}"
|
79
|
+
end
|
75
80
|
opt.smith_max = smith_search(para, target, opt.comp_min, opt: opt_nocut)
|
76
81
|
opt.smith_min = smith_search(para, target, opt.comp_max, opt: opt_nocut)
|
77
82
|
raise Mgmg::SearchCutException if opt.cut_exp < Mgmg.exp(opt.smith_min, opt.comp_min)
|
@@ -104,7 +109,8 @@ class String
|
|
104
109
|
end
|
105
110
|
end
|
106
111
|
exp_best = opt.cut_exp
|
107
|
-
|
112
|
+
diff = values.max-values.min
|
113
|
+
opt.cut_exp = exp_best + diff*opt.fib_ext[0]
|
108
114
|
(comps[0]-1).downto(opt.comp_min) do |comp|
|
109
115
|
exp_best, ret = fine(exp_best, ret, para, target, comp, opt, eo)
|
110
116
|
rescue Mgmg::SearchCutException
|
@@ -170,7 +176,8 @@ class String
|
|
170
176
|
values = [values[1], values[2], cur, values[3]]
|
171
177
|
end
|
172
178
|
end
|
173
|
-
|
179
|
+
diff = values.max-values.min
|
180
|
+
th = max - diff*opt.fib_ext[1]
|
174
181
|
(comps[0]-1).downto(opt.comp_min) do |comp|
|
175
182
|
next if ( eo & (2**(comp&1)) == 0 )
|
176
183
|
cur, smith = eval_comp_fm(para, comp, eo, opt, max, max_exp)
|
@@ -292,7 +299,7 @@ module Enumerable
|
|
292
299
|
if target <= opt.irep.para_call(para, smith, armor, opt.comp_min)
|
293
300
|
return opt.comp_min
|
294
301
|
elsif opt.irep.para_call(para, smith, armor, opt.comp_max) < target
|
295
|
-
raise
|
302
|
+
raise Mgmg::SearchCutException, "given comp_max=#{opt.comp_max} does not satisfies the target"
|
296
303
|
end
|
297
304
|
while 1 < opt.comp_max - opt.comp_min do
|
298
305
|
comp = (opt.comp_max - opt.comp_min).div(2) + opt.comp_min
|
@@ -304,152 +311,6 @@ module Enumerable
|
|
304
311
|
end
|
305
312
|
opt.comp_max
|
306
313
|
end
|
307
|
-
private def eval_comp_a(para, target, comp, opt, eo)
|
308
|
-
return [nil, Float::INFINITY] if (comp < opt.comp_min or opt.comp_max < comp)
|
309
|
-
comp -= 1 if ( opt.comp_min<comp and eo & (2**(comp&1)) == 0 )
|
310
|
-
armor = armor_search(para, target, -1, comp, opt:)
|
311
|
-
exp = Mgmg.exp(armor, comp)
|
312
|
-
[[-1, armor, comp], exp]
|
313
|
-
rescue Mgmg::SearchCutException
|
314
|
-
[nil, Float::INFINITY]
|
315
|
-
end
|
316
|
-
private def fine_a(exp_best, ret, para, target, comp, opt, eo)
|
317
|
-
return [exp_best, ret] if eo & (2**(comp&1)) == 0
|
318
|
-
armor = armor_search(para, target, -1, comp, opt:)
|
319
|
-
exp = Mgmg.exp(armor, comp)
|
320
|
-
if exp < exp_best
|
321
|
-
exp_best, ret = exp, [-1, armor, comp]
|
322
|
-
elsif exp == exp_best
|
323
|
-
if ret.nil? or opt.irep.para_call(para, *ret) < opt.irep.para_call(para, -1, armor, comp) then
|
324
|
-
ret = [-1, armor, comp]
|
325
|
-
end
|
326
|
-
end
|
327
|
-
[exp_best, ret]
|
328
|
-
end
|
329
|
-
private def search_aonly(para, target, opt: Mgmg::Option.new)
|
330
|
-
opt_nocut = opt.dup; opt_nocut.cut_exp = Float::INFINITY
|
331
|
-
opt.armor_max = armor_search(para, target, -1, opt.comp_min, opt: opt_nocut)
|
332
|
-
opt.armor_min = armor_search(para, target, -1, opt.comp_max, opt: opt_nocut)
|
333
|
-
raise Mgmg::SearchCutException if opt.cut_exp < Mgmg.exp(opt.armor_min, opt.comp_min)
|
334
|
-
opt.comp_max = comp_search(para, target, -1, opt.armor_min, opt:)
|
335
|
-
ret = nil
|
336
|
-
exp = Mgmg.exp(opt.armor_min, opt.comp_max)
|
337
|
-
opt.cut_exp, ret = exp, [-1, opt.armor_min, opt.comp_max] if exp <= opt.cut_exp
|
338
|
-
exp = Mgmg.exp(opt.armor_max, opt.comp_min)
|
339
|
-
opt.cut_exp, ret = exp, [-1, opt.armor_max, opt.comp_min] if ( exp < opt.cut_exp || (ret.nil? && exp==opt.cut_exp) )
|
340
|
-
eo = opt.irep.eo_para(para)
|
341
|
-
comps = Mgmg.fib_init(opt.comp_min, opt.comp_max)
|
342
|
-
values = comps.map do |comp|
|
343
|
-
r, e = eval_comp_a(para, target, comp, opt_nocut, eo)
|
344
|
-
opt.cut_exp, ret = e, r if e < opt.cut_exp
|
345
|
-
e
|
346
|
-
end
|
347
|
-
while 3 < comps[3]-comps[0]
|
348
|
-
if values[1] <= values[2]
|
349
|
-
comp = comps[0] + comps[2]-comps[1]
|
350
|
-
comps = [comps[0], comp, comps[1], comps[2]]
|
351
|
-
r, e = eval_comp_a(para, target, comp, opt_nocut, eo)
|
352
|
-
opt.cut_exp, ret = e, r if e < opt.cut_exp
|
353
|
-
values = [values[0], e, values[1], values[2]]
|
354
|
-
else
|
355
|
-
comp = comps[1] + comps[3]-comps[2]
|
356
|
-
comps = [comps[1], comps[2], comp, comps[3]]
|
357
|
-
r, e = eval_comp_a(para, target, comp, opt_nocut, eo)
|
358
|
-
opt.cut_exp, ret = e, r if e < opt.cut_exp
|
359
|
-
values = [values[1], values[2], e, values[3]]
|
360
|
-
end
|
361
|
-
end
|
362
|
-
exp_best = opt.cut_exp
|
363
|
-
opt.cut_exp = exp_best + (exp_best*opt.comp_ext[0]).to_i.clamp(opt.comp_ext[1], opt.comp_ext[2])
|
364
|
-
(comps[0]-1).downto(opt.comp_min) do |comp|
|
365
|
-
exp_best, ret = fine_a(exp_best, ret, para, target, comp, opt, eo)
|
366
|
-
rescue Mgmg::SearchCutException
|
367
|
-
break
|
368
|
-
end
|
369
|
-
(comps[3]+1).upto(opt.comp_max) do |comp|
|
370
|
-
exp_best, ret = fine_a(exp_best, ret, para, target, comp, opt, eo)
|
371
|
-
rescue Mgmg::SearchCutException
|
372
|
-
break
|
373
|
-
end
|
374
|
-
if ret.nil?
|
375
|
-
max = opt.irep.para_call(para, *find_max(para, opt.cut_exp, opt:))
|
376
|
-
raise Mgmg::SearchCutException, "the maximum output with given cut_exp=#{opt.cut_exp.comma3} is #{max.comma3}, which does not reach given target=#{target.comma3}"
|
377
|
-
end
|
378
|
-
ret
|
379
|
-
end
|
380
|
-
private def eval_comp_s(para, target, comp, opt, eo)
|
381
|
-
return [nil, Float::INFINITY] if (comp < opt.comp_min or opt.comp_max < comp)
|
382
|
-
comp -= 1 if ( opt.comp_min<comp and eo & (2**(comp&1)) == 0 )
|
383
|
-
smith = smith_search(para, target, -1, comp, opt:)
|
384
|
-
exp = Mgmg.exp(smith, comp)
|
385
|
-
[[smith, -1, comp], exp]
|
386
|
-
rescue Mgmg::SearchCutException
|
387
|
-
[nil, Float::INFINITY]
|
388
|
-
end
|
389
|
-
private def fine_s(exp_best, ret, para, target, comp, opt, eo)
|
390
|
-
return [exp_best, ret] if eo & (2**(comp&1)) == 0
|
391
|
-
smith = smith_search(para, target, -1, comp, opt:)
|
392
|
-
exp = Mgmg.exp(smith, comp)
|
393
|
-
if exp < exp_best
|
394
|
-
exp_best, ret = exp, [smith, -1, comp]
|
395
|
-
elsif exp == exp_best
|
396
|
-
if ret.nil? or opt.irep.para_call(para, *ret) < opt.irep.para_call(para, smith, -1, comp) then
|
397
|
-
ret = [smith, -1, comp]
|
398
|
-
end
|
399
|
-
end
|
400
|
-
[exp_best, ret]
|
401
|
-
end
|
402
|
-
private def search_sonly(para, target, opt: Mgmg::Option.new)
|
403
|
-
opt_nocut = opt.dup; opt_nocut.cut_exp = Float::INFINITY
|
404
|
-
opt.smith_max = smith_search(para, target, -1, opt.comp_min, opt: opt_nocut)
|
405
|
-
opt.smith_min = smith_search(para, target, -1, opt.comp_max, opt: opt_nocut)
|
406
|
-
raise Mgmg::SearchCutException if opt.cut_exp < Mgmg.exp(opt.smith_min, opt.comp_min)
|
407
|
-
opt.comp_max = comp_search(para, target, opt.smith_min, -1, opt:)
|
408
|
-
ret = nil
|
409
|
-
exp = Mgmg.exp(opt.smith_min, opt.comp_max)
|
410
|
-
opt.cut_exp, ret = exp, [opt.smith_min, -1, opt.comp_max] if exp <= opt.cut_exp
|
411
|
-
exp = Mgmg.exp(opt.smith_max, opt.comp_min)
|
412
|
-
opt.cut_exp, ret = exp, [opt.smith_max, -1, opt.comp_min] if ( exp < opt.cut_exp || (ret.nil? && exp==opt.cut_exp) )
|
413
|
-
eo = opt.irep.eo_para(para)
|
414
|
-
comps = Mgmg.fib_init(opt.comp_min, opt.comp_max)
|
415
|
-
values = comps.map do |comp|
|
416
|
-
r, e = eval_comp_s(para, target, comp, opt_nocut, eo)
|
417
|
-
opt.cut_exp, ret = e, r if e < opt.cut_exp
|
418
|
-
e
|
419
|
-
end
|
420
|
-
while 3 < comps[3]-comps[0]
|
421
|
-
if values[1] <= values[2]
|
422
|
-
comp = comps[0] + comps[2]-comps[1]
|
423
|
-
comps = [comps[0], comp, comps[1], comps[2]]
|
424
|
-
r, e = eval_comp_s(para, target, comp, opt_nocut, eo)
|
425
|
-
opt.cut_exp, ret = e, r if e < opt.cut_exp
|
426
|
-
values = [values[0], e, values[1], values[2]]
|
427
|
-
else
|
428
|
-
comp = comps[1] + comps[3]-comps[2]
|
429
|
-
comps = [comps[1], comps[2], comp, comps[3]]
|
430
|
-
r, e = eval_comp_s(para, target, comp, opt_nocut, eo)
|
431
|
-
opt.cut_exp, ret = e, r if e < opt.cut_exp
|
432
|
-
values = [values[1], values[2], e, values[3]]
|
433
|
-
end
|
434
|
-
end
|
435
|
-
exp_best = opt.cut_exp
|
436
|
-
opt.cut_exp = exp_best + (exp_best*opt.comp_ext[0]).to_i.clamp(opt.comp_ext[1], opt.comp_ext[2])
|
437
|
-
(comps[0]-1).downto(opt.comp_min) do |comp|
|
438
|
-
exp_best, ret = fine_s(exp_best, ret, para, target, comp, opt, eo)
|
439
|
-
rescue Mgmg::SearchCutException
|
440
|
-
break
|
441
|
-
end
|
442
|
-
(comps[3]+1).upto(opt.comp_max) do |comp|
|
443
|
-
exp_best, ret = fine_s(exp_best, ret, para, target, comp, opt, eo)
|
444
|
-
rescue Mgmg::SearchCutException
|
445
|
-
break
|
446
|
-
end
|
447
|
-
if ret.nil?
|
448
|
-
max = opt.irep.para_call(para, *find_max(para, opt.cut_exp, opt:))
|
449
|
-
raise Mgmg::SearchCutException, "the maximum output with given cut_exp=#{opt.cut_exp.comma3} is #{max.comma3}, which does not reach given target=#{target.comma3}"
|
450
|
-
end
|
451
|
-
ret
|
452
|
-
end
|
453
314
|
private def eval_comp_sa(para, target, comp, opt, eo)
|
454
315
|
return [nil, Float::INFINITY] if (comp < opt.comp_min or opt.comp_max < comp)
|
455
316
|
comp -= 1 if ( opt.comp_min<comp and eo & (2**(comp&1)) == 0 )
|
@@ -474,10 +335,15 @@ module Enumerable
|
|
474
335
|
end
|
475
336
|
def search(para, target, opt: Mgmg::Option.new)
|
476
337
|
opt = opt.dup.set_default(self)
|
477
|
-
|
338
|
+
begin
|
339
|
+
opt.comp_min = comp_search(para, target, opt.smith_max, opt.armor_max, opt:)
|
340
|
+
rescue Mgmg::SearchCutException
|
341
|
+
foo = opt.irep.para_call(para, opt.smith_max, opt.armor_max, opt.comp_max)
|
342
|
+
raise Mgmg::SearchCutException, "#{self} could not reach target=#{target} until (smith_max, armor_max, comp_max)=(#{opt.smith_max}, #{opt.armor_max}, #{opt.comp_max}), which yields #{foo.comma3}"
|
343
|
+
end
|
478
344
|
opt_nocut = opt.dup; opt_nocut.cut_exp = Float::INFINITY
|
479
|
-
opt.smith_max = smith_search(para, target, opt.armor_min, opt.comp_min, opt: opt_nocut) rescue (
|
480
|
-
opt.armor_max = armor_search(para, target, opt.smith_min, opt.comp_min, opt: opt_nocut) rescue (
|
345
|
+
opt.smith_max = smith_search(para, target, opt.armor_min, opt.comp_min, opt: opt_nocut) rescue ( opt.smith_max )
|
346
|
+
opt.armor_max = armor_search(para, target, opt.smith_min, opt.comp_min, opt: opt_nocut) rescue ( opt.armor_max )
|
481
347
|
opt.smith_min = smith_search(para, target, opt.armor_max, opt.comp_max, opt: opt_nocut)
|
482
348
|
opt.armor_min = armor_search(para, target, opt.smith_max, opt.comp_max, opt: opt_nocut)
|
483
349
|
raise Mgmg::SearchCutException if opt.cut_exp < Mgmg.exp(opt.smith_min, opt.armor_min, opt.comp_min)
|
@@ -507,7 +373,8 @@ module Enumerable
|
|
507
373
|
end
|
508
374
|
end
|
509
375
|
exp_best = opt.cut_exp
|
510
|
-
|
376
|
+
diff = values.max-values.min
|
377
|
+
opt.cut_exp = exp_best + diff*opt.fib_ext[0]
|
511
378
|
(comps[0]-1).downto(opt.comp_min) do |comp|
|
512
379
|
exp_best, ret = fine_sa(exp_best, ret, para, target, comp, opt, eo)
|
513
380
|
rescue Mgmg::SearchCutException
|
@@ -539,13 +406,15 @@ module Enumerable
|
|
539
406
|
end
|
540
407
|
private def eval_arm(para, armor, comp, eo, opt, ret, max, max_exp)
|
541
408
|
smith = Mgmg.invexp3(max_exp, armor, comp)
|
409
|
+
exp = Mgmg.exp(smith, armor, comp)
|
410
|
+
return [-Float::INFINITY, ret, max] if max_exp < exp
|
542
411
|
cur = opt.irep.para_call(para, smith, armor, comp)
|
543
412
|
smith = minimize_smith(para, smith, armor, comp, cur, opt) if max <= cur
|
544
|
-
ret, max = [smith, armor, comp], cur if ( max < cur || ( max == cur &&
|
413
|
+
ret, max = [smith, armor, comp], cur if ( max < cur || ( max == cur && exp < Mgmg.exp(*ret) ) )
|
545
414
|
[cur, ret, max]
|
546
415
|
end
|
547
416
|
private def eval_comp_fm(para, comp, eo, opt, ret, max, max_exp)
|
548
|
-
return [-Float::INFINITY,
|
417
|
+
return [-Float::INFINITY, ret, max] if (comp < opt.comp_min or opt.comp_max < comp)
|
549
418
|
comp -= 1 if ( opt.comp_min<comp and ( eo & (2**(comp&1)) == 0 ) )
|
550
419
|
cur = -Float::INFINITY
|
551
420
|
a_max = [opt.armor_max, Mgmg.invexp3(max_exp, opt.smith_min, comp)].min
|
@@ -569,7 +438,8 @@ module Enumerable
|
|
569
438
|
cur = cur_i if cur < cur_i
|
570
439
|
end
|
571
440
|
end
|
572
|
-
|
441
|
+
diff = a_vals.max-a_vals.min
|
442
|
+
th = max - diff*opt.fib_ext[1]
|
573
443
|
(arms[0]-1).downto(opt.armor_min) do |armor|
|
574
444
|
cur_i, ret, max = eval_arm(para, armor, comp, eo, opt, ret, max, max_exp)
|
575
445
|
break if cur_i < th
|
@@ -608,7 +478,8 @@ module Enumerable
|
|
608
478
|
values = [values[1], values[2], cur, values[3]]
|
609
479
|
end
|
610
480
|
end
|
611
|
-
|
481
|
+
diff = values.max-values.min
|
482
|
+
th = max - diff*opt.fib_ext[1]
|
612
483
|
(comps[0]-1).downto(opt.comp_min) do |comp|
|
613
484
|
next if ( eo & (2**(comp&1)) == 0 )
|
614
485
|
cur, ret, max = eval_comp_fm(para, comp, eo, opt, ret, max, max_exp)
|
@@ -670,28 +541,27 @@ module Mgmg
|
|
670
541
|
loop do
|
671
542
|
foo = a.find_max(para, eb, opt: opt_a)
|
672
543
|
break if sca == foo
|
673
|
-
|
544
|
+
bar = opt_a.irep.para_call(para, *foo)
|
545
|
+
break if bar < pa
|
546
|
+
sca, pa = foo, bar
|
674
547
|
scb = b.search(para, pa, opt: opt_b)
|
675
548
|
foo = Mgmg.exp(*scb)
|
676
549
|
break if eb == foo
|
677
550
|
eb = foo
|
678
551
|
end
|
679
552
|
ea = Mgmg.exp(*sca)
|
680
|
-
|
681
|
-
tag = pa + Eighth
|
682
|
-
raise Mgmg::SearchCutException, "given recipes are never reversed from start target=#{start.comma3} until term target=#{term.comma3}" if term < tag
|
683
|
-
sca, scb = a.search(para, tag, opt: opt_a), b.search(para, tag, opt: opt_b)
|
684
|
-
ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
|
685
|
-
pa, pb = opt_a.irep.para_call(para, *sca), opt_b.irep.para_call(para, *scb)
|
686
|
-
break if ea == eb && pa < pb
|
687
|
-
end
|
688
|
-
if eb < ea || ( ea == eb && pa < pb )
|
553
|
+
if (eb <= ea and pa <= pb and (eb+pa)!=(ea+pb)) or (eb < ea and sca == a.search(para, pb, opt: opt_a)) then
|
689
554
|
until ea < eb || ( ea == eb && pb < pa )
|
690
555
|
sca = a.find_max(para, ea-1, opt: opt_a)
|
691
556
|
ea, pa = Mgmg.exp(*sca), opt_a.irep.para_call(para, *sca)
|
692
557
|
end
|
693
558
|
return [pa, pb]
|
694
559
|
end
|
560
|
+
tag = pa + Eighth
|
561
|
+
raise Mgmg::SearchCutException, "given recipes are never reversed from start target=#{start.comma3} until term target=#{term.comma3}" if term < tag
|
562
|
+
sca, scb = a.search(para, tag, opt: opt_a), b.search(para, tag, opt: opt_b)
|
563
|
+
ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
|
564
|
+
pa, pb = opt_a.irep.para_call(para, *sca), opt_b.irep.para_call(para, *scb)
|
695
565
|
end
|
696
566
|
raise UnexpectedError
|
697
567
|
end
|
data/lib/mgmg/version.rb
CHANGED
data/reference.md
CHANGED
@@ -130,9 +130,9 @@
|
|
130
130
|
`opt`は,`comp_min`,`comp_max`,`left_associative`,`reinforcement`,`irep`を使用します.
|
131
131
|
|
132
132
|
## `String#search(para, target, opt: Mgmg.option())`
|
133
|
-
合計経験値が最小となる鍛冶・防具製作Lvと道具製作Lvの組を探索します.道具製作Lvを決定変数として,`smith_search`の返り値との合計経験値を最小化する道具製作Lvをフィボナッチ探索で探索した後,得られた解 c
|
133
|
+
合計経験値が最小となる鍛冶・防具製作Lvと道具製作Lvの組を探索します.道具製作Lvを決定変数として,`smith_search`の返り値との合計経験値を最小化する道具製作Lvをフィボナッチ探索で探索した後,得られた解 c の前後を探索し,最適化します.このとき,道具製作Lv c における合計経験値`exp`,及びフィボナッチ探索で得られた最後の4点の経験値の最大値`exp2`に対して,`exp+(exp2-exp)*opt.fib_ext[0]`を超えない範囲を探索します.この目的関数は単峰ではないため,フィボナッチ探索のみでは最適解が得られないことがあります.
|
134
134
|
|
135
|
-
その他は`String#smith_seach`と同様で,`opt`は,`String#smith_search`または`String#comp_search`で使われるすべてのパラメータと,`
|
135
|
+
その他は`String#smith_seach`と同様で,`opt`は,`String#smith_search`または`String#comp_search`で使われるすべてのパラメータと,`fib_ext`を使用します.
|
136
136
|
|
137
137
|
## `Enumerable#search(para, target, opt: Mgmg.option())`
|
138
138
|
複数装備の組について,`para`の値が`target`以上となる最小経験値の`[鍛冶Lv,防具製作Lv,道具製作Lv]`を返します.
|
@@ -145,7 +145,7 @@
|
|
145
145
|
## `String#find_max(para, max_exp, opt: Mgmg.option())`
|
146
146
|
経験値の合計が`max_exp`以下の範囲で,`para`の値が最大となる鍛冶・防具製作Lvと道具製作Lvからなる配列を返します.`para`の値が最大となる組が複数存在する場合,経験値が小さい方が優先されます.
|
147
147
|
|
148
|
-
`String#search`と同様に,道具製作Lvをフィボナッチ探索で探索した後,得られた解 c の前後を探索し,最適化します.道具製作Lv c における最大の`para`値`p_c`に対して,`p_c-(p_c*opt.
|
148
|
+
`String#search`と同様に,道具製作Lvをフィボナッチ探索で探索した後,得られた解 c の前後を探索し,最適化します.道具製作Lv c における最大の`para`値`p_c`,及びフィボナッチ探索で得られた最後の4点の`para`値の最小値`p_min`に対して,`p_c-(p_c-p_min)*opt.fib_ext[1]`を下回らない範囲を探索します.
|
149
149
|
|
150
150
|
## `Enumerable#find_max(para, max_exp, opt: Mgmg.option())`
|
151
151
|
複数装備の組について,経験値の合計が`max_exp`以下の範囲で,`para`の値が最大となる鍛冶Lv,防具製作Lv,道具製作Lvからなる配列を返します.`para`の値が最大となる組が複数存在する場合,経験値が小さい方が優先されます.
|
@@ -454,8 +454,8 @@ alias として`*`があるほか`scalar(1.quo(value))`として`quo`,`/`,`s
|
|
454
454
|
|smith_min|`recipe.min_level(target_weight)`|非対応|鍛冶Lvに関する探索範囲の最小値|`String#search`など|
|
455
455
|
|armor_min|`recipe.min_level(*target_weight)[1]`|非対応|防具製作Lvに関する探索範囲の最小値|`Enumerable#search`など.`String`系では代わりに`smith_min`を使う|
|
456
456
|
|comp_min|`recipe.min_comp`|非対応|道具製作Lvに関する探索範囲の最小値|`String#search`など|
|
457
|
-
|smith_max, armor_max, comp_max|`
|
458
|
-
|
|
457
|
+
|smith_max, armor_max, comp_max|`100_000`|対応|各製作Lvの探索範囲の最大値|`String#search`など|
|
458
|
+
|fib_ext|`[4, 10]`|対応|フィボナッチ探索後に追加探索を行う範囲|`String#search`など|
|
459
459
|
|target_weight|`0`|非対応|`smith_min`のデフォルト値計算に使う目標重量|`String#search`など|
|
460
460
|
|magdef_maximize|`true`|非対応|目標を魔防最大(真)かコスト最小(偽)にするためのスイッチ|`String#phydef_optimize`|
|
461
461
|
|reinforcement|`[]`|非対応|[前述](#mgmgequipreinforcearg)の`Mgmg::Equip#reinforce`による強化リスト|一部を除くすべてのメソッド|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mgmg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- KAZOON
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-11-
|
11
|
+
date: 2022-11-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|