-
Notifications
You must be signed in to change notification settings - Fork 35
[WIP] Minimax search function #71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Game trait created.
added missing isTerminalState function
minimaxsearch added
|
@BusyByte Hey, could you please resolve the conflicts and review the pull request. Thanks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some changes needed but looks good overall.
Can you add a test specification (specs2) and/or a scalacheck (property based check) to prove it works?
If there are examples from the book sometimes I'll use those to prove it works.
core/src/main/scala/aima/core/search/adversarial/MinimaxSearch.scala
Outdated
Show resolved
Hide resolved
core/src/main/scala/aima/core/search/adversarial/MinimaxSearch.scala
Outdated
Show resolved
Hide resolved
core/src/main/scala/aima/core/search/adversarial/MinimaxSearch.scala
Outdated
Show resolved
Hide resolved
core/src/main/scala/aima/core/search/adversarial/MinimaxSearch.scala
Outdated
Show resolved
Hide resolved
core/src/main/scala/aima/core/search/adversarial/MinimaxSearch.scala
Outdated
Show resolved
Hide resolved
core/src/main/scala/aima/core/search/adversarial/MinimaxSearch.scala
Outdated
Show resolved
Hide resolved
|
@a1shadows sorry something wasn't quite right with my resolution of the merge conflicts, hopefully you can fix it up |
|
@a1shadows let me know if you have any questions on the above or need help |
case a :: Nil used instead to improve consistency with other cases.
Integrated all requested changes and remedied handful of syntactical and logical errors.
|
@BusyByte Have tried addressing all the requested changes. Am working on testing the code. Could you please review the changes? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@a1shadows this looks good but still missing a test specification/property based test.
--edit never mind above, I just saw you were working on the testing code still
I'll do the test code. I have my mid-terms till the 28th. Just need a little bit of time. Thanks for your constant guidance. |
added test problem for minimax
test spec for minimax
|
@BusyByte I've written a test for the function, but I'm having some difficulty coming up with more tests. Could you please review the new code and suggest how I should proceed with the tests? |
|
@a1shadows fyi travis has broken, I've merge a fix to master for it now: you'll need to merge master in order to get travis to run your tests |
catching up
| case class State(stateNumber: Int) extends AnyVal | ||
| case class Action(stateNumber: Int) extends AnyVal | ||
|
|
||
| object TwoPlyGame extends Game[Player, State, Action] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be worth explaining what this game is and if it's in the book at all provide documentation (comments around it and how it works).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please give an example of the format in which I'm supposed to give the comment about the function?
| "The two-ply game " should { | ||
| "should return action to state 1 from state 0" in { | ||
| MinimaxDecision | ||
| .minMaxDecision[Player, State, Action](TwoPlyGame, Action(-1))(TwoPlyGame.initialState, TwoPlyGame.Players(1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than having a special integer value to signify no action why not have action be a sum type
sealed trait Action
case object NoAction extends Action
final case class MoveToState(s : State) extends Action| /** | ||
| * @author Aditya Lahiri | ||
| */ | ||
| case class Player(name: String) extends AnyVal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if there can only be 2 players why not code it that way;
sealed abstract class Player {
def name: String
}
final case class Player1(name: String) extends Player
final case class Player2(name: String) extends Player| 1 -> List(Action(4), Action(5), Action(6)), | ||
| 2 -> List(Action(7), Action(8), Action(9)), | ||
| 3 -> List(Action(10), Action(11), Action(12))) | ||
| val States = Map(0 -> State(0), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like this might go away with changes I outlined below to Action.
|
@a1shadows might be worth going through a full game and verifying each player's actions are what you expect and not just the first one and verify you get NoAction at the end. |
|
@a1shadows also since this is |
|
I'm getting a ton of errors on the code when I'm running it on the sbt which weren't there earlier. I can't understand them. aima-scala\core\src\main\scala\aima\core\agent\Actuator.scala:8:16: type parameter Action defined in trait Actuator shadows trait Action defined in package agent. You may want to rename your type parameter, or possibly remove it. Could you point me to what's going wrong, please? |
|
Also, would it be possible to set up a gitter channel to discuss the repository? For general queries and the like? |
|
@a1shadows I've created a gitter channel, you should get an invitation, I think the error you are seeing is because of a name collision. Maybe try upper case |
|
@a1shadows maybe you need to do a sbt clean |
|
@a1shadows this still says |
|
Yeah. I'd like to work a bit on it.
…On Sat, 29 Jun 2019, 5:00 pm Shawn Garner, ***@***.***> wrote:
@a1shadows <https://github.com/a1shadows> this still says WIP in the
title. Is there anything else you'd like to do before merging this?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#71?email_source=notifications&email_token=AFIGZIQM36IBESICN2TJWGDP45BWHA5CNFSM4HCLQQRKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODY3XFGA#issuecomment-506950296>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AFIGZISJXT33CFT5IDIL6M3P45BWHANCNFSM4HCLQQRA>
.
|
|
@BusyByte Hey, I was attempting to rewrite the code to give an optimal state for the game at every level as opposed to my earlier code that only gave the next best move, but I just realized that the pseudocode only provides an algorithm for the next best move with the assumption that the "MAX" player is making the move. I am unsure how to proceed from here on. Should I try to write the code for the complete algorithm that can calculate moves for both "MIN" and "MAX" players or should I restrict myself to what the book has provided? |
|
@a1shadows Looking at the test for the Java version it looks like it should handle both players. Looking at the Java implementation it just determines which player's turn it is based on the state. So when you call the search function you give it a state so it should just handle it naturally. I think it selects the max utility of the minimum utility assuming the next player will pick the min. So it doesn't look like the algorithm needs changed to handle both users. I think your spec may need to change to handle both users. Sorry for the delay in response. Work has been pretty hectic lately. |
|
@a1shadows is this good to go? If you are satisfied I can merge it. It still says WIP in the title so I'm inclined to wait. |
|
Ahh. Sorry. I've been busy with work. I'll wrap it up within this weekend.
…On Thu, 16 Jan 2020, 1:09 am Shawn Garner, ***@***.***> wrote:
@a1shadows <https://github.com/a1shadows> is this good to go? If you are
satisfied I can merge it.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#71?email_source=notifications&email_token=AFIGZIVT26T3YQMRU7P2VN3Q55RABA5CNFSM4HCLQQRKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEJBRPOI#issuecomment-574822329>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AFIGZIVP5DUXYEQNCSZFT53Q55RABANCNFSM4HCLQQRA>
.
|
|
Still ironing a few things out. I'll let you know when I'm comfortable with the changes. Is that okay? |
|
@a1shadows yeah, that's fine but please prioritize this as there are some more PRs coming through and I don't want you to have a bunch of merge conflicts to work through since your PR predates them. |
|
I'm satisfied with my changes. Can you review and merge? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some things I'd change but this looks good.
|
|
||
| final case class UtilityValue(value: Double) extends AnyVal | ||
| final case class UtilityValue(value: Double) extends AnyVal { | ||
| def <(that: UtilityValue) = if (this.value < that.value) true else false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really this should be typeclass
| def getUtility(state: S): UtilityValue | ||
| } | ||
|
|
||
| trait Player {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really like having traits with no defined behavior.
I'd just as soon keep these in the definition of the given game so they can be sealed and compile time checked to be total matched.
| maxValue(g.result(state, minMaxValue(g.getActions(state)))) | ||
| } | ||
|
|
||
| maxMinValue(g.getActions(g.initialState)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@a1shadows I was looking at this when trying to implement alpha beta search and have a question. Why are you passing in the g.initialState rather than state which is passed into the function? this does not seem to match the algorithm.
|
I decided to not leave that decision up to the caller because the correct
behavior will change according to the state for which the decision will be
made. For some of the nodes, minMaxValue has to be called for the correct
decision and not maxMindecision. Would me like me to change the logic?
Sorry for the late reply.
…On Sun, Mar 1, 2020 at 10:50 PM Shawn Garner ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In core/src/main/scala/aima/core/search/adversarial/MinimaxSearch.scala
<#71 (comment)>:
> +
+ def maxValue(state: STATE): UtilityValue = {
+ if (g.isTerminalState(state))
+ g.getUtility(state)
+ else
+ minValue(g.result(state, maxMinValue(g.getActions(state))))
+ }
+
+ def minValue(state: STATE): UtilityValue = {
+ if (g.isTerminalState(state))
+ g.getUtility(state)
+ else
+ maxValue(g.result(state, minMaxValue(g.getActions(state))))
+ }
+
+ maxMinValue(g.getActions(g.initialState))
@a1shadows <https://github.com/a1shadows> I was looking at this when
trying to implement alpha beta search and have a question. Why are you
passing in the g.initialState rather than state which is passed into the
function? this does not seem to match the algorithm.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#71?email_source=notifications&email_token=AFIGZIXSKVMEYC4KUHB6NODRFKKMLA5CNFSM4HCLQQRKYY3PNVWWK3TUL52HS4DFWFIHK3DMKJSXC5LFON2FEZLWNFSXPKTDN5WW2ZLOORPWSZGOCXPAWJQ#pullrequestreview-366873382>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AFIGZIUA4J4SVH7D6FNHY2DRFKKMLANCNFSM4HCLQQRA>
.
|
Issue #9