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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c14a55ea3bffa94e0b9aa9e65a7a5013d34d8bec62179baae302dabdd150f08
4
- data.tar.gz: db35e0738dc57da24e132bacea2cd30a1040d6dc563449ce3b3b8b19a62fa0ae
3
+ metadata.gz: 79211ca6cd5422500f7dc957eadfb2c1812459c98fd39b84fc9a3ebf178174ec
4
+ data.tar.gz: efa0254194363114aee22993e78cab9359e9a7c92f454d5fffc12b1d14368e6c
5
5
  SHA512:
6
- metadata.gz: 475431bc7166ad3c18fb60aec3fb921e43a2987086caf357ab20de75b085da125df70941c4810e06094f3b859c8480258dae41a89b29a46562cb3a4510016aa5
7
- data.tar.gz: a4466773b3f3f77e9636b4ab5fa46934ec3781f8d088e889c39dbb72f45e79c5a7217dbb15b79767e067283bf30425449f28804a1794b591bbbef07669ed8749
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: 1_000_000_000, armor_max: 1_000_000_000, comp_max: 1_000_000_000,
6
- comp_ext: [0.1, 100, 10_000, 0.1]
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
- comp_ext: Defaults[:comp_ext],
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
- @comp_ext = comp_ext
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, :comp_ext
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
- @comp_ext = other.comp_ext
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
- opt.comp_min = comp_search(para, target, opt.smith_max, opt:)
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
- opt.cut_exp = exp_best + (exp_best*opt.comp_ext[0]).to_i.clamp(opt.comp_ext[1], opt.comp_ext[2])
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
- th = max - (max*opt.comp_ext[3]).ceil
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 ArgumentError, "given comp_max=#{opt.comp_max} does not satisfies the target"
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
- opt.comp_min = comp_search(para, target, opt.smith_max, opt.armor_max, opt:)
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 ( return search_aonly(para, target, opt:) )
480
- opt.armor_max = armor_search(para, target, opt.smith_min, opt.comp_min, opt: opt_nocut) rescue ( return search_sonly(para, target, opt:) )
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
- opt.cut_exp = exp_best + (exp_best*opt.comp_ext[0]).to_i.clamp(opt.comp_ext[1], opt.comp_ext[2])
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 && Mgmg.exp(smith, armor, comp) < Mgmg.exp(*ret) ) )
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, Float::INFINITY, max] if (comp < opt.comp_min or opt.comp_max < comp)
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
- th = max - (max*opt.comp_ext[3]).ceil
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
- th = max - (max*opt.comp_ext[3]).ceil
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
- sca, pa = foo, opt_a.irep.para_call(para, *foo)
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
- while ea<=eb
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
@@ -1,3 +1,3 @@
1
1
  module Mgmg
2
- VERSION = "1.7.0"
2
+ VERSION = "1.8.0"
3
3
  end
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 の前後を探索し,最適化します.道具製作Lv c における合計経験値`exp`に対して,`exp+(exp*opt.comp_ext[0]).to_i.clamp(opt.comp_ext[1], opt.comp_ext[2])`を超えない範囲を探索します.この目的関数は単峰ではないため,フィボナッチ探索のみでは最適解が得られないことがあります.
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`で使われるすべてのパラメータと,`comp_ext`を使用します.
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.comp_ext[3]).ceil`を下回らない範囲を探索します.
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|`1_000_000_000`|対応|各製作Lvの探索範囲の最大値|`String#search`など|
458
- |comp_ext|`[0.1, 100, 10_000, 0.1]`|対応|フィボナッチ探索後に追加探索を行う範囲|`String#search`など|
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.7.0
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-12 00:00:00.000000000 Z
11
+ date: 2022-11-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler