001package org.cpsolver.ifs.assignment; 002 003import java.util.Arrays; 004import java.util.Collection; 005import java.util.HashMap; 006import java.util.Map; 007import java.util.concurrent.locks.ReentrantReadWriteLock; 008 009import org.cpsolver.ifs.assignment.context.DefaultParallelAssignmentContextHolder; 010import org.cpsolver.ifs.model.Model; 011import org.cpsolver.ifs.model.Value; 012import org.cpsolver.ifs.model.Variable; 013import org.cpsolver.ifs.solver.ParallelSolver; 014 015 016/** 017 * An assignment using the {@link Variable#setAssignments(Value[])} to store values of all the 018 * variables of the model. Besides of that, a set of assigned variables is kept in memory. 019 * Each extra contains an array of values, indexed by {@link Assignment#getIndex()}. 020 * Useful for a small, fixed number of assignments. Used by the {@link ParallelSolver}, 021 * where there is one assignment for each thread. 022 * 023 * @see Assignment 024 * @see ParallelSolver 025 * 026 * @version IFS 1.3 (Iterative Forward Search)<br> 027 * Copyright (C) 2014 Tomas Muller<br> 028 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 029 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 030 * <br> 031 * This library is free software; you can redistribute it and/or modify 032 * it under the terms of the GNU Lesser General Public License as 033 * published by the Free Software Foundation; either version 3 of the 034 * License, or (at your option) any later version. <br> 035 * <br> 036 * This library is distributed in the hope that it will be useful, but 037 * WITHOUT ANY WARRANTY; without even the implied warranty of 038 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 039 * Lesser General Public License for more details. <br> 040 * <br> 041 * You should have received a copy of the GNU Lesser General Public 042 * License along with this library; if not see <a href='http://www.gnu.org/licenses'>http://www.gnu.org/licenses</a>. 043 * @param <V> Variable 044 * @param <T> Value 045 **/ 046public class DefaultParallelAssignment <V extends Variable<V, T>, T extends Value<V, T>> extends AssignmentAbstract<V, T> { 047 private Map<V, Long> iAssignedVariables = new HashMap<V, Long>(); 048 private int iIndex; 049 private final ReentrantReadWriteLock iLock = new ReentrantReadWriteLock(); 050 051 public DefaultParallelAssignment(int threadIndex) { 052 super(new DefaultParallelAssignmentContextHolder<V, T>(threadIndex)); 053 iIndex = threadIndex; 054 } 055 056 public DefaultParallelAssignment() { 057 this(0); 058 } 059 060 public DefaultParallelAssignment(int threadIndex, Model<V, T> model, Assignment<V, T> assignment) { 061 this(threadIndex); 062 for (V variable: model.variables()) 063 setValueInternal(0, variable, assignment != null ? assignment.getValue(variable) : null); 064 } 065 066 @Override 067 public long getIteration(V variable) { 068 Long it = iAssignedVariables.get(variable); 069 return (it == null ? 0 : it.longValue()); 070 } 071 072 @Override 073 public Collection<V> assignedVariables() { 074 return iAssignedVariables.keySet(); 075 } 076 077 @SuppressWarnings({ "unchecked", "deprecation" }) 078 protected T[] getAssignments(V variable) { 079 iLock.readLock().lock(); 080 try { 081 T[] assignments = variable.getAssignments(); 082 if (assignments != null && iIndex < assignments.length) return assignments; 083 } finally { 084 iLock.readLock().unlock(); 085 } 086 iLock.writeLock().lock(); 087 try { 088 T[] assignments = variable.getAssignments(); 089 if (assignments == null) { 090 assignments = (T[])new Value[Math.max(10, 1 + iIndex)]; 091 variable.setAssignments(assignments); 092 } else if (assignments.length <= iIndex) { 093 assignments = Arrays.copyOf(assignments, 10 + iIndex); 094 variable.setAssignments(assignments); 095 } 096 return assignments; 097 } finally { 098 iLock.writeLock().unlock(); 099 } 100 } 101 102 @Override 103 protected T getValueInternal(V variable) { 104 return getAssignments(variable)[iIndex]; 105 } 106 107 @Override 108 protected void setValueInternal(long iteration, V variable, T value) { 109 getAssignments(variable)[iIndex] = value; 110 if (value == null) 111 iAssignedVariables.remove(variable); 112 else 113 iAssignedVariables.put(variable, iteration); 114 } 115 116 @Override 117 public int getIndex() { 118 return iIndex; 119 } 120}