Skip to content
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

[BUG] Adding value to Dictionary leads to hang sometimes #726

Closed
1 task done
liz3 opened this issue Jan 16, 2024 · 0 comments · Fixed by #728
Closed
1 task done

[BUG] Adding value to Dictionary leads to hang sometimes #726

liz3 opened this issue Jan 16, 2024 · 0 comments · Fixed by #728
Labels
bug Something isn't working

Comments

@liz3
Copy link
Contributor

liz3 commented Jan 16, 2024

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

Apologies that the code is a bit bigger, but i thought maybe it helps pin down the issue.
This code is a implementation of Karger's algorithm for the Advent of code coding Puzzle 2023 day 25.

Sometimes this section hangs forever either in the first assigment(n1[rr.first] = 1; or the second n2[k] = 1;):

var edgesToMerge = nodes[rr.second].edges;
edgesToMerge.forEach(def (k, v) => {
  print("start forEach call");
  print("1: removing {} from {} in {}".format(rr.second, nodes[k].edges, k));
  nodes[k].edges.remove(rr.second);
  var n1 = nodes[k].edges;
  print("1: adding {} into {} in {}".format(rr.first, n1, k));
  n1[rr.first] = 1;
  var n2 = nodes[rr.first].edges;
  print("2: adding {} into {} in {}".format(k, n2, rr.first));
  n2[k] = 1;
  print("end forEach call");
});

But again only sometimes, the other times the program ends successfully.

Expected Behavior

The program should not lock during the assigment into the Dictionary

Steps To Reproduce

  1. Create input.txt from given file
jqt: rhn xhk nvd
rsh: frs pzl lsr
xhk: hfx
cmg: qnr nvd lhk bvb
rhn: xhk bvb hfx
bvb: xhk hfx
pzl: lsr hfx nvd
qnr: nvd
ntq: jqt hfx bvb xhk
nvd: lhk
lsr: lhk
rzs: qnr cmg lsr rsh
frs: qnr lhk lsr
  1. Create a file from the given source code:
import Random;
import Queue;
class Node {
init(var name, var edges) {}
}
class Edge {
init(var first, var second, var origFirst, var origSecond) {}

}
with("input.txt", "r") {
  var line;
  var lines = [];
  var origNodes = {};
  // When you reach the end of the file, nil is returned
  while((line = file.readLine()) != nil) {
      lines.push(line);
      var parts = line.split(" ");
      parts[0] = parts[0][0:parts[0].find(":")];

      parts.forEach(def (entry) => {
         if(not origNodes.exists(entry)) {
             var n = Node(entry, {});
             origNodes[entry] = n;
          }
      });

  }
  var pp = [];
  lines.forEach(def (l) => {
      var parts = l.split(" ");
      parts[0] = parts[0][0:parts[0].find(":")];
      const f = parts[0];
      if(parts.len() > 1) {
          var sub = parts[1:];
          sub.forEach(def (p) => {
              origNodes[f].edges[p] = 1;
              origNodes[p].edges[f] = 1;
              var e = Edge(f, p, f, p);
              pp.push(e);
          });

      }
  });
  var found = [];
  while {
    var pairs = pp.deepCopy();
    var nodes = origNodes.deepCopy();
    while(pairs.len() > 3) {
      const index = Random.range(0, pairs.len()-1);
      var rr = pairs.pop(index);
      nodes[rr.first].edges.remove(rr.second);
      nodes[rr.second].edges.remove(rr.first);

      var indexes = [];
      for(var i = 0; i < pairs.len(); i += 1) {
        const p = pairs[i];
        if((p.first == rr.first or p.second == rr.first) and (p.first == rr.second or p.second == rr.second)) {
          indexes.push(p);
        }
      }
      indexes.reverse();
      indexes.forEach(def (i) => pairs.remove(i));

      var edgesToMerge = nodes[rr.second].edges;
      edgesToMerge.forEach(def (k, v) => {
        print("start forEach call");
        print("1: removing {} from {} in {}".format(rr.second, nodes[k].edges, k));
        nodes[k].edges.remove(rr.second);
        var n1 = nodes[k].edges;
        print("1: adding {} into {} in {}".format(rr.first, n1, k));
        n1[rr.first] = 1;
        var n2 = nodes[rr.first].edges;
        print("2: adding {} into {} in {}".format(k, n2, rr.first));
        n2[k] = 1;
        print("end forEach call");
      });

      for(var i = 0; i < pairs.len(); i += 1) {
         var p = pairs[i];
         if(p.first == rr.second) {
              p.first = rr.first;
              pairs[i] = p;
          } else if (p.second == rr.second) {
              p.second = rr.first;
              pairs[i] = p;

          }
      }
    }
    if(not (pairs.len() == 3))
      continue;
    pairs.forEach(def(v) => found.push([v.origFirst, v.origSecond]));
    break;
  }
  print(found);
  const q = Queue.new();
  var nodes = origNodes.deepCopy();
  found.forEach(def (v) => {
    nodes[v[0]].edges.remove(v[1]);
    nodes[v[1]].edges.remove(v[0]);
  });
  var left = set();
  const k = nodes.keys()[0];
  q.push(k);
  while(q.len()) {
    const elem = q.pop();
    if(elem == 0)
      continue;
    if(left.contains(elem))
      continue;
    left.add(elem);
    nodes[elem].edges.forEach(def (k, v) => {
  q.push(k);
  });
  }
  const answer = left.len() * (nodes.len()- left.len());
  print(answer);
}
  1. run the Programm repeatedly until it hangs following one of the prints print("1: adding {} into {} in {}".format(rr.first, n1, k)); or print("2: adding {} into {} in {}".format(k, n2, rr.first));

Anything else?

System: Darwin Kernel Version 23.2.0: Wed Nov 15 21:53:18 PST 2023; root:xnu-10002.61.3~2/RELEASE_ARM64_T6000 arm64

Build commit: 97de4c1a6932a884e7cecf9456ebf5d929d3da06

Clang:
Homebrew clang version 17.0.6
Target: arm64-apple-darwin23.2.0
Thread model: posix

Cmake: cmake version 3.27.7

@liz3 liz3 added the bug Something isn't working label Jan 16, 2024
@liz3 liz3 changed the title [BUG] Adding value to Dictionary locks sometimes [BUG] Adding value to Dictionary leads to hang sometimes Jan 16, 2024
liz3 added a commit to liz3/Dictu that referenced this issue Jan 16, 2024
The dict findDictEntry function did not correctly handle the case when,
a dict had no "free" slot but had tombstones, it would loop forever.

This fixes that by conditionally returning a tombstone when all other indexes where processed.
Fixes: dictu-lang#726
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant