001package conexp.fx.core.algorithm.exploration; 002 003import java.util.Collections; 004import java.util.Set; 005import java.util.concurrent.CountDownLatch; 006import java.util.concurrent.ExecutionException; 007import java.util.concurrent.Future; 008import java.util.concurrent.TimeUnit; 009import java.util.concurrent.TimeoutException; 010import java.util.concurrent.atomic.AtomicReference; 011 012import conexp.fx.core.context.Implication; 013 014/* 015 * #%L 016 * Concept Explorer FX 017 * %% 018 * Copyright (C) 2010 - 2019 Francesco Kriegel 019 * %% 020 * This program is free software: you can redistribute it and/or modify 021 * it under the terms of the GNU General Public License as 022 * published by the Free Software Foundation, either version 3 of the 023 * License, or (at your option) any later version. 024 * 025 * This program is distributed in the hope that it will be useful, 026 * but WITHOUT ANY WARRANTY; without even the implied warranty of 027 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 028 * GNU General Public License for more details. 029 * 030 * You should have received a copy of the GNU General Public 031 * License along with this program. If not, see 032 * <http://www.gnu.org/licenses/gpl-3.0.html>. 033 * #L% 034 */ 035 036@FunctionalInterface 037public interface Expert<G, M> { 038 039 /** 040 * 041 * Returns an empty set if the provided implication is valid, otherwise returns a set containing at least one 042 * counterexample. 043 * 044 * @param impl 045 * @return 046 * @throws InterruptedException 047 */ 048 public Set<CounterExample<G, M>> getCounterExamples(Implication<G, M> implication) throws InterruptedException; 049 050 public default Future<Set<CounterExample<G, M>>> requestCounterExamples(final Implication<G, M> implication) { 051 return new Future<Set<CounterExample<G, M>>>() { 052 053 private final CountDownLatch cdl = new CountDownLatch(1); 054 private final AtomicReference<Set<CounterExample<G, M>>> ref = 055 new AtomicReference<>(Collections.emptySet()); 056 private boolean isCancelled = false; 057 058 { 059 new Thread(() -> { 060 try { 061 ref.set(getCounterExamples(implication)); 062 cdl.countDown(); 063 } catch (InterruptedException __) { 064 cancel(true); 065 } 066 }).start(); 067 } 068 069 @Override 070 public boolean cancel(boolean mayInterruptIfRunning) { 071 if (isCancelled) 072 return false; 073 isCancelled = true; 074 cdl.countDown(); 075 return true; 076 } 077 078 @Override 079 public boolean isCancelled() { 080 return isCancelled; 081 } 082 083 @Override 084 public boolean isDone() { 085 return cdl.getCount() == 0; 086 } 087 088 @Override 089 public Set<CounterExample<G, M>> get() throws InterruptedException, ExecutionException { 090 cdl.await(); 091 return ref.get(); 092 } 093 094 @Override 095 public Set<CounterExample<G, M>> get(long timeout, TimeUnit unit) 096 throws InterruptedException, ExecutionException, TimeoutException { 097 if (cdl.await(timeout, unit)) 098 return ref.get(); 099 throw new TimeoutException(); 100 } 101 }; 102 } 103 104}