Save the following as test.pgn

[Event "Gothenburg-B"]
[Site "Gothenburg"]
[Date "1920.??.??"]
[Round "14"]
[White "Euwe, Max"]
[Black "Larsson, Anders"]
[Result "1-0"]
[BlackElo ""]
[ECO "D66"]
[WhiteElo ""]

1. d4 d5 2. Nf3 e6 3. c4 Nf6 4. Nc3 Nbd7 5. Bg5 Be7 6. e3 O-O 7. Rc1 c6 8. Bd3
h6 9. Bh4 dxc4 10. Bxc4 Nd5 11. Bg3 b6 12. O-O Bb7 13. Qe2 a6 14. Rfd1 b5 15.
Bb3 Rc8 16. a4 Nxc3 17. Rxc3 Qb6 18. Ne5 Nf6 19. Bh4 Rfd8 20. Rdc1 Rc7 21. Qc2
Nd5 22. Bxd5 Bxh4 23. Bxc6 b4 24. Rc5 Be7 25. a5 Qa7 26. Rc4 Bd6 27. Bxb7 Rxc4
28. Qxc4 Bxe5 29. Qxa6 Bb8 30. Qxa7 Bxa7 31. Rc8 Rxc8 32. Bxc8 Kf8 33. Kf1 Ke8
34. Ke2 Kd8 35. Bb7 Kc7 36. Bf3 Bb8 37. Kd3 Kc8 38. g3 Bc7 39. a6 Kb8 40. Kc4
Ka7 41. Kb5 Bd8 42. b3 f5 43. Bb7 g5 44. Kc6 f4 45. Kd7 fxe3 46. fxe3 Bb6 47.
Kxe6 Kb8 48. Kf5 1-0

Then import it with:

pgns = Import["test.pgn"]

(** Entity["Person", "AndersLarsson::r49h5"] **)

... and you get this annoying Entity instead of just a plain old string. If we look at White we get a normal string instead!

(** "Euwe, Max" **)

Is there a way to prevent the creation of entities here? This is a simple example, but I've found when importing very large pgn files containing thousands of games, the Entity objects slow it down significantly. Not only that, but it makes accessing this data much harder because sometimes the player name will be an entity and sometimes it's a string when it's not known to Wolfram.

I know about EntityValue[..., "Name"] but I don't want to have to use it when the name has an Entity head, and besides it's slow. I'd rather just get strings straight from the Import and not have to deal with Entity at all.


2 Answers 2


The preferred way of skipping SemanticInterpretation on import of PGN metadata is to use the "RawMetadata" element. It returns all metadata as strings, exactly as they are stored in the file:

In[16]:= Import["/tmp/test.pgn", "RawMetadata"]

Out[16]= {<|"Black" -> "Larsson, Anders", "BlackElo" -> "", 
  "Date" -> "1920.??.??", "ECO" -> "D66", "Event" -> "Gothenburg-B", 
  "Result" -> "1-0", "Round" -> "14", "Site" -> "Gothenburg", 
  "White" -> "Euwe, Max", "WhiteElo" -> ""|>}

"RawMetadata" is also a property of the ChessGame object:

In[28]:= game = First @ Import["/tmp/test.pgn"]

Out[28]= ChessGame[<...>]

In[29]:= game["RawMetadata"]

Out[29]= <|"Black" -> "Larsson, Anders", "BlackElo" -> "", 
 "Date" -> "1920.??.??", "ECO" -> "D66", "Event" -> "Gothenburg-B", 
 "Result" -> "1-0", "Round" -> "14", "Site" -> "Gothenburg", 
 "White" -> "Euwe, Max", "WhiteElo" -> ""|>

In the Wolfram Chess paclet's Common.wl file, we can see that it tries to interpret the name as a person entity:

(* try to interpret the name into Entity with memoization (this is crucial in terms of performance) *)
interpretPerson[name_] := interpretPerson[name] = SemanticInterpretation[parsedName, Entity["Person", __]];

We can restart the kernel from a clean slate and hack the built-in definition of SemanticInterpretation by replacing it with a function that just returns the first argument. This will be a string. Entities be gone!

SemanticInterpretation = #1 &;
pgns = Import["test.pgn"]

(** "Anders Larsson" **)

Thanks to @Domen, a more specific solution is to define:
Wolfram`Chess`Common`Private`interpretPerson[name_] := name;

... after loading Wolfram Chess, which avoids breaking other uses of SemanticInterpretation elsewhere.

  • 2
    $\begingroup$ I believe Wolfram`Chess`Common`Private`interpretPerson[name_] := name; is a more suitable and targeted solution than overloading a much more general SemanticInterpretation ... $\endgroup$
    – Domen
    Nov 24, 2023 at 15:33
  • $\begingroup$ @Domen thanks, updated. $\endgroup$
    – flinty
    Nov 24, 2023 at 15:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.