Skip to content

Commit c53544c

Browse files
committed
WIP: Add search into the core library.
TODO - [X] C++ lib - [X] Python lib - [ ] Javascript lib - [ ] C++ test - [ ] Python test - [ ] Javascript test
1 parent 5783fcb commit c53544c

File tree

11 files changed

+400
-259
lines changed

11 files changed

+400
-259
lines changed

examples/main.cc

Lines changed: 30 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -2,134 +2,54 @@
22
#include <cstring>
33
#include <functional>
44
#include <iostream>
5-
#include <map>
6-
#include <set>
75

86
#include <ds/ds.hh>
7+
#include <ds/search.hh>
98
#include <ds/utility.hh>
109

11-
struct PointerLess {
12-
template<typename T>
13-
bool operator()(const T& lhs, const T& rhs) const {
14-
if (lhs->data_size() < rhs->data_size()) {
15-
return true;
16-
}
17-
if (lhs->data_size() > rhs->data_size()) {
18-
return false;
19-
}
20-
ds::length_t data_size = lhs->data_size();
21-
const std::byte* lhs_data = reinterpret_cast<const std::byte*>(lhs.get());
22-
const std::byte* rhs_data = reinterpret_cast<const std::byte*>(rhs.get());
23-
for (ds::length_t index = 0; index < data_size; ++index) {
24-
if (lhs_data[index] < rhs_data[index]) {
25-
return true;
26-
}
27-
if (lhs_data[index] > rhs_data[index]) {
28-
return false;
29-
}
30-
}
31-
return false;
32-
}
33-
};
34-
3510
void run() {
3611
int temp_data_size = 1000;
3712
int temp_text_size = 1000;
3813
int single_result_size = 10000;
3914

15+
auto search = ds::search_t(temp_data_size, single_result_size);
16+
4017
// P -> Q, P |- Q
41-
auto mp = ds::text_to_rule(
42-
"(`P -> `Q)\n"
43-
"`P\n"
44-
"----------\n"
45-
"`Q",
46-
temp_data_size
47-
);
18+
search.add("(`P -> `Q)\n"
19+
"`P\n"
20+
"----------\n"
21+
"`Q\n");
4822
// p -> (q -> p)
49-
auto axiom1 = ds::text_to_rule(
50-
"------------------\n"
51-
"(`p -> (`q -> `p))\n",
52-
temp_data_size
53-
);
23+
search.add("(`p -> (`q -> `p))");
5424
// (p -> (q -> r)) -> ((p -> q) -> (p -> r))
55-
auto axiom2 = ds::text_to_rule(
56-
"--------------------------------------------------\n"
57-
"((`p -> (`q -> `r)) -> ((`p -> `q) -> (`p -> `r)))\n",
58-
temp_data_size
59-
);
25+
search.add("((`p -> (`q -> `r)) -> ((`p -> `q) -> (`p -> `r)))");
6026
// (!p -> !q) -> (q -> p)
61-
auto axiom3 = ds::text_to_rule(
62-
"----------------------------------\n"
63-
"(((! `p) -> (! `q)) -> (`q -> `p))\n",
64-
temp_data_size
65-
);
66-
67-
auto premise = ds::text_to_rule("(! (! X))", temp_data_size);
68-
auto target = ds::text_to_rule("X", temp_data_size);
27+
search.add("(((! `p) -> (! `q)) -> (`q -> `p))");
6928

70-
std::map<std::unique_ptr<ds::rule_t>, ds::length_t, PointerLess> rules;
71-
std::map<std::unique_ptr<ds::rule_t>, ds::length_t, PointerLess> facts;
29+
// premise
30+
search.add("(! (! X))");
7231

73-
std::set<std::unique_ptr<ds::rule_t>, PointerLess> temp_rules;
74-
std::set<std::unique_ptr<ds::rule_t>, PointerLess> temp_facts;
75-
76-
ds::length_t cycle = -1;
77-
rules.emplace(std::move(mp), cycle);
78-
facts.emplace(std::move(axiom1), cycle);
79-
facts.emplace(std::move(axiom2), cycle);
80-
facts.emplace(std::move(axiom3), cycle);
81-
facts.emplace(std::move(premise), cycle);
82-
83-
auto buffer = std::unique_ptr<ds::rule_t>(reinterpret_cast<ds::rule_t*>(operator new(single_result_size)));
84-
85-
auto less = PointerLess();
32+
auto target = ds::text_to_rule("X", temp_data_size);
8633

8734
while (true) {
88-
temp_rules.clear();
89-
temp_facts.clear();
90-
91-
for (auto& [rule, rules_cycle] : rules) {
92-
for (auto& [fact, facts_cycle] : facts) {
93-
if (rules_cycle != cycle && facts_cycle != cycle) {
94-
continue;
95-
}
96-
buffer->match(rule.get(), fact.get(), reinterpret_cast<std::byte*>(buffer.get()) + single_result_size);
97-
if (!buffer->valid()) {
98-
continue;
99-
}
100-
if (buffer->premises_count() != 0) {
101-
// rule
102-
if (rules.find(buffer) != rules.end() || temp_rules.find(buffer) != temp_rules.end()) {
103-
continue;
104-
}
105-
auto new_rule = std::unique_ptr<ds::rule_t>(reinterpret_cast<ds::rule_t*>(operator new(buffer->data_size())));
106-
memcpy(new_rule.get(), buffer.get(), buffer->data_size());
107-
temp_rules.emplace(std::move(new_rule));
108-
} else {
109-
// fact
110-
if (facts.find(buffer) != facts.end() || temp_facts.find(buffer) != temp_facts.end()) {
111-
continue;
112-
}
113-
auto new_fact = std::unique_ptr<ds::rule_t>(reinterpret_cast<ds::rule_t*>(operator new(buffer->data_size())));
114-
memcpy(new_fact.get(), buffer.get(), buffer->data_size());
115-
if ((!less(new_fact, target)) && (!less(target, new_fact))) {
116-
printf("Found!\n");
117-
printf("%s", ds::rule_to_text(new_fact.get(), temp_text_size).get());
118-
return;
119-
}
120-
temp_facts.emplace(std::move(new_fact));
121-
}
35+
bool success = false;
36+
auto callback = [&target, &success, &temp_text_size](ds::rule_t* candidate) {
37+
if (candidate->data_size() != target->data_size()) {
38+
return false;
12239
}
123-
}
124-
125-
++cycle;
126-
for (auto& rule : temp_rules) {
127-
auto& movable_rule = const_cast<std::unique_ptr<ds::rule_t>&>(rule);
128-
rules.emplace(std::move(movable_rule), cycle);
129-
}
130-
for (auto& fact : temp_facts) {
131-
auto& movable_fact = const_cast<std::unique_ptr<ds::rule_t>&>(fact);
132-
facts.emplace(std::move(movable_fact), cycle);
40+
auto data_size = candidate->data_size();
41+
auto equal = memcmp(candidate->head(), target->head(), data_size) == 0;
42+
if (equal) {
43+
printf("Found!\n");
44+
printf("%s", ds::rule_to_text(candidate, temp_text_size).get());
45+
success = true;
46+
return true;
47+
}
48+
return false;
49+
};
50+
search.execute(callback);
51+
if (success) {
52+
break;
13353
}
13454
}
13555
}

examples/main.mjs

Lines changed: 28 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,40 @@
1-
import { buffer_size, rule_t } from "../tsds/tsds.mts";
1+
import { rule_t, search_t } from "../tsds/tsds.mts";
22

3-
buffer_size(1000);
4-
5-
// biome-ignore format: 保持多行对齐
6-
// P -> Q, P |- Q
7-
const mp = new rule_t(
8-
"(`P -> `Q)\n" +
9-
"`P\n" +
10-
"----------\n" +
11-
"`Q\n");
12-
13-
// biome-ignore format: 保持多行对齐
14-
// p -> (q -> p)
15-
const axiom1 = new rule_t(
16-
"(`p -> (`q -> `p))"
17-
);
18-
19-
// biome-ignore format: 保持多行对齐
20-
// (p -> (q -> r)) -> ((p -> q) -> (p -> r))
21-
const axiom2 = new rule_t(
22-
"((`p -> (`q -> `r)) -> ((`p -> `q) -> (`p -> `r)))"
23-
);
3+
function main() {
4+
const temp_data_size = 1000;
5+
const single_result_size = 10000;
246

25-
// biome-ignore format: 保持多行对齐
26-
// (!p -> !q) -> (q -> p)
27-
const axiom3 = new rule_t(
28-
"(((! `p) -> (! `q)) -> (`q -> `p))"
29-
);
7+
const search = new search_t(temp_data_size, single_result_size);
308

31-
const premise = new rule_t("(! (! X))");
32-
const target = new rule_t("X");
33-
const target_hash = target.key();
9+
// P -> Q, P |- Q
10+
search.add("(`P -> `Q) `P `Q\n");
11+
// p -> (q -> p)
12+
search.add("(`p -> (`q -> `p))");
13+
// (p -> (q -> r)) -> ((p -> q) -> (p -> r))
14+
search.add("((`p -> (`q -> `r)) -> ((`p -> `q) -> (`p -> `r)))");
15+
// (!p -> !q) -> (q -> p)
16+
search.add("(((! `p) -> (! `q)) -> (`q -> `p))");
3417

35-
function main() {
36-
const rules = {};
37-
const facts = {};
18+
// premise
19+
search.add("(! (! X))");
3820

39-
let cycle = -1;
40-
rules[mp.key()] = [mp, cycle];
41-
facts[axiom1.key()] = [axiom1, cycle];
42-
facts[axiom2.key()] = [axiom2, cycle];
43-
facts[axiom3.key()] = [axiom3, cycle];
44-
facts[premise.key()] = [premise, cycle];
21+
const target = new rule_t("X");
4522

4623
while (true) {
47-
const temp_rules = {};
48-
const temp_facts = {};
49-
50-
for (const r_hash in rules) {
51-
for (const f_hash in facts) {
52-
const [rule, r_cycle] = rules[r_hash];
53-
const [fact, f_cycle] = facts[f_hash];
54-
if (r_cycle !== cycle && f_cycle !== cycle) {
55-
continue;
56-
}
57-
const candidate = rule.match(fact);
58-
if (candidate === null) {
59-
continue;
60-
}
61-
const candidate_hash = candidate.key();
62-
if (candidate.length() !== 0) {
63-
// rule
64-
if (candidate_hash in rules || candidate_hash in temp_rules) {
65-
continue;
66-
}
67-
temp_rules[candidate_hash] = candidate;
68-
} else {
69-
// fact
70-
if (candidate_hash in facts || candidate_hash in temp_facts) {
71-
continue;
72-
}
73-
if (candidate_hash === target_hash) {
74-
console.log("Found!");
75-
console.log(candidate.toString());
76-
return;
77-
}
78-
temp_facts[candidate_hash] = candidate;
79-
}
24+
let success = false;
25+
const callback = (candidate) => {
26+
if (candidate.key() === target.key()) {
27+
console.log("Found!");
28+
console.log(candidate.toString());
29+
success = true;
30+
return true;
8031
}
81-
}
32+
return false;
33+
};
8234

83-
cycle++;
84-
for (const r_hash in temp_rules) {
85-
const rule = temp_rules[r_hash];
86-
rules[rule.key()] = [rule, cycle];
87-
}
88-
for (const f_hash in temp_facts) {
89-
const fact = temp_facts[f_hash];
90-
facts[fact.key()] = [fact, cycle];
35+
search.execute(callback);
36+
if (success) {
37+
break;
9138
}
9239
}
9340
}

examples/main.py

Lines changed: 29 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,42 @@
11
import time
22
import pyds
33

4-
pyds.buffer_size(1000)
54

6-
# P -> Q, P |- Q
7-
mp = pyds.Rule("""
8-
(`P -> `Q)
9-
`P
10-
----------
11-
`Q
12-
""")
13-
14-
# p -> (q -> p)
15-
axiom1 = pyds.Rule("""
16-
------------------
17-
(`p -> (`q -> `p))
18-
""")
19-
20-
# (p -> (q -> r)) -> ((p -> q) -> (p -> r))
21-
axiom2 = pyds.Rule("""
22-
--------------------------------------------------
23-
((`p -> (`q -> `r)) -> ((`p -> `q) -> (`p -> `r)))
24-
""")
5+
def main():
6+
temp_data_size = 1000
7+
single_result_size = 10000
258

26-
# (!p -> !q) -> (q -> p)
27-
axiom3 = pyds.Rule("""
28-
----------------------------------
29-
(((! `p) -> (! `q)) -> (`q -> `p))
30-
""")
9+
search = pyds.Search(temp_data_size, single_result_size)
3110

32-
premise = pyds.Rule("(! (! X))")
33-
target = pyds.Rule("X")
11+
# P -> Q, P |- Q
12+
search.add("(`P -> `Q) `P `Q\n")
13+
# p -> (q -> p)
14+
search.add("(`p -> (`q -> `p))")
15+
# (p -> (q -> r)) -> ((p -> q) -> (p -> r))
16+
search.add("((`p -> (`q -> `r)) -> ((`p -> `q) -> (`p -> `r)))")
17+
# (!p -> !q) -> (q -> p)
18+
search.add("(((! `p) -> (! `q)) -> (`q -> `p))")
3419

20+
# premise
21+
search.add("(! (! X))")
3522

36-
def main():
37-
rules: dict[pyds.Rule, int] = {}
38-
facts: dict[pyds.Rule, int] = {}
39-
40-
cycle = -1
41-
rules[mp] = cycle
42-
facts[axiom1] = cycle
43-
facts[axiom2] = cycle
44-
facts[axiom3] = cycle
45-
facts[premise] = cycle
23+
target = pyds.Rule("X")
4624

4725
while True:
48-
temp_rules: set[pyds.Rule] = set()
49-
temp_facts: set[pyds.Rule] = set()
50-
51-
for rule, r_cycle in rules.items():
52-
for fact, f_cycle in facts.items():
53-
if r_cycle != cycle and f_cycle != cycle:
54-
continue
55-
candidate = rule @ fact
56-
if candidate is None:
57-
continue
58-
if len(candidate) != 0:
59-
# Rule
60-
if candidate in rules or candidate in temp_rules:
61-
continue
62-
temp_rules.add(candidate)
63-
else:
64-
# Fact
65-
if candidate in facts or candidate in temp_facts:
66-
continue
67-
if hash(candidate) == hash(target):
68-
print("Found!")
69-
print(candidate)
70-
return
71-
temp_facts.add(candidate)
72-
73-
cycle += 1
74-
for rule in temp_rules:
75-
rules[rule] = cycle
76-
for fact in temp_facts:
77-
facts[fact] = cycle
26+
success = False
27+
28+
def callback(candidate: pyds.Rule) -> bool:
29+
if candidate == target:
30+
print("Found!")
31+
print(candidate)
32+
nonlocal success
33+
success = True
34+
return True
35+
return False
36+
37+
search.execute(callback)
38+
if success:
39+
break
7840

7941

8042
for i in range(10):

0 commit comments

Comments
 (0)