/
query.go
105 lines (91 loc) · 2.51 KB
/
query.go
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package main
// Query - allows a user to query a Suiron knowledge base.
// Usage:
//
// > go run query.go test/kings.txt
//
// The command above will load facts and rules from kings.txt,
// and then prompt for a query with:
//
// Successfully loaded facts and rules from test/kings.txt
// ?-
//
// To find the grandchildren of Godwin, the user would type in
// the following query:
//
// ?- grandfather(Godwin, $X)
//
// ($X is a variable.)
//
// The Suiron inference engine will output one result after each
// press of 'enter'. When solutions are exhausted, the inference
// engine will print out 'No'.
//
// grandfather(Godwin, Harold)
// grandfather(Godwin, Skule)
// No
// ?-
//
// Type <enter> to end the program.
//
// Cleve Lendon
import (
. "github.com/indrikoterio/suiron/suiron"
"strings"
"errors"
"bufio"
"fmt"
"os"
)
func main() {
kb := KnowledgeBase{}
// Is there a file name?
if len(os.Args) > 1 {
fileName := os.Args[1]
if _, err := os.Stat(fileName); err == nil {
// Read in facts and rules.
err = LoadKBFromFile(kb, fileName)
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Printf("Successfully loaded facts and rules from %v\n", fileName)
} else if errors.Is(err, os.ErrNotExist) {
fmt.Printf("The file %v does not exist.\n", fileName)
return
}
} else {
fmt.Println("This is Suiron, an inference engine written in Go by Cleve Lendon.")
fmt.Println("To load knowledge> go run query rules.txt")
}
reader := bufio.NewReader(os.Stdin)
previous := "" // Previous query.
for {
fmt.Print("?- ") // Prompt for query.
q, _ := reader.ReadString('\n')
queryStr := strings.TrimSpace(q)
if len(queryStr) == 0 { break }
if queryStr == "." {
queryStr = previous
} else {
previous = queryStr
}
query, err := ParseQuery(queryStr)
if err != nil {
fmt.Println(err.Error())
continue
}
// Get the root solution node.
root := query.GetSolver(kb, SubstitutionSet{}, nil)
for {
solution, found := root.NextSolution()
if !found {
fmt.Println("No")
break
}
result := FormatSolution(query, solution)
fmt.Print(result)
_, _ = reader.ReadString('\n')
}
} // for
} // main