this is "optimization"

This commit is contained in:
efim
2022-12-24 10:11:53 +00:00
parent 83f65babdf
commit bf52645d93
2 changed files with 225 additions and 8 deletions

View File

@@ -134,7 +134,7 @@
(let* ((will-collect-this-minute (calc-resources-to-be-collected s))
(max-if-building
(loop
for bot-type in *add-types*
for bot-type in (get-possible-bot-builds blueprints s)
for state-with-new-bot = (create-robot blueprints bot-type s)
when state-with-new-bot
maximize (progn
@@ -164,7 +164,7 @@
:geode (:ore 2 :obsidian 7)))
(setq *test-state* (make-instance 'state))
(print (find-max-geod *test-blueprint* *test-state* 1))
;; (print (find-max-geod *test-blueprint* *test-state* 1))
;; => 0
;; that's because i have no ability to "wait"
;; whoops
@@ -212,3 +212,180 @@
;; but only over states with same amount of steps?
;; ok. let's commit what i have right now and try to trim?
;; how could i compare with that "cur-max" and update that cur-max?
;; no, i don't understand
(format t "some result ~a~%" (find-max-geod *test-blueprint* *test-state* 1))
;; well, yes one optimizaiton - stop building robots, when resource is to the top of
;; max daily expense
;; that would reduce a lot
;; 1)
;; would be nice to put these into (possible-robots-to-build)
;; so that it would also filtered out unnecessary new robots
;;
;; 2)
;; "keep global current max state" how would i compare and check if it's impossible to beat?
;; with "even if i could to build geod machine every day for rest N days"
*test-blueprint*
*test-state*
(add-resources '(:ore 10) *test-state*)
(incf (getf (robots *test-state*) :ore) 2)
(any-use-of-creating-robot *test-blueprint* *test-state* :ore)
(any-use-of-creating-robot *test-blueprint* *test-state* :clay)
(any-use-of-creating-robot *test-blueprint* *test-state* :obsidian)
(any-use-of-creating-robot *test-blueprint* *test-state* :geode)
(max-need *test-blueprint* *test-state* :ore)
(max-need *test-blueprint* *test-state* :clay)
(max-need *test-blueprint* *test-state* :obsidian)
(max-need *test-blueprint* *test-state* :geode)
;; and this is not good for :geode, we want as much as possible
(get-possible-bot-builds *test-blueprint* *test-state*)
;; and now let's add static "max state"?
;; i'd need comparison like "can catch up" with that found max "is dominated by"
;; and also way to update that maximal state?
;;
;; so, what will that be?
;; comparison for update, should it also be if i found a state that dominates?
;; only for satiated states?
;;
;; if day is same or more
;; but the amount of geode robots and geodes is smaller?
(is-satiated-p *test-blueprint* *test-state*)
(incf (getf (robots *test-state*) :obsidian 0) 20)
;; seems to work,
;; but i already want to utilize some test framework
;; whelp. i do want to test this
;; 4 14 7 to be satisfied
(is-satiated-p
*test-blueprint*
(make-instance 'state :robots '(:ore 4 :clay 14 :obsidian 7 :geode 2)))
(is-satiated-p
*test-blueprint*
(make-instance 'state :resources '(:ore 4 :clay 14 :obsidian 7 :geode 2))) ; not, need robots
(is-satiated-p
*test-blueprint*
(make-instance 'state :robots '(:ore 4 :clay 14 :obsidian 7 :geode 2)))
;; now for checking is-dominated. ugh.
(a-dominates-b-p
*test-blueprint*
(make-instance 'state :robots '(:ore 4 :clay 14 :obsidian 7 :geode 2))
(make-instance 'state :robots '(:ore 4 :clay 14 :obsidian 7 :geode 2)))
;; both satiated, but second bigger
(a-dominates-b-p
*test-blueprint*
(make-instance 'state :robots '(:ore 5 :clay 17 :obsidian 7 :geode 2))
(make-instance 'state :robots '(:ore 6 :clay 18 :obsidian 7 :geode 2)))
;;
;; both satiated, but second not always bigger
(a-dominates-b-p
*test-blueprint*
(make-instance 'state :robots '(:ore 5 :clay 17 :obsidian 9 :geode 2))
(make-instance 'state :robots '(:ore 6 :clay 18 :obsidian 8 :geode 2)))
;;
;; first not satiated, even though second is bigger - nil
(a-dominates-b-p
*test-blueprint*
(make-instance 'state :robots '(:ore 2 :clay 17 :obsidian 9 :geode 2))
(make-instance 'state :robots '(:ore 6 :clay 18 :obsidian 8 :geode 2)))
;; and that's not right. if we have on same amount of steps
;; reference as satiated and checking as not - wouldn't keep up
;; so big check should be whether steps are even in imagination permit
;; ugh. that would mean putting minute\step into state.
;; um, let's not do it right now?
;; for both satiated is a very weak check, but let's try it like this?
(setq *test-state* (make-instance 'state))
(setf (cur-found-max *test-state*) (make-instance 'state))
;; so whelp
;; should have committed after doing the "build makes sence list"
;;
;; my problems are because "is dominated by" is not simmetrical to "dominates"
;; and i want both
;;
;; now in the loop set first satiated as domination
;; after that compare if our set dominates that one and swap
;; and compare if it's dominated by that one and prune
;; so, only if ref earlier than checked state.
;; and then - if checked not saitated, or by all resources less than
;; but i do want tests
;; both satiated, but second bigger
(a-dominates-b-p
*test-blueprint*
(make-instance 'state :robots '(:ore 6 :clay 18 :obsidian 7 :geode 2) :minute 2)
(make-instance 'state :robots '(:ore 6 :clay 18 :obsidian 7 :geode 2) :minute 3))
;; should be NIL
;; now want to check for different amount of steps.
;; so if same resources but first is earlier - it dominates
(minute (make-instance 'state :robots '(:ore 6 :clay 18 :obsidian 7 :geode 2) :minute 2))
;; i was putting :minute 2 into :robots plist, cool, no thanks to you types
(minute (make-instance 'state :robots '(:ore 6 :clay 18 :obsidian 7 :geode 2) :minute 2))
;; ok. this also seems well.
;; then main loop? on fisrt satiated set as `cur-found-max`
;; and after that always check -
(defmethod find-max-geod-2 (blueprints (s state))
;; (declare (optimize (debug 3)))
(format t "in step for ~a; with ~a~%" (minute s) s)
(when (and
(not (cur-found-max s)) ; first pruning max
(is-satiated-p blueprints s))
(setf (cur-found-max s) s))
(cond
((= 25 (minute s)) ; exit condition fully calculated
(getf (resources s) :geode 0))
((and (cur-found-max s) (a-dominates-b-p blueprints (cur-found-max s) s)
0)) ; pruning this branch
(t ; default check
(progn
(when (and (cur-found-max s)
(a-dominates-b-p blueprints s (cur-found-max s)))
(setf (cur-found-max s) s)) ; set current state as domineering
(let* ((will-collect-this-minute (calc-resources-to-be-collected s))
(possible-bot-builds (get-possible-bot-builds blueprints s))
(max-if-building
(when possible-bot-builds
(loop
for bot-type in possible-bot-builds
for state-with-new-bot = (create-robot blueprints bot-type s)
when state-with-new-bot
maximize (progn
(add-resources will-collect-this-minute state-with-new-bot)
(incf (minute state-with-new-bot))
(find-max-geod-2 blueprints state-with-new-bot )))))
(if-not-building
(let ((state-copy (copy-state s)))
;; (break)
(add-resources will-collect-this-minute state-copy)
(incf (minute state-copy))
(find-max-geod-2 blueprints state-copy ))))
;; (break)
;; (format t "would build ~a~%" possible-bot-builds)
(max (or max-if-building 0) if-not-building))))))
(setq *test-state* (make-instance 'state))
(setf (cur-found-max *test-state*) nil)
(print (find-max-geod-2 *test-blueprint* *test-state*))
;; so, why doesn't it ever builds obsidian?
*test-blueprint*
;; because is "has to build something if it can" whops