Example #1
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

}
Example #2
0
//original recursive algorithm that attempts to eliminate half candidates with each question
func askQuestions(u []*rx.BitSet, h []rx.DFAexample, e []*RegEx, alive *rx.BitSet, track int, iter int, answers *rx.BitSet, qns []string, cand []*rx.DFA) ([]*rx.BitSet, []rx.DFAexample, *rx.BitSet, []string) {

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

	//none left alive, means there is no match in the corpus
	if alive.Count() == 0 {
		fmt.Println("No reg ex in our library matches your query.")
		fmt.Println("answers after iter = ", iter, " ", answers.String())
		return t, k, answers, qns
	}

	//if there was at least 1 yes answer and only 1 remaining expr alive, it must be accepted by the target
	if track >= 1 {
		if alive.Count() == 1 {
			if findQn(alive, h) != "" {
				answers.Set(iter)
				qns = append(qns, findQn(alive, h))
			}
			fmt.Println("answers after iter = ", iter, " ", answers.String())
			return t, k, answers, qns
		}
	}

	//if there were 0 yes answers and there is 1 remaining, must ask again or return no match
	if track == 0 && alive.Count() == 1 {
		if len(u) == 0 {
			fmt.Println("No reg ex in our library matches your query.")
			fmt.Println("answers after iter = ", iter, " ", answers.String())
			return t, k, answers, qns
		} else {
			goto askAgain
		}

	askAgain:
		//ask last question
		qns = append(qns, h[0].Example)
		fmt.Println("Does your language accept this word: ", h[0].Example)

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

		if input1 == "Yes" || input1 == "y" || input1 == "Y" || input1 == "yes" {
			track++
			answers.Set(iter)
			fmt.Println("answers after iter = ", iter, " ", answers.String())
			return t, k, answers, qns
		} else if input1 == "No" || input1 == "N" || input1 == "n" || input1 == "no" {
			fmt.Println("No reg ex in our library matches your query.")
			fmt.Println("answers after iter = ", iter, " ", answers.String())
			return t, k, answers, qns
		} else {
			fmt.Println("That is not a valid expression, please try again.")
			goto askAgain
		}

	}

	//if 0 yes answers, and no more questions, no match found
	if track == 0 && len(u) == 0 {
		fmt.Println("No reg ex in our library matches your query.")
		return t, k, answers, qns
	}

	//if no more questions but more than 1 candidate, find the next question
	if len(u) == 0 && alive.Count() > 1 {
		qns = append(qns, findQn(alive, h))
		return t, k, answers, qns
	}

	//Iterate through u to find the rx.BitSet with numleft/2 bits set to 1
	i := 0
	n := float64(alive.Count() / 2)
	size := math.Floor(n)
	//if small enough set, take the cieling
	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))
	nextQn := u[i]
	word := h[i].Example
	examInt := i

	//find the region that is the intersection of n/2 regexs (or closest to n/2)
	for i := 0; i < len(u); i++ {
		c = float64(u[i].Count())
		if math.Abs(c-size) == 0 {
			nextQn = u[i]
			word = h[i].Example
			examInt = i
			break
		} else if math.Abs(c-size) < hM {
			hM = math.Abs(c - size)
			nextQn = u[i]
			word = h[i].Example
			examInt = i
		} else { /*do nothing*/
		}
	}

	qns = append(qns, word)    //append question to list
	rate := rateQns(qns, cand) //rate the questions

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

	//ask if the best question word is accepted
	fmt.Println("Does your language accept this word: ", word)

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

	//Refine the candidate set based on the answer
	if input == "Yes" || input == "y" || input == "Y" || input == "yes" {
		track++
		if nextQn.Count() == 1 {
			t = append(t, nextQn)
			k = append(k, h[examInt])
			answers.Set(iter)
			fmt.Println("answers after iter = ", iter, " ", answers.String())
			return t, k, answers, qns
		}
		answers.Set(iter)
		alive = alive.And(nextQn)
		for i := 0; i < len(u); i++ {
			if !((nextQn.And(u[i])).IsEmpty()) && !(nextQn.Equals(u[i])) {
				t = append(t, u[i])
				k = append(k, h[i])
			}
		}

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

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

		bs := new(rx.BitSet)
		for i := 0; i < len(e); i++ {
			if !(nextQn.Test(e[i].Index)) {
				bs.Set(e[i].Index)
			}
		}

		alive = bs.And(alive)
		for i := 0; i < len(u); i++ {
			if !((bs.And(u[i])).IsEmpty()) {
				t = append(t, u[i])
				k = append(k, h[i])
			}
		}

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

	} 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 after iter = ", iter, " ", answers.String())
	iter++

	//recursive call on the new candidate set
	return askQuestions(t, k, e, alive, track, iter, answers, qns, cand)
}