Dec-01-2018, 01:38 AM
''' Here is some short code which is rather self-contained and is somewhat difficult to write making it perfect for sharing. So here are the rules, hopefully you're familiar with the propositional logic formulas which look like this: p → (q & r) Things become much more difficult if the sentences which p, q and r stand for have words in them like 'something'. So, for example, 'if something is a man, then it is mortal'. It is obvious that I can replace 'something' with 'Socrates' and get the conditional: 'if Socrates is a man, then he is mortal'. What if you have something more complicated? Suppose we want to define the word 'during'. A reasonable definition might be: event b [occurs] during period c iff period c has moment d and b [occurs] at d We could then abbreviate the sentences as: p = event b [occurs] during period c q = period c has moment d r = b [occurs] at d which would give us: p ≡ (q & r) The problem with the above definition is the location of the word 'iff'. Suppose I believe falsely that: event b [occurs] during [the entirety of] period c and period c has moment d and event b was not in progress at moment d. It turns out that if we have to be able to switch the sentences around, like so: If event b [occurs] during [all of] period c and period c has moment d then b [occurs] at d But we can also do: If period c has moment d and event b [occurs] at d then event b [occurs] during period c. Now for pedagogical reasons I had to simplify things but for quite complicated reasons, we cannot do: If period c has moment d then event b [occurs] at d and event b [occurs] during period c. This is mostly because in the real definitions you don't put the words 'period' and 'event' in the sentence but just 'has' which would give us: If c has d then b [occurs] at d and b [occurs] during c. which of course is not true because c could be just a geometric shape and not a period. So in any case we have to be able to handle sentences which move around between the ≡ → signs. So here are the rules I've adopted, the following: A sentence which is left of the ⊳ can only be right of the → sign if it is the only sentence to the right of the → sign. Other than that every combination is possible p ⊳ q ⊗ r can be transformed into: p → (q & r) (p & r) → q (p & q) → r (q & r) → p but not (r → (p & q) (q → (p & r) because if p is to the right of → then it can be the only sentence which appears to the right of → We can also have any number of ⊗ signs, so we can also have p ⊳ q ⊗ r ⊗ s p ⊳ q ⊗ r ⊗ s ⊗ t For the purposes of the following algorithm I simply number the sentences starting at 1.1 and number them 1.2, 1.3 and so on. We then need to split the sentences into two categories and antecedent and a consequent. So if we number the sentences as follows: p = 1.1 q = 1.2 r = 1.3 s = 1.4 and if we have 4 sentences then this will return a list which looks like this: [ [['1.1', '1.2'], ['1.3', '1.4']], [['1.1', '1.3'], ['1.2', '1.4']], [['1.1', '1.4'], ['1.2', '1.3']], [['1.1', '1.2', '1.3'], ['1.4']], [['1.1', '1.2', '1.4'], ['1.3']], [['1.1', '1.3', '1.4'], ['1.2']], [['1.1'], ['1.3','1.2', '1.4']], [['1.4', '1.3','1.2'], ['1.1']], ] ''' import ujson # i use ujson instead of deepcopy so if you don't have ujson you can just use deepcopy from itertools import chain, combinations jsonc = lambda x: ujson.loads(ujson.dumps(x)) def powerset(list1): '''not written by me''' b = chain.from_iterable(combinations(list1, r) for r in range(len(list1) + 1)) return [set(x) for x in b] def build_lst_nums(): dict1 = {} for x in range(4, 7): dict1[x] = build_lst_nums2(x) return dict1 def build_lst_nums2(num): lst = ["1." + str(x) for x in range(1, num + 1)] main_lst = jsonc(lst) main_lst.remove('1.1') lst_nums = [ [['1.1'], lst[1:]], [lst[1:], ['1.1']] ] for x in range(1, num - 1): con_sents = jsonc(main_lst) ant_sents = jsonc(main_lst) ant_size = x con_size = (num - 1) - x power_ants = powerset(ant_sents) power_cons = powerset(con_sents) power_ants = [x for x in list(power_ants) if len(x) == ant_size] power_cons = [x for x in list(power_cons) if len(x) == con_size] for power_ant in power_ants: for power_con in power_cons: if len(power_con & power_ant) == 0: ant = list(power_ant) ant.append('1.1') lst_nums.append([ant, list(power_con)]) return lst_nums def quadruple(): ''' this is a sample answer for how the list should look if we have 4 sentences ''' return [ [['1.1', '1.2'], ['1.3', '1.4']], [['1.1', '1.3'], ['1.2', '1.4']], [['1.1', '1.4'], ['1.2', '1.3']], [['1.1', '1.2', '1.3'], ['1.4']], [['1.1', '1.2', '1.4'], ['1.3']], [['1.1', '1.3', '1.4'], ['1.2']], [['1.1'], ['1.3','1.2', '1.4']], [['1.4', '1.3','1.2'], ['1.1']], ] build_lst_nums()