org.drugis.mtc.parameterization.InconsistencyBaselineSearchProblem.java Source code

Java tutorial

Introduction

Here is the source code for org.drugis.mtc.parameterization.InconsistencyBaselineSearchProblem.java

Source

/*
 * This file is part of the GeMTC software for MTC model generation and
 * analysis. GeMTC is distributed from http://drugis.org/gemtc.
 * Copyright (C) 2009-2012 Gert van Valkenhoef.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.drugis.mtc.parameterization;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.collections15.CollectionUtils;
import org.apache.commons.collections15.Predicate;
import org.drugis.mtc.model.Study;
import org.drugis.mtc.model.Treatment;
import org.drugis.mtc.search.SearchProblem;

import edu.uci.ics.jung.algorithms.transformation.FoldingTransformerFixed.FoldedEdge;
import edu.uci.ics.jung.graph.UndirectedGraph;

/**
 * Defines the SearchProblem that is to be solved in order to correctly assign baselines for an inconsistency model.
 */
public class InconsistencyBaselineSearchProblem implements SearchProblem<Map<Study, Treatment>> {
    private final Collection<Study> d_studies;
    private final UndirectedGraph<Treatment, FoldedEdge<Treatment, Study>> d_cGraph;
    private final Map<Partition, Set<List<Treatment>>> d_cycleClasses;

    /**
     * Search problem for finding a baseline assignment that covers all edges.
     * @param studies List of studies.
     * @param cGraph Comparison graph.
     */
    public InconsistencyBaselineSearchProblem(Collection<Study> studies,
            UndirectedGraph<Treatment, FoldedEdge<Treatment, Study>> cGraph) {
        this(studies, cGraph, null);
    }

    public InconsistencyBaselineSearchProblem(Collection<Study> studies,
            UndirectedGraph<Treatment, FoldedEdge<Treatment, Study>> cGraph,
            Map<Partition, Set<List<Treatment>>> cycleClasses) {
        d_studies = studies;
        d_cGraph = cGraph;
        d_cycleClasses = cycleClasses;
    }

    public Map<Study, Treatment> getInitialState() {
        Map<Study, Treatment> state = new HashMap<Study, Treatment>();
        for (Study s : d_studies) {
            Set<Treatment> treatments = s.getTreatments();
            if (treatments.size() == 2) {
                state.put(s, CompareUtil.findLeast(treatments, TreatmentComparator.INSTANCE));
            }
        }
        return state;
    }

    public List<Map<Study, Treatment>> getSuccessors(final Map<Study, Treatment> state) {
        // Find the first study without a baseline
        Study study = CollectionUtils.find(d_studies, new Predicate<Study>() {
            public boolean evaluate(Study study) {
                return !state.containsKey(study);
            }
        });

        if (study == null) {
            return Collections.emptyList();
        }

        // Each treatment generates a successor
        Set<Treatment> treatments = new TreeSet<Treatment>(new TreatmentComparator());
        treatments.addAll(study.getTreatments());
        List<Map<Study, Treatment>> succ = new ArrayList<Map<Study, Treatment>>(treatments.size());
        for (Treatment treatment : treatments) {
            Map<Study, Treatment> map = new HashMap<Study, Treatment>(state);
            map.put(study, treatment);
            succ.add(map);
        }

        return succ;
    }

    public boolean isGoal(Map<Study, Treatment> state) {
        if (!state.keySet().containsAll(d_studies)) {
            return false;
        }

        // Calculate covered edges
        Set<FoldedEdge<Treatment, Study>> covered = new HashSet<FoldedEdge<Treatment, Study>>();
        for (Entry<Study, Treatment> entry : state.entrySet()) {
            Treatment t0 = entry.getValue();
            for (Treatment t1 : entry.getKey().getTreatments()) {
                FoldedEdge<Treatment, Study> edge = d_cGraph.findEdge(t0, t1);
                if (edge != null) {
                    covered.add(edge);
                }
            }
        }

        if (d_cycleClasses == null) { // Looking for full baseline cover
            return covered.containsAll(d_cGraph.getEdges());
        }

        // Now check that for each cycle class, all cycles have at least (n-1) edges covered,
        // and if the cycle is potentially inconsistent, that at least one as n edges covered.
        for (Entry<Partition, Set<List<Treatment>>> c : d_cycleClasses.entrySet()) {
            Set<List<Treatment>> cycles = c.getValue();
            if (existsTooManyMissing(cycles, covered)) {
                return false;
            } else if (InconsistencyParameterization.isInconsistencyCycle(c.getKey())
                    && !existsNoneMissing(cycles, covered)) {
                return false;
            }
        }
        return true;
    }

    private boolean existsNoneMissing(Set<List<Treatment>> cycles,
            final Set<FoldedEdge<Treatment, Study>> covered) {
        return CollectionUtils.exists(cycles, new Predicate<List<Treatment>>() {
            public boolean evaluate(List<Treatment> cycle) {
                return countMissingEdges(cycle, covered) == 0;
            }
        });
    }

    private boolean existsTooManyMissing(Set<List<Treatment>> cycles,
            final Set<FoldedEdge<Treatment, Study>> covered) {
        return CollectionUtils.exists(cycles, new Predicate<List<Treatment>>() {
            public boolean evaluate(List<Treatment> cycle) {
                return countMissingEdges(cycle, covered) < -1;
            }
        });
    }

    private int countMissingEdges(List<Treatment> cycle, Set<FoldedEdge<Treatment, Study>> covered) {
        int missing = 0;
        for (int i = 1; i < cycle.size(); ++i) {
            FoldedEdge<Treatment, Study> edge = d_cGraph.findEdge(cycle.get(i - 1), cycle.get(i));
            if (!covered.contains(edge)) {
                ++missing;
            }
        }
        return missing;
    }
}