Exemple #1
0
//  multaut displays a multi-NFA and multi-DFA
func multaut(w http.ResponseWriter, r *http.Request) {

	// must read all input before writing anything
	exprlist := getexprs(r)
	nx := len(exprlist)

	// parse and echo the input
	treelist := make([]rx.Node, 0, nx)
	putheader(w, r, "Multi-expression Automata")
	fmt.Fprintf(w, "<P class=xleading>%d expressions:\n", nx)
	for i, s := range exprlist {
		fmt.Fprintf(w, "<BR><B>%c:</B> &nbsp; %s\n",
			rx.AcceptLabels[i], hx(s))
		tree, err := rx.Parse(s)
		if !showerror(w, err) {
			treelist = append(treelist, rx.Augment(tree, i))
		}
	}

	if nx > 0 && len(treelist) == nx { // if no errors
		dfa := rx.MultiDFA(treelist) // build combined DFA
		dmin := dfa.Minimize()
		showaut(w, dmin, exprlist)
	}
	putfooter(w, r)
}
Exemple #2
0
//  combos responds to a comparison request for multiple expressions
func combos(w http.ResponseWriter, r *http.Request) {

	// must read all input before writing anything
	// first get the expressions, trimming leading/trailing blanks
	exprlist := getexprs(r)
	nx := len(exprlist)

	// then get the test strings; these are not trimmed
	testlist := make([]string, 0)
	for i := 0; i < maxTest; i++ {
		arg := r.FormValue(fmt.Sprintf("v%d", baseTest+i))
		if arg != "" {
			testlist = append(testlist, arg)
		}
	}

	// parse and echo the input
	putheader(w, r, "Compare Expressions")
	fmt.Fprintf(w, "<P class=xleading>%d expressions:\n", nx)
	treelist := lpxc(w, exprlist)

	if nx > 0 && len(treelist) == nx { // if no errors
		dfa := rx.MultiDFA(treelist) // build combined DFA
		trylist := make([]string, 0) // list of strings to try
		// tests from form submission
		for _, x := range testlist {
			trylist = append(trylist, x)
		}
		trylist = append(trylist, DRAWLINE)
		// examples from DFA
		synthx := dfa.Synthesize() // synthesize from DFA
		for _, x := range synthx { // put results on list
			trylist = append(trylist, x.Example)
		}
		// DON'T separate parse tree examples
		// (confusing in the the absence of a published explanation)
		// trylist = append(trylist, DRAWLINE)
		// examples from parse tree
		for i := 0; i < nx; i++ {
			trylist = append(trylist, rx.Specimen(treelist[i], 1))
			trylist = append(trylist, rx.Specimen(treelist[i], 2))
			trylist = append(trylist, rx.Specimen(treelist[i], 3))
			trylist = append(trylist, rx.Specimen(treelist[i], 5))
		}
		fmt.Fprintf(w, "<H2>Results</H2>\n")
		showgrid(w, dfa, nx, trylist) // show examples
	}

	fmt.Fprintln(w, "<P>&nbsp;")
	formlink(w, "/multaut", exprlist, "Show automata states")
	formlink(w, "/drawNFA", exprlist, "Draw the NFA")
	formlink(w, "/drawDFA", exprlist, "Draw the DFA")

	fmt.Fprint(w, "<h2>Try again?</h2>")
	putform(w, "/combos", "Enter regular expressions:",
		nExpr, exprlist, nTest, testlist)
	putfooter(w, r)
}
Exemple #3
0
func main() {
	// get command line options
	nways := 1
	if len(os.Args) == 3 {
		nways, _ = strconv.Atoi(os.Args[2])
	}
	if len(os.Args) < 2 || len(os.Args) > 3 || nways < 1 {
		log.Fatal("usage: rxtime exprfile [n]")
	}
	filename := os.Args[1]

	// load expressions from file
	exprs := rx.LoadExpressions(filename, nil)
	nexprs := len(exprs)
	if nways < 1 || nways > nexprs {
		log.Fatal(fmt.Sprintf(
			"cannot combine %d expressions(s) in %d way(s)",
			nexprs, nways))
	}

	// record individual complexity scores and make augmented parse trees
	cx := make([]int, nexprs)
	for i, t := range exprs {
		cx[i] = rx.ComplexityScore(t.Tree)
		t.Tree = rx.Augment(t.Tree, i)
	}

	// initialize index list for first combination {0,1,2...}
	xlist := make([]int, nways)
	for i := range xlist {
		xlist[i] = i
	}

	// try all possible n-way combinations by varying the index list
	tlist := make([]rx.Node, nways)
	for xlist != nil {
		for i, x := range xlist {
			tlist[i] = exprs[x].Tree
		}
		_ = rxsys.Interval()             // reset timer
		dfa1 := rx.MultiDFA(tlist)       // make DFA
		t1 := rxsys.Interval().Seconds() // measure time
		dfa2 := dfa1.Minimize()          // minimize DFA
		t2 := rxsys.Interval().Seconds() // measure time
		fmt.Printf("%6d %6d %8.3f %8.3f",
			len(dfa1.Dstates), len(dfa2.Dstates), t1, t2)
		if nways == 1 {
			fmt.Printf(" %6d", cx[xlist[0]])
		}
		fmt.Print("   {")
		for _, x := range xlist {
			fmt.Printf(" %d", x)
		}
		fmt.Print(" }\n")
		xlist = advance(xlist, nexprs) // get next combination
	}
}
Exemple #4
0
// main is the overall controller
func main() {
	setup()                      // initialize
	defer pprof.StopCPUProfile() // may have started profiling

	exprs, trees := load() // load input
	timestamp(fmt.Sprintf(
		"load %d expressions", len(exprs)))

	if !*opt['m'] { // if nothing uses a combined DFA
		return
	}
	if *opt['i'] { // if preceded by individual processing
		fmt.Println()
		rx.ShowLabel(os.Stdout, "MERGING EXPRESSIONS")
		fmt.Println()
		if *opt['R'] {
			rand.Seed(int64(seedvalue))
		}
	}

	dfa := rx.MultiDFA(trees)
	timestamp(fmt.Sprintf(
		"make merged DFA of %d states", len(dfa.Dstates)))
	dfa = showDFA(dfa, "Combined Tree", *opt['t'])

	// generate graphs if requested
	label := exprs[0].Expr
	if len(exprs) > 1 {
		label = fmt.Sprintf("%d expressions", len(exprs))
	}
	if *val['N'] != "" {
		rx.WriteGraph(*val['N'], func(w io.Writer) {
			dfa.GraphNFA(w, "NFA: "+label)
		})
	}
	if *val['D'] != "" {
		labels := ""
		if len(exprs) > 1 && len(exprs) <= len(rx.AcceptLabels) {
			labels = rx.AcceptLabels
		}
		rx.WriteGraph(*val['D'], func(w io.Writer) {
			dfa.ToDot(w, "DFA: "+label, labels)
		})
	}
}
Exemple #5
0
func main() {

	rflag := flag.Bool("R", false, "reproducible output")
	flag.Parse()
	if *rflag {
		rand.Seed(0)
	} else {
		rand.Seed(int64(time.Now().Nanosecond()))
	}

	// load and process regexps
	exprs := make([]*RegEx, 0)
	tlist := make([]rx.Node, 0)
	rx.LoadExpressions(rx.OneInputFile(), func(l *rx.RegExParsed) {
		if l.Err != nil {
			fmt.Fprintln(os.Stderr, l.Err)
		}
		if l.Tree != nil {
			atree := rx.Augment(l.Tree, len(tlist))
			tlist = append(tlist, atree)
			exprs = append(exprs, &RegEx{len(exprs), l.Expr})
		}
	})

	// echo the input with index numbers
	fmt.Print(`{"Expressions":`)
	rx.Jlist(os.Stdout, exprs)
	fmt.Println(",")

	// build the DFA and produce examples
	synthx := rx.MultiDFA(tlist).Synthesize()

	// convert into expected form with int array replacing BitSet
	results := make([]*Example, 0, len(synthx))
	for _, x := range synthx {
		results = append(results,
			&Example{x.State, x.RXset.Members(), x.Example})
	}

	// output the array of synthesized examples
	fmt.Print(`"Examples":`)
	rx.Jlist(os.Stdout, results)
	fmt.Println("}")
}
Exemple #6
0
//  draw produces a Dot file for rendering a DFA or NFA in the user's browser.
func draw(w http.ResponseWriter, r *http.Request, which string) {

	exprlist := getexprs(r) // must load data before writing anything
	nx := len(exprlist)

	putheader(w, r, which+" Graph") // write page header
	fmt.Fprintln(w, "<P class=xleading>")

	treelist := make([]rx.Node, 0)
	for i, e := range exprlist {
		if nx > 1 {
			fmt.Fprintf(w, "%c. &nbsp; ", rx.AcceptLabels[i])
		}
		fmt.Fprintf(w, "%s<BR>\n", hx(e))
		tree, err := rx.Parse(e)
		if !showerror(w, err) {
			treelist = append(treelist, rx.Augment(tree, i))
		}
	}

	if nx > 0 && len(treelist) == nx { // if no errors
		dfa := rx.MultiDFA(treelist) // build combined DFA
		dmin := dfa.Minimize()       // minimize it

		fmt.Fprintln(w, `<script type="text/vnd.graphviz" id="graph">`)
		if which == "NFA" {
			dmin.GraphNFA(w, "")
		} else if nx == 1 {
			dmin.ToDot(w, "", "")
		} else {
			which = "Multi"
			dmin.ToDot(w, "", rx.AcceptLabels)
		}
		fmt.Fprintln(w, `</script>`)

		tDraw.Execute(w, which)
	}
	putfooter(w, r)
}
Exemple #7
0
// refcompare advertises the Compare page
func refcompare(w http.ResponseWriter) {
	fmt.Fprintf(w, `
<P> The <A HREF="/compare">Compare</A> page accepts multiple expressions
and shows how their languages overlap or differ.
The results page shows synthesized examples and indicates which expressions
they match.
You can also submit your own examples for testing.
Again, there are links to produce automata diagrams.
<DIV CLASS="inblock xleading">
%d expressions:
`, len(HomeCompare))
	treelist := lpxc(w, HomeCompare)
	dfa := rx.MultiDFA(treelist)
	synthx := dfa.Synthesize()
	trylist := make([]string, 0)
	for _, x := range synthx {
		trylist = append(trylist, x.Example)
	}
	fmt.Fprintln(w, `<BR><BR>`)
	showgrid(w, dfa, len(treelist), trylist)
	fmt.Fprintln(w, `<DIV class="rside smaller">`)
	gencomp(w, "submit this example to see full output", HomeCompare)
	fmt.Fprintln(w, `</DIV></DIV>`)
}
Exemple #8
0
func main() {
	args := os.Args
	if len(args) != 3 {
		log.Fatal("usage: rxx efile sfile")
	}
	ename := args[1]
	sfile := rx.MkScanner(args[2])

	labels :=
		"123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
	elist := make([]tester, 0, len(labels))

	// load and compile regexps
	fmt.Println()
	tlist := make([]rx.Node, 0) // list of valid parse trees
	rx.LoadExpressions(ename, func(x *rx.RegExParsed) {
		spec := x.Expr
		ptree := x.Tree
		err := x.Err
		if err != nil {
			fmt.Printf("ERR %s\n", spec)
			elist = append(elist, tester{" ", spec, nil, 0})
		} else if ptree == nil {
			fmt.Printf("    %s\n", spec)
			elist = append(elist, tester{" ", spec, nil, 0})
		} else {
			i := len(tlist)
			if i >= len(labels) {
				log.Fatal("too many regular expressions")
			}
			label := string(labels[i : i+1])
			fmt.Printf("%s:  %s\n", label, spec)
			atree := rx.Augment(ptree, len(tlist))
			tlist = append(tlist, atree)
			elist = append(elist, tester{label, spec, ptree, i})
		}
	})

	dfa := rx.MultiDFA(tlist)
	_ = dfa.Minimize()   // should have no effect
	_ = dfa.Minimize()   // should again have no effect
	dfa = dfa.Minimize() // not necessary, but a good stress test
	dfa = dfa.Minimize() // especially if done more than once

	// read and test candidate strings
	fmt.Println()
	for sfile.Scan() {
		s := string(sfile.Bytes())
		results := dfa.Accepts(s)
		if results == nil {
			results = &rx.BitSet{}
		}
		for _, e := range elist {
			if e.tree == nil {
				fmt.Print(" ")
			} else {
				if results.Test(e.index) {
					fmt.Print(e.label)
				} else {
					fmt.Print("-")
				}
			}
		}
		fmt.Printf("  %s\n", s)
	}
	rx.CkErr(sfile.Err())
}
Exemple #9
0
//determines best question by the number of candidates that accept the question word.
func askBulk2(answers *rx.BitSet, qns []string, perm []int, cand []*rx.DFA, expns []*rx.RegExParsed, numPerGrp int) (*rx.BitSet, []string) {

	numGroups := math.Floor(float64(len(cand) / numPerGrp))
	word := ""

	if len(cand) < numPerGrp {
		numPerGrp = len(cand)
	}

	fmt.Println("length cand = ", len(cand))

	subjlist := make([]int, 0, *group)
	subjtrees := make([]rx.Node, 0, *group)
	expressions := make([]*RegEx, 0, len(cand))
	numKeep := make([]int, 0, int(numGroups))
	overlap := make([]*rx.BitSet, 0, int(numGroups))

	it := 0

	subjlist = make([]int, 0, *group)
	subjtrees = make([]rx.Node, 0, *group)
	expressions = make([]*RegEx, 0, len(cand))

	//create the grouping
	for j := it * int(numPerGrp); j < (it+1)*numPerGrp; j++ {
		subjlist = append(subjlist, perm[j])
		subjtrees = append(subjtrees, cand[perm[j]].Tree)
		expressions = append(expressions, &RegEx{perm[j], expns[perm[j]].Expr})
		fmt.Printf("rx { %d } %s \n", perm[j], expns[perm[j]].Expr)
	}

	//construct multi DFA
	fmt.Printf("Constructing multiDFA\n")
	dfa := rx.MultiDFA(subjtrees)
	//dfa = dfa.Minimize()
	h := dfa.Synthesize()
	for _, ex := range h {
		fmt.Printf("eg %s %s\n", ex.RXset, ex.Example)
	}

	u := make([]*rx.BitSet, 0, len(h))

	for i := 0; i < len(h); i++ {
		u = append(u, h[i].RXset)
	}

	//candidates
	alive := new(rx.BitSet)
	for i := 0; i < len(expressions); i++ {
		alive.Set(expressions[i].Index)
	}

	total := 0
	max := 0
	diff := float64(len(cand))
	half := math.Floor(float64(len(cand) / 2))
	maxWord := ""
	over := new(rx.BitSet)
	prevWord := make([]string, 0, len(cand))

	//iterate through all example words generated
	for j := 0; j < len(h); j++ {
		total = 0
		over = new(rx.BitSet) //tracks which candidates accept the question word
		//iterate through all candidates
		for i := 0; i < len(cand); i++ {
			//if the candidate accepts the example word, increment total and update bitset
			if cand[i].Accepts(h[j].Example) != nil {
				total++
				over.Set(i)
			}
		}
		//order question words according to the number of candidates that accept them
		if math.Abs(float64(total)-half) < float64(diff) {
			diff = math.Abs(float64(total) - half)
			max = total
			maxWord = h[j].Example
			prevWord = append(prevWord, maxWord)
			overlap = append(overlap, over)
		}

	}

	fmt.Println("max = ", max, " max word: ", maxWord)

	qns = append(qns, maxWord)
	numKeep = append(numKeep, int(max))

	fmt.Println("alive =", len(cand), ", max eliminate = ", max, ", maxWord =", maxWord)
	fmt.Printf("\n")

	answers = new(rx.BitSet)
	maybe := 0

	for i := 0; i < len(qns); i++ {
		//if answer is maybe, ask the next question in the list
	begin:
		if maybe > 0 {
			if len(prevWord) == 1 {
				qns[i] = h[maybe].Example
				fmt.Println("Does your language accept this word: ", h[maybe].Example)
			} else {
				qns[i] = prevWord[len(prevWord)-maybe-1]
				fmt.Printf("Does your language accept this word: %s, max over = %s\n", prevWord[len(prevWord)-maybe-1], overlap[len(overlap)-maybe-1].String())
			}
		} else {
			fmt.Println("Does your language accept this word: ", qns[i])
		}

		var input string
		_, e1 := fmt.Scan(&input)
		if e1 != nil {
			fmt.Printf("err = %#v\n", e1)
			os.Exit(2)
		}

		if input == "Yes" || input == "y" || input == "Y" || input == "yes" {

			answers.Set(i)

		} else if input == "No" || input == "N" || input == "n" || input == "no" {

		} else if input == "maybe" || input == "m" || input == "M" {
			maybe++
			goto begin
		} else {
			fmt.Println("That is not a valid expression, please try again.")
			fmt.Println("Does your language accept this word: ", word)
			goto begin
		}

	}
	fmt.Println("answers = ", answers.String())

	for i := 0; i < len(qns); i++ {
		fmt.Println(qns[i])
	}

	return answers, qns

}
Exemple #10
0
//used when candidate set partitioned. Asks the best question from each partition and records answers
func askBulk(answers *rx.BitSet, qns []string, perm []int, cand []*rx.DFA, expns []*rx.RegExParsed, numPerGrp int) (*rx.BitSet, []string) {

	numGroups := math.Floor(float64(len(cand) / numPerGrp))
	fmt.Println("num groups = ", numGroups)
	word := ""

	//modTest := math.Mod(float64(len(cand)), numGroups)

	//fmt.Println("testMod = ", modTest)

	subjlist := make([]int, 0, *group)
	subjtrees := make([]rx.Node, 0, *group)
	expressions := make([]*RegEx, 0, len(cand))

	for it := 0; it < int(numGroups/2); it++ {

		subjlist = make([]int, 0, *group)
		subjtrees = make([]rx.Node, 0, *group)
		expressions = make([]*RegEx, 0, len(cand))

		//create the grouping
		for j := it * int(numPerGrp); j < (it+1)*numPerGrp; j++ {
			subjlist = append(subjlist, perm[j])
			subjtrees = append(subjtrees, cand[perm[j]].Tree)
			expressions = append(expressions, &RegEx{perm[j], expns[perm[j]].Expr})
			fmt.Printf("rx { %d } %s\n", perm[j], expns[perm[j]].Expr)
		}

		//construct multiDFA
		fmt.Printf("Constructing multiDFA it = %d\n", it)
		dfa := rx.MultiDFA(subjtrees)
		//dfa = dfa.Minimize()
		h := dfa.Synthesize()
		//for _, ex := range h {
		//fmt.Printf("eg %s %s\n", ex.RXset, ex.Example)
		//}

		u := make([]*rx.BitSet, 0, len(h))

		//possible questions
		for i := 0; i < len(h); i++ {
			u = append(u, h[i].RXset)
		}

		//candidate set
		alive := new(rx.BitSet)
		for i := 0; i < len(expressions); i++ {
			alive.Set(expressions[i].Index)
		}

		//fmt.Println("alive = ", alive.String());

		//find best question and ask it
		i := 0
		n := float64(alive.Count() / 2)
		size := math.Floor(n)
		if alive.Count() < 4 && math.Mod(float64(alive.Count()), 2) == 1 {
			size = size + 1
		}
		cur := u[i].Count()
		c := float64(cur)
		hM := float64(math.Abs(c - size))
		word = h[i].Example

		for i := 0; i < len(u); i++ {
			c = float64(u[i].Count())
			if math.Abs(c-size) == 0 {
				word = h[i].Example
				break
			} else if math.Abs(c-size) < hM {
				hM = math.Abs(c - size)
				word = h[i].Example
			} else { /*do nothing*/
			}
		}
		fmt.Println("before qns append")

		qns = append(qns, word)
	}
	//rate questions and print rating
	rate := rateQns(qns, cand)

	for i := 0; i < len(rate); i++ {
		fmt.Println(rate[i], " dfas accepted this word ", qns[i])
	}

	for i := 0; i < len(qns); i++ {

	begin:
		//ask questions
		fmt.Println("Does your language accept this word (): ", qns[i])

		var input string
		_, e1 := fmt.Scan(&input)
		if e1 != nil {
			fmt.Printf("err = %#v\n", e1)
			os.Exit(2)
		}

		if input == "Yes" || input == "y" || input == "Y" || input == "yes" {
			answers.Set(i)

		} else if input == "No" || input == "N" || input == "n" || input == "no" {

		} else {
			fmt.Println("That is not a valid expression, please try again.")
			fmt.Println("Does your language accept this word: ", word)
			goto begin
		}

	}
	fmt.Println("answers = ", answers.String())

	return answers, qns

}