Network graph (force directed graph)

author(s): Paweł Fus

by nima101

HTML

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>2-SAT Implication Graph</title>
    <link rel="stylesheet" href="style.css">
    <script type="text/javascript" src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
    <script type="text/javascript" src="script.js" defer></script>
    <script src="https://use.fontawesome.com/c3ef28c600.js"></script>
</head>
<body>

<h3>2-SAT Implication Graph</h3>

<!-- Input for 2-SAT Expression -->
<input type="text" id="satInput" placeholder="Enter 2-SAT expression" value="(x or ~y) and (~x or y) and (~x or ~y) and (y or z)">
<button id="genGraph"><span class="fa fa-play fa-large"></span></button>

<!-- Div to display the graph -->
<div id="network"></div>

</body>
</html>

CSS

#network {
    width: 88%;
    height: 300px;
    border: 3px solid lightgray;
    margin-top: 10px;
}

h3 {
    text-align: center;
}

#satInput {
    width: 80%;
    padding: 8px;
    margin-bottom: 10px;
}

button {
    padding: 8px 12px;
    font-size: 13px;
}

JavaScript

// Function to get the negation of a literal using "~"
function negate(literal) {
    return literal.startsWith('~') ? literal.substring(1) : '~' + literal;
}

// Function to convert clauses into edges of the implication graph
function generateImplicationGraph(clauses) {
    var edges = [];

    clauses.forEach(clause => {
        var [a, b] = clause;
        edges.push({ from: negate(a), to: b });
        edges.push({ from: negate(b), to: a });
    });

    return edges;
}

// Function to parse user input 2-SAT expression into clauses
function parseSATExpression(expression) {
    // Remove whitespaces and split clauses by "and"
    var clauseStrings = expression.replace(/\s+/g, '').split('and');
    var clauses = [];

    clauseStrings.forEach(clause => {
        // Remove parentheses and split by "or"
        var literals = clause.replace(/[()]/g, '').split('or');
        clauses.push(literals);
    });

    return clauses;
}

// Function to draw the graph
function drawGraph(clauses) {
    // Generate the edges for the implication graph
    var edgesData = generateImplicationGraph(clauses);

    // Create nodes from literals
    var literals = new Set();
    clauses.flat().forEach(literal => {
        literals.add(literal);
        literals.add(negate(literal));
    });

    // Create an array of nodes
    var nodes = Array.from(literals).map(literal => {
        return { id: literal, label: literal };
    });

    // Create an array of edges
    var edges = edgesData.map(edge => {
        return { from: edge.from, to: edge.to, arrows: 'to' };
    });

    // Create a network
    var container = document.getElementById('network');

    // Provide the data for the graph
    var data = {
        nodes: new vis.DataSet(nodes),
        edges: new vis.DataSet(edges)
    };

    // Define options for the graph
    var options = {
        nodes: {
            shape: 'circle',
            size: 50,
            font: {
                size: 18,
                align:...