001package org.cpsolver.ifs.assignment.context; 002 003import org.cpsolver.ifs.assignment.Assignment; 004import org.cpsolver.ifs.assignment.InheritedAssignment; 005import org.cpsolver.ifs.model.Value; 006import org.cpsolver.ifs.model.Variable; 007 008/** 009 * A variant of the {@link AssignmentContextHolderMap} that is used by the {@link InheritedAssignment} 010 * class. If a {@link HasAssignmentContext} class implements the {@link CanInheritContext} interface, 011 * this class will use the {@link CanInheritContext#inheritAssignmentContext(Assignment, AssignmentContext)} method 012 * instead of the {@link HasAssignmentContext#createAssignmentContext(Assignment)} method to create 013 * a new context. 014 * 015 * @see HasAssignmentContext 016 * @see InheritedAssignment 017 * @see CanInheritContext 018 * 019 * @author Tomáš Müller 020 * @version IFS 1.3 (Iterative Forward Search)<br> 021 * Copyright (C) 2014 Tomáš Müller<br> 022 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 023 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 024 * <br> 025 * This library is free software; you can redistribute it and/or modify 026 * it under the terms of the GNU Lesser General Public License as 027 * published by the Free Software Foundation; either version 3 of the 028 * License, or (at your option) any later version. <br> 029 * <br> 030 * This library is distributed in the hope that it will be useful, but 031 * WITHOUT ANY WARRANTY; without even the implied warranty of 032 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 033 * Lesser General Public License for more details. <br> 034 * <br> 035 * You should have received a copy of the GNU Lesser General Public 036 * License along with this library; if not see <a href='http://www.gnu.org/licenses'>http://www.gnu.org/licenses</a>. 037 * @param <V> Variable 038 * @param <T> Value 039 **/ 040public class InheritedAssignmentContextHolder<V extends Variable<V, T>, T extends Value<V, T>> extends DefaultParallelAssignmentContextHolder<V, T> { 041 private long iVersion; 042 043 public InheritedAssignmentContextHolder(int index, long version) { 044 super(index); 045 iVersion = version; 046 } 047 048 /** 049 * If the {@link AssignmentContextReference#getParent()} implements the {@link CanInheritContext} interface, this 050 * method will use the {@link CanInheritContext#inheritAssignmentContext(Assignment, AssignmentContext)} instead of the 051 * {@link HasAssignmentContext#createAssignmentContext(Assignment)} to create a new context. 052 * @param assignment current assignment (must be {@link InheritedAssignment}) 053 * @param reference assignment context reference 054 * @return assignment context for the given assignment and reference 055 */ 056 @Override 057 @SuppressWarnings("unchecked") 058 public <U extends AssignmentContext> U getAssignmentContext(Assignment<V, T> assignment, AssignmentContextReference<V, T, U> reference) { 059 if (iIndex >= 0 && iIndex < CanHoldContext.sMaxSize && reference.getParent() instanceof CanHoldContext) { 060 AssignmentContext[] contexts = ((CanHoldContext)reference.getParent()).getContext(); 061 062 VersionedContext<U> context = (VersionedContext<U>)contexts[iIndex]; 063 if (context == null) { 064 context = new VersionedContext<U>(); 065 if (reference.getParent() instanceof CanInheritContext) 066 context.setContent(((CanInheritContext<V, T, U>)reference.getParent()).inheritAssignmentContext(assignment, 067 ((InheritedAssignment<V, T>)assignment).getParentAssignment().getAssignmentContext(reference)), iVersion); 068 else 069 context.setContent(reference.getParent().createAssignmentContext(assignment), iVersion); 070 contexts[iIndex] = context; 071 } else if (!context.isCurrent(iVersion)) { 072 if (reference.getParent() instanceof CanInheritContext) 073 context.setContent(((CanInheritContext<V, T, U>)reference.getParent()).inheritAssignmentContext(assignment, 074 ((InheritedAssignment<V, T>)assignment).getParentAssignment().getAssignmentContext(reference)), iVersion); 075 else 076 context.setContent(reference.getParent().createAssignmentContext(assignment), iVersion); 077 } 078 079 return context.getContent(); 080 } else { 081 U context = (U) iContexts.get(reference.getIndex()); 082 if (context != null) return context; 083 084 if (reference.getParent() instanceof CanInheritContext) 085 context = ((CanInheritContext<V, T, U>)reference.getParent()).inheritAssignmentContext(assignment, 086 ((InheritedAssignment<V, T>)assignment).getParentAssignment().getAssignmentContext(reference)); 087 else 088 context = reference.getParent().createAssignmentContext(assignment); 089 iContexts.put(reference.getIndex(), context); 090 091 return context; 092 } 093 } 094 095 public static class VersionedContext<U extends AssignmentContext> implements AssignmentContext { 096 U iContent = null; 097 long iContentVersion = -1; 098 099 VersionedContext() {} 100 101 public U getContent() { 102 return iContent; 103 } 104 105 public void setContent(U content, long version) { 106 iContent = content; 107 iContentVersion = version; 108 } 109 110 public boolean isCurrent(long version) { 111 return iContentVersion == version; 112 } 113 } 114}