package tiny_libs
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
From-scratch libraries for teaching: graphics, audio, compression, crypto, networking and more
Install
dune-project
Dependency
Authors
Maintainers
Sources
0.3.6.tar.gz
md5=7c636383d146d30ac6f2fa234a6253c8
sha512=c79f3823c5f8f57e5038eb640d487c61168b84aa07c61999d6622ef9fd0c890e2b03b4c6a7cdbbe9352a49e25dda00ac7bb14693cee8e3d7beeed251351a2af0
doc/src/tiny_libs.ai_learning/Qlearn.ml.html
Source file Qlearn.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91(* Claude Code * * Copyright (C) 2026 Yoann Padioleau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * (LGPL) as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. *) (* See Qlearn.mli *) type ('state, 'action) t = { table : ('state * 'action, float) Hashtbl.t; rate : float; discount : float; explore : float; st : Random.State.t; } let make ?(rate = 0.2) ?(discount = 0.9) ?(explore = 0.1) ?(seed = 0) () : ('state, 'action) t = { table = Hashtbl.create 997; rate; discount; explore; st = Random.State.make [| seed |] } let value (q : ('state, 'action) t) (s : 'state) (a : 'action) : float = match Hashtbl.find_opt q.table (s, a) with Some v -> v | None -> 0. let values (q : ('state, 'action) t) (s : 'state) (actions : 'action list) : ('action * float) list = List.map (fun a -> (a, value q s a)) actions (* the best it knows of, ties going to the first: with an empty table * that is the first action, which is why a fresh learner walks in a * straight line until something pays *) let best (q : ('state, 'action) t) (s : 'state) (actions : 'action list) : 'action option = List.fold_left (fun best a -> match best with Some b when value q s b >= value q s a -> Some b | _ -> Some a) None actions let choose (q : ('state, 'action) t) (s : 'state) (actions : 'action list) : 'action option = match actions with | [] -> None | _ -> if Random.State.float q.st 1. < q.explore then Some (List.nth actions (Random.State.int q.st (List.length actions))) else best q s actions let learn (q : ('state, 'action) t) ~(state : 'state) ~(action : 'action) ~(reward : float) ~(next : 'state) ~(next_actions : 'action list) : unit = (* the best it could do next -- not what it will do, which is what * makes this off-policy *) let future = match next_actions with | [] -> 0. (* the end: there is no future to discount *) | _ -> List.fold_left (fun m a -> Float.max m (value q next a)) Float.neg_infinity next_actions in let was = value q state action in let target = reward +. (q.discount *. future) in Hashtbl.replace q.table (state, action) (was +. (q.rate *. (target -. was))) type ('state, 'action) world = { actions : 'state -> 'action list; step : 'state -> 'action -> 'state * float; over : 'state -> bool; } let episode ?(limit = 1000) (q : ('state, 'action) t) (w : ('state, 'action) world) (start : 'state) : float = let rec go state got left = if left = 0 || w.over state then got else match choose q state (w.actions state) with | None -> got | Some action -> let (next, reward) = w.step state action in let next_actions = if w.over next then [] else w.actions next in learn q ~state ~action ~reward ~next ~next_actions; go next (got +. reward) (left - 1) in go start 0. limit let greedy_run ?(limit = 1000) (q : ('state, 'action) t) (w : ('state, 'action) world) (start : 'state) : float * 'state list = let rec go state got path left = if left = 0 || w.over state then (got, List.rev (state :: path)) else match best q state (w.actions state) with | None -> (got, List.rev (state :: path)) | Some action -> let (next, reward) = w.step state action in go next (got +. reward) (state :: path) (left - 1) in go start 0. [] limit let known (q : ('state, 'action) t) : int = Hashtbl.length q.table
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>