1

im currently writing a program which requires me to have a logical formula and then try every combination of True and False on that logical formula. Currently I have some code which creates a logical formula in the form : ({1} or not {2} or not {5} )and (not {1} or {6} )and (not {2} or not {3} )and ({3} or not {4} )and (not {4} or {5} or not {6} ) where the numbers need to be swapped out for every combination of true and false. The combos of true and false i work out using this line combos= product([True,False],repeat = no_variables). I currently have this code to attempt to do this:

for i in combos:
    for j in range (no_variables):
            k=j+1 //as the variables in the string do not start at 0
            print(formulastring.format(k = i[j]))

however it doesn't work and returns this error:

print(formulastring.format(k = i[j]))
IndexError: Replacement index 1 out of range for positional args tuple

Any help would be greatly appreciated !

userj
  • 158
  • 11

2 Answers2

1

The problem is you are giving a format string that looks for positional arguments ({0}, {1}, etc), but you call your format function with keyword arguments (k=...)

You need to either change your format string to accept keyword arguments, like: {k} instead of {0},

Or, change the way you pass the arguments, so call it like .format(i[j], ...). Remember, your format string expects 7 arguments.

Demonstration:

# Positional
"{0} {1} {2}".format(3, 423, 12)
# Output: '3 423 12'

# Keyword
"{a} {b} {c}".format(a=3, b=423, c=12)
# Output: '3 423 12'

Now applying this to your problem:

formulastring = "({1} or not {2} or not {5} )and (not {1} or {6} )and (not {2} or not {3} )and ({3} or not {4} )and (not {4} or {5} or not {6} )"
no_variables = 7 # Judging from this particular formatstring

combos= product([True,False],repeat = no_variables)
# Each element of combos is a 7-element tuple

for values in combos:
    # values is a tuple containing no_variables booleans
    # *values unpacks the tuple and passes it as positional arguments to format()
    print(formulastring.format(*values))

This gives the output you expect.

Pranav Hosangadi
  • 23,755
  • 7
  • 44
  • 70
  • but k changes from 0 to 6 with each iteration. The overall code is meant to work for any logical formula so I am not able to hard code in exactly how many variables there would be as it may change for each formula – userj Feb 17 '21 at 16:55
  • I'm adding to my answer. Hold tight – Pranav Hosangadi Feb 17 '21 at 16:56
  • I cannot use poisitional as some variables are repeated in the formula and I cant do keyword as I cannot hard code the variables from before. – userj Feb 17 '21 at 16:56
  • You can pass a list as positional arguments by [unpacking it](https://stackoverflow.com/a/7527889/843953). I'm editing my answer to include an example – Pranav Hosangadi Feb 17 '21 at 16:58
  • Does this work even though I have variables being used more than one in the formal string so they would have to be replaced with the same variable ? As it does not work and returns ` print(formulastring.format(*values)) IndexError: Replacement index 6 out of range for positional args tuple` this error – userj Feb 17 '21 at 17:07
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/228859/discussion-between-pranav-hosangadi-and-userj). – Pranav Hosangadi Feb 17 '21 at 17:08
0
import itertools

combos = list(itertools.product([False, True], repeat=6))

test = f'({1} or not {2} or not {5}) and (not {1} or {6})and (not {2} or not {3} )and ({3} or not {4} )and (not {4} or {5} or not {6} )'

results = []
for combo in combos:
    cur = test
    for idx, val in enumerate(combo):
        cur = cur.replace(str(idx+1), str(val))
        
    results.append(eval(cur))
Will.Evo
  • 1,112
  • 13
  • 31
  • what does the f in test mean ? – userj Feb 17 '21 at 17:00
  • and is 'results' the overall truth assignment obtained by each combo ? – userj Feb 17 '21 at 17:02
  • It is an f-string, basically python will evaluate whatever is in {} brackets, so in this case, test just ends up with a 1, 2, 3, etcc in those spots. You could remove the {} brackets and the string wouldn't change. Right, results contains True or False for each combo in combos. – Will.Evo Feb 17 '21 at 17:35
  • I had a couple bugs that I fixed. Should work now! – Will.Evo Feb 17 '21 at 17:40