Skip to content

Instantly share code, notes, and snippets.

@DavidParamonov
Forked from huyen-nguyen/generate-cnf.js
Created February 26, 2023 23:22
Show Gist options
  • Select an option

  • Save DavidParamonov/bc118d1dbb1167c0848dea766cf8d619 to your computer and use it in GitHub Desktop.

Select an option

Save DavidParamonov/bc118d1dbb1167c0848dea766cf8d619 to your computer and use it in GitHub Desktop.

Revisions

  1. @huyen-nguyen huyen-nguyen created this gist Nov 20, 2020.
    132 changes: 132 additions & 0 deletions generate-cnf.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,132 @@
    // helper functions

    // cnf formula exactly one of the variables in the chosen list to be true

    function ext_one(list) {
    let temp = ""
    temp=temp+atl_one(list)
    temp=temp+atm_one(list)
    return temp
    }

    // cnf formula for atleast one of the variables in the chosen list to be true
    function atl_one(list) {
    let temp=""
    list.forEach(item => {
    temp = temp +" " + item
    })
    temp=temp+" 0\n"
    console.log("at least, ", temp)
    return temp
    }

    // cnf formula for atmost one of the variables in the chosen list to be true
    function atm_one(list) {
    let temp=""
    list.forEach(function (x) {
    list.slice(list.indexOf(x) + 1).forEach(y => {
    temp = temp +" -"+x+" -"+y+" 0\n"
    })
    })
    return temp
    }

    // function to map position (r,c) 0 <= r,c < N, in an NxN grid to the integer
    // position when the grid is stored linearly by rows.

    function varmap(r,c,N) {
    return r*N+c+1
    }

    // range
    function range(start, stop, step) {
    if (typeof stop == 'undefined') {
    // one param defined
    stop = start;
    start = 0;
    }
    if (typeof step == 'undefined') {
    step = 1;
    }
    if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) {
    return [];
    }
    var result = [];
    for (var i = start; step > 0 ? i < stop : i > stop; i += step) {
    result.push(i);
    }
    return result;
    }

    /**
    * @return {string}
    */
    function sat(N){
    // Start Solver: Comments
    let output="c SAT Expression for N="+N+((N === 1)? " queen\n": " queens\n")
    let size = N*N
    output = output + "c Chess board has "+size+((N === 1)? " position\n": " positions\n")

    // Exactly 1 queen per row
    let tempG = ""
    range(0,N).forEach(row => {
    let A=[]
    range(0,N).forEach(column => {
    let position = varmap(row,column,N)
    A.push(position)
    })
    tempG = tempG+ext_one(A)
    })


    // Exactly 1 queen per column
    range(0,N).forEach(column => {
    let A=[]
    range(0,N).forEach(row => {
    let position = varmap(row,column,N)
    A.push(position)
    })
    tempG = tempG+ext_one(A)
    })


    // Atmost 1 queen per negative diagonal from left
    range(N-1,-1,-1).forEach(row => {
    let A=[]
    range(0,N-row).forEach(x => {
    A.push(varmap(row+x,x,N))
    })
    tempG=tempG+atm_one(A)
    })


    // Atmost 1 queen per negative diagonal from top
    range(1,N).forEach(column => {
    let A=[]
    range(0,N-column).forEach(x => {
    A.push(varmap(x,column+x,N))
    })
    tempG=tempG+atm_one(A)
    })

    // Atmost 1 queen per positive diagonal from right
    range(N-1,-1,-1).forEach(row => {
    let A=[]
    range(0,N-row).forEach(x => {
    A.push(varmap(row+x,N-1-x,N))
    })
    tempG=tempG+atm_one(A)
    })

    // Atmost 1 queen per positive diagonal from top
    range(N-2,-1,-1).forEach(column => {
    let A=[]
    range(0,column+1).forEach(x => {
    A.push(varmap(x,column-x,N))
    })
    tempG=tempG+atm_one(A)
    })

    output = output + 'p cnf ' + (N*N) + ' ' + (tempG.split('\n').length - 1) + '\n' + tempG.trim()
    return output
    }