A Program Finder (pf1) (one instance of one replace predicate) - inputs: i's,o's - outputs: program1 - pfpf takes [i's,o's of program x pf1, xx] program1[s xxx] as inputs outputs: a pf2 (replace, delete xx) [if program->program - takes care of specific commands and arguments in predicate instances - combines predicates - each predicate instance may operate on different input(s) single type eg replace and single idea X] - must output multiple predicates from pf - pf2 is pf1 of p1 x - must find eg replace, delete predicates - given inputs i's,o's to pf1, runs modified pf1 on pf1 pfpfpf - takes [i's o's, ps x, of pf2s xx] pf2s x (from pfpf - replace, delete x, member x) - out: pfpf - pfpf is pf1or2 of pf2 x - given inputs i's,o's to pf[1or x]2, runs modified pf[1or x]2 on pf2 Just concatenates them x finds general cases pf of pf is really pf and pf x will the programs i->o correctly x should io from pf be used in later programs x *-for phil 6x n levels of pf for enough correctness - necessary for (some) assignments - other factors in correctness, pf1 code and data are affected by regression testing * pf's use (*2) - automation - accuracy in types, etc. bug checking pfs - check i against o per predicate instance - pf: must be given i's, o's for each predicate in the program *regression (return to results/positivity) when programs that program finders produce are run, which may need further pfs to correct code as pf is run, more possible o's for predicates accounted for, making development faster - can generate philosophical list prolog code more easily - bug checks - pf - interpreter pf: non-child predicates are treated in the same way as child predicates, i.e. patterns are found, broken down and programmed - ff, logic ff - if there is e.g. finding a number of instances of phrases across grammars, then it will detect and do this - test combinations of these operations (e.g. counting, traversing, replacing, etc.), like formula finder - appropriate for i's, o's - and as a formula finder operation - in prolog formal finder, inserts command if data suggests it is needed - e.g. replace is recognised to to be needed as main called predicate - other calls are predicted by the data complexity (lists) - finds 2p e.g. two lists being co-processed - () even though pfpf takes i's, o's of program as input, a pfpf has the aforementioned advantages (*2 above) it should rewrite the predicate without "cheating" by looking at the code, because of the advantages. - the i's o's given are of the program we want to find the pf for, not the original program - () above pf, it just verifies code by rewriting it - a test finds what (emdar, emar, etc. is used) then finds this code (emdar, emar, etc.) how to modify emar, etc. - tries with, without commands and predicate calls at points. e.g. append not used if verifying list (this will be evident in output) - () could find predicates and their sub-predicates by trial and error - repeats emar etc test for possible subpredicates - structure of code as data should be analysed (same predicate names and their arguments) to find right location of running, how code calling emars etc work (the i's o's from programs really will be taken, given to pf by itself) code calling emars - what list is being processed? - by i's o's - predicates need some lists that are used by them passed down to them - buildpredicate predicate will be recognised as building emar etc from i's o's, rewritten bug check - how will it write code that writes code in LIP? - use var not upper case, replace with uppercase before lpi (*1) x will replace upper case with lower case in next level down x converts first instance (*1 above) from var to capitalised in next level down x need to concatenate code and variables together in lip