All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.chocosolver.solver.constraints.graph.symmbreaking.PropIncrementalAdjacencyMatrix Maven / Gradle / Ivy

The newest version!
/*
 * This file is part of choco-solver, http://choco-solver.org/
 *
 * Copyright (c) 2024, IMT Atlantique. All rights reserved.
 *
 * Licensed under the BSD 4-clause license.
 *
 * See LICENSE file in the project root for full license information.
 */
package org.chocosolver.solver.constraints.graph.symmbreaking;

import org.chocosolver.solver.constraints.Propagator;
import org.chocosolver.solver.constraints.PropagatorPriority;
import org.chocosolver.solver.exception.ContradictionException;
import org.chocosolver.solver.variables.BoolVar;
import org.chocosolver.solver.variables.DirectedGraphVar;
import org.chocosolver.solver.variables.Variable;
import org.chocosolver.solver.variables.delta.IGraphDeltaMonitor;
import org.chocosolver.solver.variables.events.GraphEventType;
import org.chocosolver.solver.variables.events.IntEventType;
import org.chocosolver.util.ESat;
import org.chocosolver.util.objects.setDataStructures.ISet;
import org.chocosolver.util.procedure.PairProcedure;
import org.chocosolver.util.tools.ArrayUtils;

import java.util.HashSet;
import java.util.Set;

/**
 * @author Моклев Вячеслав
 */
public class PropIncrementalAdjacencyMatrix extends Propagator {

    private final DirectedGraphVar graph;
    private final IGraphDeltaMonitor gdm;
    private final PairProcedure enforce;
    private final PairProcedure remove;
    private int n;
    private final BoolVar[] t;

    public PropIncrementalAdjacencyMatrix(DirectedGraphVar graphVar, BoolVar[] t) {
        super(ArrayUtils.append(new Variable[]{graphVar}, t), PropagatorPriority.LINEAR, true);
        graph = graphVar;
        gdm = graph.monitorDelta(this);
        enforce = (from, to) -> t[from + to * n].instantiateTo(1, this);
        remove = (from, to) -> t[from + to * n].instantiateTo(0, this);
        n = graphVar.getNbMaxNodes();
        this.t = t;
    }

    @Override
    public void propagate(int evtmask) throws ContradictionException {
        // first, nonincremental propagation
        propagateGraphChanged();
        propagateTChanged();
        // initializing incremental data-structures
        gdm.startMonitoring();
    }

    private void propagateGraphChanged() throws ContradictionException {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (t[i + j * n].isInstantiatedTo(1)) {
                    graph.enforceEdge(i, j, this);
                }
                if (t[i + j * n].isInstantiatedTo(0)) {
                    graph.removeEdge(i, j, this);
                }
            }
        }
    }

    private void propagateTChanged() throws ContradictionException {
        for (int u = 0; u < n; u++) {
            for (int v : graph.getMandatorySuccessorsOf(u)) {
                t[u + v * n].instantiateTo(1, this);
            }
        }
        for (int u = 0; u < n; u++) {
            Set set = new HashSet<>();
            for (int v : graph.getPotentialSuccessorsOf(u)) {
                set.add(v);
            }
            for (int v = 0; v < n; v++) {
                if (!set.contains(v)) {
                    t[u + v * n].instantiateTo(0, this);
                }
            }
        }
    }

    @Override
    public void propagate(int idxVarInProp, int mask) throws ContradictionException {
        // incremental propagation
        if (idxVarInProp == 0) {
            gdm.forEachEdge(enforce, GraphEventType.ADD_EDGE);
            gdm.forEachEdge(remove, GraphEventType.REMOVE_EDGE);
        } else {
            propagateTChanged();
        }
    }

    @Override
    public int getPropagationConditions(int vIdx) {
        if (vIdx == 0) {
            return GraphEventType.ADD_EDGE.getMask() | GraphEventType.REMOVE_EDGE.getMask();
        } else {
            return IntEventType.boundAndInst();
        }
    }

    @Override
    public ESat isEntailed() {
        for (int i = 0; i < n; i++) {
            ISet children = graph.getMandatorySuccessorsOf(i);
            for (int j = 0; j < n; j++) {
                if (t[i + j * n].isInstantiatedTo(0) && children.contains(j)) {
                    return ESat.FALSE;
                }
            }
        }
        for (int i = 0; i < n; i++) {
            ISet children = graph.getPotentialSuccessorsOf(i);
            for (int j = 0; j < n; j++) {
                if (t[i + j * n].isInstantiatedTo(1) && !children.contains(j)) {
                    return ESat.FALSE;
                }
            }
        }
        if (graph.isInstantiated()) {
            return ESat.TRUE;
        }
        return ESat.UNDEFINED;
    }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy