mgmg 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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