GithubHelp home page GithubHelp logo

bupticybee / texassolver Goto Github PK

View Code? Open in Web Editor NEW
1.7K 42.0 299.0 31.58 MB

🚀 A very efficient Texas Holdem GTO solver :spades::hearts::clubs::diamonds:

Home Page: https://bupticybee.github.io/texassolver_page

License: GNU Affero General Public License v3.0

Python 1.93% C++ 97.23% QMake 0.39% Shell 0.19% C 0.24%
texas-holdem solver texas-holdem-poker shortdeck piosolver holdem-poker game-theory game-theory-algorithms gto poker-ai

texassolver's Introduction

CPP Texas Solver

release license Open In Colab Gitter chat

README English | 中文

Introduction

A open sourced, extremely efficient Texas Hold'em and short deck solver. See this Introduction video for more. Supports Windows,MacOs and Linux.

Features:

  • In a tree with 1~2bets + allin, it's speed exceeds piosolver on flop
  • Support Mac, Linux and Windows
  • Support texas holdem and shortdeck
  • Support cross language calls
  • Result aliged with piosolver
  • Support dump strategy to json file
  • It's the c++ version of TexasHoldemSolverJava with a ton of optimization, it's 5x faster than the java version and takes less than 1/3 memory.

Feel free to mess with a toy solver in google colab

Install

Download package according to your OS in release package, unzip it, and install is done. It's that simple.

GUI version Usage

After install the solver, double click the application binary (TexasSolverGui.exe in windows or TexasSolverGui.app in MacOS) to run TexasSolver.

Console version Usage

Please check console version document for more.

Speed benchmark with piosolver

Piosolver and my TexasSolver(console version) run use the same settings (spr=10,flop game) and their result are aligned.

Input config log thread number memory usage accuracy converge time
piosolver 1.0 config_piosolver log_piosolver 6 492Mb 0.29% 242s
TexasSolver 0.1.0 (Our solver) config_texassolver log_texassolver 6 1600Mb 0.275% 172s

The compare image of their results is here. As you can see their result are very close.

License

GNU AGPL v3

Email

[email protected]

Q & As

  1. Q: Is the solver really free?

    • A: Yes, for personal users, the solver is completely opensourced and free.
  2. Q: Can I upload it to other websites or forums? Can I share it with my friend?

    • A: No, you can only put the link of this project to other website, not the binary, this project is under AGPL-V3 license, and these kind of actions violates this license.
  3. Q: Can I integrate it to my software?

    • A: If you integrate the release package (binary) into your software, Yes, you can do that. If you want to integrate the code of the solver into your software or provide service through internet, then you need to contact me for a commercial license, which is also the main profit-making method of this project.
  4. Q: What framework do you use to write the ui?

    • A: I use QT 5.1.0 (opensourced edition) to build the GUI version. For the console version, I use Mingw + CMake.

texassolver's People

Contributors

bupticybee avatar chessparov avatar endle avatar kncesarini avatar mix16atpitt avatar moreheadm avatar notx0r avatar ra1u avatar ruimaciel avatar yffbit avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

texassolver's Issues

遇到错误: Card length incorrect: 0

大神好,win10环境,个把月前一台电脑成功运行并求解。今天下载后成功运行,使用默认参数或者自行选择范围,点击求解后提示:
遇到错误:
Card length incorrect: 0
另,选择opp或者ip范围不对,例如6max中utg open2.5bb 没有co call的目录
1(1)

segfault in --mode shortdeck

Try to run solver with --mode shortdeck, but it fails. Can you please help?

root@:~/TexasSolver-Linux# ./console_solver -i resources/text/commandline_sample_input.txt --mode shortdeck EXEC FROM FILE [##################################################] 100% <<<START SOLVING>>> Using 8 threads Iter: 0 Segmentation fault (core dumped)
This is commandline file that I use:

Isomorphic suits not converging to similar values

The used ranges are for 6-max, BTN open 2.5bb, BB 11bb, BTN calls. In this example, AcJc, AdJd, and AsJs are virtually the same hand on JhTh4h flop. However, the preferred strategy for them is not similar enough.

suits_bug

This leads to further imbalance between suits in later parts of the game tree, as can be seen in OOP's strategy when facing a bet of 15. Here, the strategies for isomorphic 8c8h, 8d8h, 8h8s do not agree - 8h8s is never raised, the other two combinations are raised 15.2% of the time.

suits_bug2

On which paper do your algorithm based on?

I tried to understand what optimization you did that differs from normal cfr, but it's quite a work to read pure codes without any comments.
If you'd tell me which paper to researh, it would be much easier.
Thx again for your hard work.

[Improvement] Range selection improvement

This is a great project, thank you for the work you have done so far.

I would like to propose a UX improvement.

Many users will be interacting with the range selection features. Currently, you have included some default ranges. This is very helpful.

One way you can improve this is to look into the UX provided by Flopzilla (https://www.flopzilla.com/) by implementing a sliding bar that allows users to populate the range with a % of hands. For instance, the slider would start at 0% with 0 hands selected, but then the user could slide the bar to the right and increase the number of hands included to be the top % of hands, where the top hands are determined by some metric, such as all-in EV against a random hand. This makes selecting ranges must faster for users.

Thank for you this amazing project! I would contribute if I knew C++ :)

Also, do you have a public roadmap or list of features you plan to add?

Floating point exception (core dumped)

I'm trying to run console_solver in a Docker container.
Image created from ubuntu. It runs, takes 500MB RAM and utilized all given threads, and then crashes.
Log looks:

EXEC FROM FILE
[##################################################] 100%
<<>>
Using 4 threads
Iter: 0
player 0 exploitability 20.712248
player 1 exploitability 14.561801
Total exploitability 35.274048 precent
Floating point exception (core dumped)

Some errors on Mac

An error has been raised on my Mac:
dyld: Library not loaded: /usr/local/opt/gcc@7/lib/gcc/7/libgomp.1.dylib
Referenced from: /Users/XXXX/poker/TexasSolver-v0/console_solver
Reason: image not found

windows的一个小问题

在执行的命令行之后,程序似乎只运行了一半,就自动结束了(没有加载进度条)试了几次都是如此

image

[not an issue, but question] How to calculate GTO hand ranges

Hello @bupticybee!
I want to say thank you for such a great project first :)

Maybe that is not a proper place to ask a question - it's about defining hand ranges.
Is there any way to calculate it using your application (for preflop, 3bet, etc.)?
I see some predefined values in config files you have provided, but how to calculate it programmatically?

specification of initial strategy

It might provide faster convergence to be able to specify an initial strategy.

Some ideas on how to do this

the simplest is use equity thresholds vs a subset of hands - the simplest subset might be TPTK (on an unpaired board).

Next is bit more complex strategy specification used in software like cardrunners EV,
such as hands > top pair top kicker on a board texture of no pair

https://www.cardrunnersev.com/manual/postflopmenu.html

fairly tedious though.

Lastly, my preffered method is using the variables specified in the papers on pokibot by university of alberta - hand strength (HS), positive hand potential (pPot), negative hand potential (nPot). I'd also add bluff range blocking (BlfBlk), and value range blocking (VBlk).

The value of this is we can use these to understand strategies created by the solver. and to simplify storage since strategies will tend to cluster based on these five properties. For instance medium HS, high nPot are vulnerable hands and will tend to want to bet for value and protection; High HS with value blockers are hands like top set, that block villians calling range, so will want to check on the flop. If in the future you want to do bucketing post flop for faster convergence, you can use these properties for creating the buckets.

Here are the formulas for the first three, from

https://poker.cs.ualberta.ca/publications/AAAI98.pdf

HandStrength(ourcards,boardcards)
{ ahead = tied = behind = 0
ourrank = Rank(ourcards,boardcards)
/* Consider all two card combinations of */
/* the remaining cards. */
for each case(oppcards)
{ opprank = Rank(oppcards,boardcards)
if(ourrank>opprank) ahead += 1
else if(ourrank=opprank) tied += 1
else /* < */ behind += 1
}
handstrength = (ahead+tied/2)
/ (ahead+tied+behind)
return(handstrength)
}
HandPotential(ourcards,boardcards)
{ /* Hand potential array, each index repre- */
/* sents ahead, tied, and behind. */
integer array HP[3][3] /* initialize to 0 */
integer array HPTotal[3] /* initialize to 0 */
ourrank = Rank(ourcards,boardcards)
/* Consider all two card combinations of */
/* the remaining cards for the opponent. */
for each case(oppcards)
{ opprank = Rank(oppcards,boardcards)
if(ourrank>opprank) index = ahead
else if(ourrank=opprank) index = tied
else /* < */ index = behind
HPTotal[index] += 1
/* All possible board cards to come. */
for each case(turn,river)
{ /* Final 5-card board */
board = [boardcards,turn,river]
ourbest = Rank(ourcards,board)
oppbest = Rank(oppcards,board)
if(ourbest>oppbest) HP[index][ahead]+=1
else if(ourbest=oppbest) HP[index][tied]+=1
else /* < */ HP[index][behind]+=1
}
}
/* Ppot: were behind but moved ahead. */
Ppot = (HP[behind][ahead]+HP[behind][tied]/2
+HP[tied][ahead]/2)
/ (HPTotal[behind]+HPTotal[tied])
/* Npot: were ahead but fell behind. */
Npot = (HP[ahead][behind]+HP[tied][behind]/2
+HP[ahead][tied]/2)
/ (HPTotal[ahead]+HPTotal[tied])
return(Ppot,Npot)
}

For the blockers, one formula counts the number hand combos blocked in the top 30% (for value blockers) and bottom 30% for (bluff blockers)

Suggestion - Allow Specification of Hand

Hey! Awesome solver you've put together and appreciate you making it open source. Not an issue but some suggestions to improve.

To save time in some solving situations, it might be useful to allow the user to specify a specific hand one player has as well as their range. This could help in reducing the size of the tree needed to compute for some situations.

Another suggestion could be to pre-program the actions of one player up to the turn/river in order to automatically narrow their range without having to calculate the full tree.

Again, not entirely sure on the feasibility of these ideas, but would be appreciated!

About 'set_thread_num'

how many thread num to set?just only 8?I try 1,2,6,10 in resources/text/commandline_sample_input.txt.None work. Error :
terminate called after throwing an instance of 'std::runtime_error'
what(): command not valid: set_thread_num

[Bug] Some range actions do not appear. even if I choose inital range.

Issue

When I calculate specific parameters, (write down below) some range actions do not appear.

Platform
MacOS BigSur
TexasSolver 0.2

Steps to reproduce

open software
input parameters

board: 4c,9d,Kh
IP range: AA:1.000,AKs:1.000,AQs:1.000,AJs:1.000,ATs:1.000,A9s:1.000,A8s:1.000,A7s:1.000,A6s:1.000,A5s:1.000,A4s:1.000,A3s:1.000,A2s:1.000,AKo:1.000,KK:1.000,KQs:1.000,KJs:1.000,KTs:1.000,K9s:1.000,K8s:1.000,K7s:1.000,K6s:1.000,K5s:1.000,AQo:1.000,KQo:1.000,QQ:1.000,QJs:1.000,QTs:1.000,Q9s:1.000,Q8s:1.000,Q7s:1.000,Q6s:1.000,AJo:1.000,KJo:1.000,QJo:1.000,JJ:1.000,JTs:1.000,J9s:1.000,J8s:1.000,J7s:1.000,ATo:1.000,KTo:1.000,QTo:1.000,JTo:1.000,TT:1.000,T9s:1.000,T8s:1.000,T7s:1.000,T6s:1.000,A9o:1.000,K9o:1.000,Q9o:1.000,J9o:1.000,T9o:1.000,99:1.000,98s:1.000,97s:1.000,96s:1.000,A8o:1.000,K8o:1.000,Q8o:1.000,J8o:1.000,T8o:1.000,98o:1.000,88:1.000,87s:1.000,86s:1.000,A7o:1.000,K7o:1.000,87o:1.000,77:1.000,76s:1.000,75s:1.000,A6o:1.000,76o:1.000,66:1.000,65s:1.000,A5o:1.000,55:1.000,54s:1.000,A4o:1.000,44:1.000,A3o:1.000,33:1.000,A2o:1.000,22:1.000

OOP range: 
ATs:1.000,A9s:1.000,A8s:1.000,A7s:1.000,A6s:1.000,A5s:1.000,A4s:1.000,A3s:1.000,A2s:1.000,KTs:1.000,K9s:1.000,K8s:1.000,KQo:1.000,QTs:1.000,Q9s:1.000,KJo:1.000,QJo:1.000,JTs:1.000,J9s:1.000,J8s:1.000,ATo:1.000,KTo:1.000,QTo:1.000,JTo:1.000,T9s:1.000,T8s:1.000,A9o:1.000,K9o:1.000,99:1.000,98s:1.000,A8o:1.000,88:1.000,87s:1.000,A7o:1.000,77:1.000,76s:1.000,A6o:1.000,66:1.000,A5o:1.000,55:1.000,44:1.000,33:1.000,22:1.000

Bet sizes:
Flop IP: 30%, 50%, 70%, 150% addallin
Flop OOP:  30%, 50%, 70%, 150% addallin
Turn IP:  30%, 50%, 70%, 150% addallin
Turn OOP:  30%, 50%, 70%, 150% addallin, donk50%
River IP:  30%, 50%, 70%, 150% addallin
River OOP:  30%, 50%, 70%, 150% addallin, donk50%

raise limit: 10
pot: 500
Effective Stack: 10200

all remaining parameters are default.

build a tree
wait for finish calculation
show result
Screen Shot 2021-11-13 at 20 46 53

It doesn't work if calculating river only

Input file:

set_pot 100
set_effective_stack 100
set_board Ts,3h,2h,5c,9s
set_range_ip KK
set_range_oop AA,QQ
set_bet_sizes oop,river,allin
set_bet_sizes ip,river,allin
set_allin_threshold 0.67
build_tree
set_thread_num 5
set_accuracy 0.5
set_max_iteration 200
set_print_interval 10
set_use_isomorphism 1
start_solve
set_dump_rounds 2
dump_result output_result.json

output:
EXEC FROM FILE
[##################################################] 100%

Nothing in output.json file

Btw, is there an introduction about all the available commands?

缺少dll

windows找不到libgcc_s_seh-1.dll, libwinpthread-1.dll, libgomo-1.dll, libstdc++-6.dll

需要装什么库?

cc1plus.exe: error: output filename specified twice

g++ -fno-keep-inline-dllexport -openmp -g -std=gnu++11 -Wall -W -Wextra -dM -E -o debug/moc_predefs.h C:/Qt/Qt5.11.3/5.11.3/mingw53_32/mkspecs/features/data/dummy.cpp
cc1plus.exe: error: output filename specified twice
Makefile.Debug:400: recipe for target 'debug/moc_predefs.h' failed
mingw32-make[1]: Leaving directory 'E:/temp/build-TexasSolverGui-Desktop_Qt_5_11_3_MinGW_32bit-Debug'
mingw32-make[1]: *** [debug/moc_predefs.h] Error 1
Makefile:36: recipe for target 'debug' failed
mingw32-make: *** [debug] Error 2
16:59:30: 进程"C:\Qt\Qt5.11.3\Tools\mingw530_32\bin\mingw32-make.exe"退出,退出代码 2 。
Error while building/deploying project TexasSolverGui (kit: Desktop Qt 5.11.3 MinGW 32bit)
When executing step "Make"

OSX GUI off Screen

Hi

The GUI is bigger than my Macbook pro screen and I can't reduce size of it ..Is this a known issue ?

Thanks In advance

preflop range format in console version

Hello. Thanks for a great job.
But there is one moment that is very important to me.
Now in the console version only this format is supported for entering the preflop range:
QTs:1,55:1,98s:1
I need the program to also support this format of the preflop range:
QhJh:0.14,QhTh:0.37,QsJs:0.02,QsTs:0.08,Tc9c:0.83,Td9d:0.82,TdTc:0.4,Th9h:0.91,ThTc:0.3
I think it's not difficult to add. And I will be very grateful.
Thank you in advance.

Strategy EV not displaying

When I choose a strategy for a street, it doesn't display the overall EV of that strategy. It does display the EV of a single hand though. This makes it impossible to compare the EV of different strategies: for instance, suppose I want to compare the EV of allowing only a 33% size cbet vs the EV of allowing only a 50% size cbet on a given texture, for it to happen I need the display of the overall EV of the strategy.

Running the solver on a Mac operating system, so maybe it is because of it?

Great product anyway, hope you can tweak this thing, good job.

随机节点的概率

// 可能的发牌情况,2代表每个人的holecard是两张
int possible_deals = node->getCards().size() - Card::long2board(current_board).size() - 2;

new_reach_probs[player_hand] = reach_probs[player_hand] / possible_deals;

// 可能的发牌情况,2代表每个人的holecard是两张
int possible_deals = node->getCards().size() - Card::long2board(current_board).size() - 2;

这里计算possible_deals应该要减去双方手牌张数之和,也就是减4,而不是减2
拿6张牌{A,B,C,D,E,F}举例,对于任意具体的节点,例如player1拿A,player2拿B,发公共牌时实际只有4个动作{C,D,E,F},也可以对齐到6个动作,其中2个动作概率为0,剩余4个动作概率均为1/4。对于向量形式,例如计算player1的信息集A的期望收益(或虚拟价值),player2拿{B,C,D,E,F},虽然发公共牌有5种情况,但是对5个子节点加权求和时,只有4个子节点的期望收益做出了贡献。
现在的计算方式乘上5/4才是真实值。这也不是什么大问题,真正出问题是在发牌节点的父节点处。假设父节点的fold动作进入叶子节点,call动作进入发牌节点,这两个子节点的期望收益一个是真实值,另一个乘上5/4才是真实值,两个值直接(加权)求和就有问题。

OOP donk flop

Hi,
In my outputs, it seems OOP always checks flop >80% and shows higher EV than betting. If this is accurate according to sim, it's fine. Is there a way to remove checking with nodelocking? I would like to study spots with OOP flop bet.

Gui faster console

Good afternoon. Thank you for your project! Please can u tell me why the speed of preparing the tree in the gui is much faster than in the console version?
It takes half a second to start counting the distribution in the gui. And in the console version about 10 seconds.

Bet size % issue

I think I am having a bet % issue, but it could be user error. In this hand I set the bet %s to be 20% and 70%. The turn is when things go weird. The starting pot is 16.4. If I bet 4 on the flop and get a call, the pot should be around 24.8 (~25). On the turn, after OOP checks, IP gets the option to bet 4 which is around 16% close enough, but IP also gets the option to bet 32 which is massive into the 25 pot. I set the bet % to be 70 so I would have expected it to offer 16 or 17, but not 32. Did I enter the numbers in wrong? This felt like a bug but I wasn't sure.

Screen Shot 2021-11-14 at 9 44 06 PM

memory usage tree compression

Are you using any tree or other memory compression tricks?

Compression is mentioned in the logs of jesolver (By the developer who did Cephesus)

https://jesolver.com/cmdref.html#set_compression
https://jesolver.com/download/free/changelog.txt

He has some CFR compression work but it isn't clear if it applies - uses average strategy
https://jeskola.net/cfr/

https://jeskola.net/cfr/dcfu/
https://jeskola.net/cfr/avgstr/

Simplepostflop mentions tree compression,

"Simple Postflop Solver has 3 different algorithms (A1, A2, A3) and SPF A1 algorithm could use different degrees of tree compression in the RAM."

https://simplepoker.com/en/News/Fair_Performance_Comparison_of_Simple_Postflop_and_PioSolver_56

". Also, algorithm can now use compression of strategy tree in RAM 2x, 3x and 4x times, which allows to run much more complex trees than previously your PCs allowed."

https://forumserver.twoplustwo.com/167/poker-software/simple-poker-best-gto-solvers-preflop-postflop-holdem-omaha-2-way-mw-amp-gto-tools-1518064/index8.html

forced frequency choices

You might consider the option of the algorithm to only consider certain action frequencies or frequency increments say 50% increment (0/50/100), or 25% increment (0/25/50/75/100); or 10% (0/10/20/...) or 5% (0/5/10/...)

I expect this will have many advantages -

  1. faster convergence
  2. the frequency increments might be useful as a warm start - so the solver first uses larger increments for an initial solve, then switches to finer frequency partitions
  3. for humans easier to implement strategies

saving to json file took 20 minutes

I ran the default free-pio range and bet sizes (3betpotFAST tree) exactly using your .exe, it solved pretty smooth but then after achieving 0.5 accuracy it took more than 20 minutes to save it to .json file
the solving process took 80 something iteration under 2 minutes using only 1GB ram but then when it started saving it to json file, its memory usage exceeded my computer ram capacity (16GB) and program started paging.

here is my command line parameters:
set_pot 180
set_effective_stack 910
set_board Qs,Jh,2h
set_range_ip AA:0.25,99,88,77,66,55,44,33,22,AQo,AJ,AT,A9,A8,A7s,A6s,A5s,A4s,A3s,A2s,KQ,KJ,KT,K9,K8s,K7s,K6s,K5s,K4s,K3s,K2s,QJ,QT,Q9,Q8s,Q7s,Q6s,Q5s,Q4s,Q3s,Q2s,JT,J9,J8s,J7s,J6s,T9,T8s,T7s,T6s,98,97s,96s,95s:0.5,87s,86s,85s:0.5,76s,75s,74s:0.5,65s,64s,63s:0.5,54s,53s:0.5,43s
set_range_oop AA,KK,QQ,JJ,TT,99,88,AK,AQ,AJ,ATs,ATo:0.75,A9s,A8s,A5s:0.5,A4s:0.5,A3s:0.5,A2s:0.5,KQ,KJs,KJo:0.75,KTs,KTo:0.25,K9s,QJs,QJo:0.5,QTs,Q9s,JTs,JTo:0.25,J9s,J8s,T9s,T8s,T7s:0.45,98s,97s,96s:0.45,87s,86s:0.75,85s:0.45,76s:0.75,75s:0.75,74s:0.45,65s:0.75,64s:0.5,63s:0.45,54s:0.75,53s:0.5,52s:0.45,43s:0.5,42s:0.45,32s:0.45
set_bet_sizes oop,flop,bet,50
set_bet_sizes oop,flop,raise,50
set_bet_sizes ip,flop,bet,50
set_bet_sizes ip,flop,raise,50
set_bet_sizes oop,turn,bet,50
set_bet_sizes oop,turn,raise,50
set_bet_sizes ip,turn,bet,50
set_bet_sizes ip,turn,raise,50
set_bet_sizes oop,river,bet,50
set_bet_sizes oop,river,donk,50
set_bet_sizes oop,river,raise,50
set_bet_sizes ip,river,bet,50
set_bet_sizes ip,river,raise,50
set_allin_threshold 0.67
build_tree
set_thread_num 8
set_accuracy 0.5
set_max_iteration 200
set_print_interval 10
set_use_isomorphism 1
start_solve
set_dump_rounds 3
dump_result output_result.json

I needed river strategy so I used set_dump_rounds 3
Also the output file was 1GB or something like that

Very long computation time compared to piosolver

Thank you for your TexasSolver CPP code. I was trying to calculate strategy based on the settings like that:

set_pot 65
set_effective_stack 965
set_board Qs,Qh,2s
set_range_ip AA:0.1,KK:0.1,QQ:0.1,JJ:0.176470588,TT:0.235294118,99:0.9,88:0.9,77:0.9,66,55,44:0.9,33:0.7,22:0.7,AK:0.1,AQs:0.352941176,AQo:0.588235294,AJs:0.411764706,AJo:0.9,ATs:0.529411765,ATo:0.9,A9s:0.9,A9o,A8,A7s,A7o:0.9,A6s,A5s,A4s,A3s,A2s,KQs:0.647058824,KQo,KJs:0.705882353,KJo,KTs:0.764705882,KTo,K9,K8s,K8o:0.5,K7s,K6s,K5s,K4s:0.5,K3s:0.5,K2s:0.5,QJs:0.823529412,QJo,QTs:0.882352941,QTo,Q9,Q8s,Q7s,Q6s,JTs:0.9,JTo,J9,J8s,J7s,J6s:0.5,T9,T8s,T7s:0.7,T6s:0.5,98s,98o:0.5,97s,96s:0.5,87s,86s:0.9,85s:0.5,76s:0.9,75s:0.9,65s:0.9,64s:0.5,54s:0.9,53s:0.5,43s:0.5
set_range_oop AA,KK,QQ,JJ,TT,99,88,77,66,55,44:0.7,33:0.5,22:0.5,AK,AQ,AJ,AT,A9s,A9o:0.7,A8s,A8o:0.5,A7s,A6s,A5s,A4s,A3s,A2s,KQ,KJ,KT,K9s,K8s,K7s,K6s,K5s:0.5,K4s:0.5,K3s:0.2,QJ,QT,Q9s,Q8s,Q7s:0.2,JT,J9s,J8s,T9s,T8s,T7s:0.5,98s,97s,87s,86s:0.7,76s,75s:0.5,65s,64s:0.5,54s:0.7,43s:0.5
set_bet_sizes oop,flop,bet,33
set_bet_sizes oop,flop,raise,75
set_bet_sizes ip,flop,bet,33,75
set_bet_sizes ip,flop,raise,75
set_bet_sizes oop,turn,bet,33,75
set_bet_sizes oop,turn,donk,33,75
set_bet_sizes oop,turn,raise,75
set_bet_sizes ip,turn,bet,33,75
set_bet_sizes ip,turn,raise,75
set_bet_sizes oop,river,bet,33,75
set_bet_sizes oop,river,donk,33,75
set_bet_sizes oop,river,raise,75
set_bet_sizes oop,river,allin
set_bet_sizes ip,river,bet,33,75
set_bet_sizes ip,river,raise,50
set_bet_sizes ip,river,allin
set_allin_threshold 0.67
set_raise_limit 3
build_tree
set_thread_num 8
set_accuracy 0.35
set_max_iteration 200
set_print_interval 1
set_use_isomorphism 1
start_solve
set_dump_rounds 2
dump_result output_result.json

Output:

Iter: 91
player 0 exploitability -2.0042167
player 1 exploitability 6.2275276
Total exploitability 3.2487009 precent
time used: 4179.4

Piosolver Pro took about 10 min to solve this.
I waited almost one hour with TexasSolver to get some results.

Please let me know what I did wrong. Thank you in advance.

segfault using console-solver when checked out from source

If I build from source on linux I keep getting a segfault when testing the console-solver, here is the backtrace, it seems to work fine when single threaded, but 2 threads or more and it crashes, also the precompiled download works fine with 8 threads.

#run with 2 threads

home:~/TexasSolver/build$ gdb console_solver
(gdb) r -i ../resources/text/commandline_sample_input.txt
Starting program: /home/tj/TexasSolver/build/console_solver -i ../resources/text/commandline_sample_input.txt
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
EXEC FROM FILE

<<>>
Using 2 threads
Iter: 0
[New Thread 0x7ffff79f3700 (LWP 42537)]

Thread 1 "console_solver" received signal SIGSEGV, Segmentation fault.
0x00005555555e08b2 in std::_Hashtable<unsigned long, std::pair<unsigned long const, int>, std::allocator<std::pair<unsigned long const, int> >, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_find_before_node(unsigned long, unsigned long const&, unsigned long) const ()
(gdb) bt
#0 0x00005555555e08b2 in std::_Hashtable<unsigned long, std::pair<unsigned long const, int>, std::allocator<std::pair<unsigned long const, int> >, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_find_before_node(unsigned long, unsigned long const&, unsigned long) const
()
#1 0x00005555555df6ae in std::_Hashtable<unsigned long, std::pair<unsigned long const, int>, std::allocator<std::pair<unsigned long const, int> >, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_find_node(unsigned long, unsigned long const&, unsigned long) const ()
#2 0x00005555555df515 in std::__detail::_Map_base<unsigned long, std::pair<unsigned long const, int>, std::allocator<std::pair<unsigned long const, int> >, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true>, true>::operator[](unsigned long const&) ()
#3 0x00005555555de963 in std::unordered_map<unsigned long, int, std::hash, std::equal_to, std::allocator<std::pair<unsigned long const, int> > >::operator[](unsigned long const&) ()
#4 0x00005555555dd902 in Dic5Compairer::getRank(std::vector<int, std::allocator >) ()
#5 0x00005555555ddbc8 in Dic5Compairer::get_rank(std::vector<int, std::allocator >, std::vector<int, std::allocator >) ()
#6 0x00005555555ddca8 in Dic5Compairer::get_rank(unsigned long, unsigned long) ()
#7 0x0000555555605658 in RiverRangeManager::getRiverCombos(int, std::vector<PrivateCards, std::allocator > const&, unsigned long) ()
#8 0x000055555560c10b in BestResponse::showdownBestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int) ()
#9 0x000055555560a55f in BestResponse::bestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int)
()
#10 0x000055555560afe8 in BestResponse::actionBestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int) ()
#11 0x000055555560a4d0 in BestResponse::bestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int)
()
#12 0x000055555560b784 in BestResponse::actionBestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int) ()
#13 0x000055555560a4d0 in BestResponse::bestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int)
()
#14 0x000055555560cd55 in BestResponse::chanceBestReponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int) [clone ._omp_fn.0] ()
#15 0x00007ffff7c428e6 in GOMP_parallel () from /lib/x86_64-linux-gnu/libgomp.so.1
#16 0x000055555560aa82 in BestResponse::chanceBestReponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int) ()
#17 0x000055555560a67d in BestResponse::bestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int)
()
#18 0x000055555560afe8 in BestResponse::actionBestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int) ()
#19 0x000055555560a4d0 in BestResponse::bestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int)
()
#20 0x000055555560b784 in BestResponse::actionBestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int) ()
#21 0x000055555560a4d0 in BestResponse::bestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int)
()
#22 0x000055555560cd55 in BestResponse::chanceBestReponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int) [clone ._omp_fn.0] ()
#23 0x00007ffff7c428e6 in GOMP_parallel () from /lib/x86_64-linux-gnu/libgomp.so.1
#24 0x000055555560aa82 in BestResponse::chanceBestReponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int) ()
#25 0x000055555560a67d in BestResponse::bestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int)
()
#26 0x000055555560afe8 in BestResponse::actionBestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int) ()
#27 0x000055555560a4d0 in BestResponse::bestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int)
()
#28 0x000055555560b784 in BestResponse::actionBestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int) ()
#29 0x000055555560a4d0 in BestResponse::bestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int)
()
#30 0x000055555560a1b8 in BestResponse::getBestReponseEv(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > >, unsigned long, int) ()
#31 0x0000555555609f10 in BestResponse::printExploitability(std::shared_ptr, int, float, unsigned long) ()
#32 0x00005555555f5e40 in PCfrSolver::train() ()
#33 0x000055555558e423 in PokerSolver::train(std::__cxx11::basic_string<char, std::char_traits, std::allocator >, std::__cxx11::basic_string<char, std::char_traits, std::allocator >, std::__cxx11::basic_string<char, std::char_traits, std::allocator >, std::__cxx11::basic_string<char, std::char_traits, std::allocator >, int, int, std::__cxx11::basic_string<char, std::char_traits, std::allocator >, int, float, bool, int) ()
#34 0x0000555555588135 in CommandLineTool::processCommand(std::__cxx11::basic_string<char, std::char_traits, std::allocator >) ()
#35 0x00005555555873a4 in CommandLineTool::execFromFile(std::__cxx11::basic_string<char, std::char_traits, std::allocator >) ()
#36 0x000055555555de28 in main ()
(gdb)

#run started using default 8 threads

home:~/TexasSolver/build$ gdb console_solver
(gdb) r -i ../resources/text/commandline_sample_input.txt
Starting program: /home/tj/TexasSolver/build/console_solver -i ../resources/text/commandline_sample_input.txt
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
EXEC FROM FILE

<<>>
Using 8 threads
Iter: 0
[New Thread 0x7ffff79f3700 (LWP 42384)]
[New Thread 0x7ffff71f2700 (LWP 42385)]
[New Thread 0x7ffff69f1700 (LWP 42386)]
[New Thread 0x7ffff61f0700 (LWP 42387)]
[New Thread 0x7ffff59ef700 (LWP 42388)]
[New Thread 0x7ffff51ee700 (LWP 42389)]
[New Thread 0x7ffff49ed700 (LWP 42390)]

Thread 2 "console_solver" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff79f3700 (LWP 42384)]
0x00005555555e08b2 in std::_Hashtable<unsigned long, std::pair<unsigned long const, int>, std::allocator<std::pair<unsigned long const, int> >, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_find_before_node(unsigned long, unsigned long const&, unsigned long) const ()
(gdb) bt
#0 0x00005555555e08b2 in std::_Hashtable<unsigned long, std::pair<unsigned long const, int>, std::allocator<std::pair<unsigned long const, int> >, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_find_before_node(unsigned long, unsigned long const&, unsigned long) const
()
#1 0x00005555555df6ae in std::_Hashtable<unsigned long, std::pair<unsigned long const, int>, std::allocator<std::pair<unsigned long const, int> >, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_find_node(unsigned long, unsigned long const&, unsigned long) const ()
#2 0x00005555555df515 in std::__detail::_Map_base<unsigned long, std::pair<unsigned long const, int>, std::allocator<std::pair<unsigned long const, int> >, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true>, true>::operator[](unsigned long const&) ()
#3 0x00005555555de963 in std::unordered_map<unsigned long, int, std::hash, std::equal_to, std::allocator<std::pair<unsigned long const, int> > >::operator[](unsigned long const&) ()
#4 0x00005555555dd902 in Dic5Compairer::getRank(std::vector<int, std::allocator >) ()
#5 0x00005555555ddbc8 in Dic5Compairer::get_rank(std::vector<int, std::allocator >, std::vector<int, std::allocator >) ()
#6 0x00005555555ddca8 in Dic5Compairer::get_rank(unsigned long, unsigned long) ()
#7 0x0000555555605658 in RiverRangeManager::getRiverCombos(int, std::vector<PrivateCards, std::allocator > const&, unsigned long) ()
#8 0x000055555560c15f in BestResponse::showdownBestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int) ()
#9 0x000055555560a55f in BestResponse::bestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int)
()
#10 0x000055555560afe8 in BestResponse::actionBestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int) ()
#11 0x000055555560a4d0 in BestResponse::bestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int)
()
#12 0x000055555560b784 in BestResponse::actionBestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int) ()
#13 0x000055555560a4d0 in BestResponse::bestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int)
()
#14 0x000055555560cd55 in BestResponse::chanceBestReponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int) [clone ._omp_fn.0] ()
#15 0x00007ffff7c428e6 in GOMP_parallel () from /lib/x86_64-linux-gnu/libgomp.so.1
#16 0x000055555560aa82 in BestResponse::chanceBestReponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int) ()
#17 0x000055555560a67d in BestResponse::bestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int)
()
#18 0x000055555560afe8 in BestResponse::actionBestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int) ()
#19 0x000055555560a4d0 in BestResponse::bestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int)
()
#20 0x000055555560b784 in BestResponse::actionBestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int) ()
#21 0x000055555560a4d0 in BestResponse::bestResponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int)
()
#22 0x000055555560cd55 in BestResponse::chanceBestReponse(std::shared_ptr, int, std::vector<std::vector<float, std::allocator >, std::allocator<std::vector<float, std::allocator > > > const&, unsigned long, int) [clone ._omp_fn.0] ()
#23 0x00007ffff7c4a78e in ?? () from /lib/x86_64-linux-gnu/libgomp.so.1
#24 0x00007ffff7bfb609 in start_thread (arg=) at pthread_create.c:477
#25 0x00007ffff7b22293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
(gdb)

[Bug] Click Show result with no solution is buggy

Issue

If you click "Show result" when there is no solution, then the application quits and the parameters folder display is ruined. The default folder that is set to populate the parameters GUI is reset to C:

Platform
Windows 10
TexasSolver 0.2

Steps to reproduce

  1. Open the GUI
  2. Build a new tree but do not solve
  3. Click show result

Then, the application quits and the parameters window shows my C: folder.

image

How to import bindSolver ?

Traceback (most recent call last):
File "test.py", line 6, in
import bindSolver
ModuleNotFoundError: No module named 'bindSolver'

python test.py

Runtime error in a Mac

Recoding an error reported by a user using macOs

He meet this error when run 0.1.0 mac release

The error is:

dyld: Library not loaded: /usr/local/opt/gcc@7/lib/gcc/7/libgomp.1.dylib
Referenced from: /Users/guangsheng/poker/TexasSolver-v0/console_solver
Reason: image not found 

will look into the error

Memory usage C++ vs Java and speed

Hi, you mention that the C++ version is slower for flop solves than the Java version. Do they use similar amounts of memory? Also roughly how much slower?

Thanks for really neat software to play with.

Impossible combos

It's an intermittent yet recurrent issue that some combos that cannot still exist due to board cards (namely turn and river cards) are still present in ranges. It seems a particularly large issue far along the game tree where when only a few combos remain there is sometimes even a full 1.000 combos of an impossible holding. Here are 2 screenshots of the most recent, but it's been in at least my last two solves:
bug
bug2

Status and GUI

Hello,

Is this project still actively being worked on? Is there a status on the GUI for C++ version?

Thanks!

Enhancement Request: include board info and hand probability into output json

Thank you for the great solver!

I'm developing the output viewer (but still alpha...) and I would like output json include below:

  • board info
    output json does not have flop board card info, if it is added into the output json, viewer easily show board info from output json.

  • hand survival probability (from pre-flop)
    You can specify open percentages of each hands, for example 99 is 75%, however, in output json's strategy of 99, sum of each action is 1.0 for 99. If you calc survived hand percentage from pre-flop, we have to remember input open probability and also remember parent node's call percentage and multiply them.
    It would be useful if hands info of strategy contains survived percentage independently from action percentage.
    like this:
    2s2d:
    [0]: 0.99..
    [1]: 0.0012..
    [2]: 0.0000...
    survived: 0.75

MinGW-w64 required for console version

When run on Windows 10 from a vanilla Windows command prompt, console_solver.exe fails to execute with 4 instances of the following error:
image

The missing dlls it complains about are:

  • libgcc_s_seh-1.dll
  • libstdc++6.dll
  • libwinpthread-1.dll
  • libgomp-1.dll

Execution is successful if run from a MinGW-w64 terminal window.

Documentation needed on output.json

Hey, thank you for this awesome work!

I am interested in using the console solver for some private reports, and I was wondering if you have some more documentation on the structure of the output file. Espescially where do I find the frequencies, EVs & equities (if available)? I think I only see frequencies in the file, but maybe I am looking in the wrong places.

Thanks in advance!
Michael

Segfault after build install

Hello, thank you for this project!
I have a problem when try to build and start "make install" from master - it fails on test, and can't start solver (segfault).
If you need any additional info - please let me know.
CentOS 8.1 4.18.0-193.14.2.el8_2.x86_64
Name : cmake
Version : 3.18.2
Release : 11.el8_4

Name : make
Epoch : 1
Version : 4.2.1
Release : 10.el8

Name : gcc
Version : 8.4.1
Release : 1.el8

What I'm tried:

  65  2021-08-30 09:38:02 root pip3.9 install cmake --upgrade
   72  2021-08-30 09:39:56 root yum install gcc
   73  2021-08-30 09:40:19 root yum install gcc-c++
   74  2021-08-30 09:40:29 root cmake ..
   82  2021-08-30 09:41:34 root make install
   83  2021-08-30 09:42:32 root ./test

[root@build]# ./test

[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from TestCase
[ RUN      ] TestCase.test_poker_solver_bench
[##################################################] 100%
unknown file: Failure
C++ exception with description "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal" thrown in the test body.
[  FAILED  ] TestCase.test_poker_solver_bench (45493 ms)
[----------] 1 test from TestCase (45493 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (45493 ms total)
[  PASSED  ] 0 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] TestCase.test_poker_solver_bench

 **1 FAILED TEST**

[root@build]# ./console_solver -i ../resources/text/commandline_sample_input.txt

EXEC FROM FILE

<<<START SOLVING>>>
Using 8 threads
Iter: 0
**Segmentation fault (core dumped)**

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.