import print import strutils import sequtils import std/math import std/sugar import std/algorithm ## Prediction type & helpers. type prediction = (string, float) # string represents a hypothesis, # prediction represents the predictionability mass proc comparePredictions (x: prediction, y: prediction): int = let (_, p1) = x let (_, p2) = y if p1 < p2: return 1 elif p1 > p2: return -1 else: return 0 proc getProbability (t: prediction): float = let (_, p) = t return p proc getHypothesis (t: prediction): string = let (h, _) = t return h ## Utils ## Find index (or -1) proc findIndex(xs: seq[string], y: string): int = for i, x in xs: if x == y: return i return -1 ## Get sequences ## let file_path = "../data/one_to_three" let file_path = "../data/stripped" proc getOEIS(): seq[seq[string]] = let f = open(file_path) var i = 0 var line : string var seqs: seq[seq[string]] while f.read_line(line): if i > 3: let seq = split(line, ",") let l = seq.len let nums = seq[1..(l-2)] seqs.add(nums) i = i + 1 f.close() return seqs var seqs = getOEIS() ## Sequence helpers proc startsWithSubsequence(subseq: seq[string], xs: seq[string]): bool = if subseq.len == 0: return true elif xs.len == 0: return false elif subseq[0] == xs[0]: return startsWithSubsequence(subseq[1.. p/sum) var next_and_ps = zip(nexts, ps) sort(next_and_ps, comparePredictions) # ^ sorts in place # also, openArray refers to both arrays and sequences. return next_and_ps ## Predict continuation but without access to all oeis sequences proc predictContinuationWithTruncatedHypotheses(seqs: seq[seq[string]], start: seq[string], num_hypotheses: int): seq[prediction] = let n = if num_hypotheses < seqs.len: num_hypotheses else: seqs.len let truncated_seqs = seqs[0.. getHypothesis(prediction)) let correct_continuation_index = findIndex(considered_continuations, correct_continuation) if correct_continuation_index == -1: var found_concordant_hypothesis = false var concordant_hypotheses: seq[seq[string]] while (not found_concordant_hypothesis) and ( num_hypotheses < seqs.len ): echo "Correct continuation, " , correct_continuation, " not found in set of hypotheses of size ", num_hypotheses, "/", seqs.len, ". Increasing size of the set of hypotheses." num_hypotheses = num_hypotheses + num_hypotheses_step if num_hypotheses > seqs.len: num_hypotheses = seqs.len hypotheses = seqs[0.. i) and startsWithSubsequence(observations[0..i], h)) if concordant_hypotheses.len > 0: found_concordant_hypothesis = true if not found_concordant_hypothesis: echo "Increased number of hypotheses to ", num_hypotheses, ", but didn't find any hypotheses concordant with observations. Giving up." return else: echo "Increased number of hypotheses to ", num_hypotheses, ", and found ", concordant_hypotheses.len, " concordant hypotheses. Continuing" ## print concordant_hypotheses else: echo "Correct continuation was ", correct_continuation echo "It was assigned a probability of ", getProbability(predictions[correct_continuation_index]) ## Infrabayesianism proc miniInfraBayesArgminMaxLoss( seqs: seq[seq[string]], observations: seq[string], n_observations_seen: int, utility_function: string ) = if utility_function != "logloss": echo "miniInfraBayes function only programmed for the logloss utility function" return else: echo "## Mini-infra-bayesianism over environments, where your utility in an environment is just the log-loss in the predictions you make until you become certain that you are in that environment." var losses: seq[float] for i in n_observations_seen.. getHypothesis(prediction)) let correct_continuation_index = findIndex(considered_continuations, correct_continuation) let p_correct_continuation = getProbability(predictions[correct_continuation_index]) let new_loss = ln(p_correct_continuation) losses.add(new_loss) echo "Correct continuation was ", correct_continuation echo "It was assigned a probability of ", p_correct_continuation echo "And hence a loss of ", new_loss echo "Total loss is: ", foldl(losses, a + b, 0.0) proc getEvens(xs: seq[string]): seq[string] = var evens: seq[string] for i,x in xs: if i mod 2 == 0: evens.add(x) return evens proc getOdds(xs: seq[string]): seq[string] = var odds: seq[string] for i,x in xs: if i mod 2 == 1: odds.add(x) return odds proc interleave(xs: seq[string], ys: seq[string]): seq[string] = if xs.len != ys.len: echo "Interleaved sequences have to have the same length; returning empty sequence." return @[] else: var zs: seq[string] for i in 0.. getHypothesis(prediction)) let correct_continuation_index = findIndex(considered_continuations, correct_continuation) let p_correct_continuation = getProbability(predictions[correct_continuation_index]) let new_loss = ln(p_correct_continuation) losses.add(new_loss) echo "Correct continuation was ", correct_continuation echo "It was assigned a probability of ", p_correct_continuation echo "And hence a loss of ", new_loss echo "Total loss is: ", foldl(losses, a + b, 0.0) ## Display outputs echo "" ## var observations = @["1", "2", "3", "4", "5", "6"] echo "## Full prediction with access to all hypotheses (~Solomonoff)" var observations = @["1", "2", "3"] echo "## Initial sequence: ", observations let continuation_probabilities = predictContinuation(seqs, observations) print continuation_probabilities echo "" echo "## Predictions with increasingly many hypotheses" observations = @["1", "2", "3", "23"] showPredictionsWithIncreasinglyManyHypotheses(seqs, observations) echo "" observations = @["1", "2", "3", "23", "11", "18", "77", "46", "84"] jitBayesLoop(seqs, observations, 3, 1_000, 30_000) echo "" observations = @["1", "2", "3", "23", "11", "18", "77", "46", "84"] miniInfraBayesArgminMaxLoss(seqs, observations, 3, "logloss") echo "" observations = interleave(@["1", "2", "3", "23", "11", "18", "77", "46", "84"], @["2", "11", "13", "23", "47", "59", "71", "83", "107"]) miniInfraBayesArgminMaxLossInterleavedHypotheses(seqs, observations, 6, "logloss") echo ""