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}