/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.commons.math4.neuralnet;

import java.util.Collection;
import java.util.NoSuchElementException;

import org.junit.Assert;
import org.junit.Test;

import org.apache.commons.rng.UniformRandomProvider;
import org.apache.commons.rng.simple.RandomSource;

import org.apache.commons.math4.neuralnet.twod.NeuronSquareMesh2D;

/**
 * Tests for {@link Network}.
 */
public class NetworkTest {
    private final UniformRandomProvider rng = RandomSource.SPLIT_MIX_64.create();
    private final FeatureInitializer init = FeatureInitializerFactory.uniform(rng, 0, 2);

    @Test
    public void testGetFeaturesSize() {
        final FeatureInitializer[] initArray = {init, init, init};

        final Network net = new NeuronSquareMesh2D(2, false,
                                                   2, false,
                                                   SquareNeighbourhood.VON_NEUMANN,
                                                   initArray).getNetwork();
        Assert.assertEquals(3, net.getFeaturesSize());
    }

    /*
     * Test assumes that the network is
     *
     *  0-----1
     *  |     |
     *  |     |
     *  2-----3
     */
    @Test
    public void testDeleteLink() {
        final FeatureInitializer[] initArray = {init};
        final Network net = new NeuronSquareMesh2D(2, false,
                                                   2, false,
                                                   SquareNeighbourhood.VON_NEUMANN,
                                                   initArray).getNetwork();
        Collection<Neuron> neighbours;

        // Delete 0 --> 1.
        net.deleteLink(net.getNeuron(0),
                       net.getNeuron(1));

        // Link from 0 to 1 was deleted.
        neighbours = net.getNeighbours(net.getNeuron(0));
        Assert.assertFalse(neighbours.contains(net.getNeuron(1)));
        // Link from 1 to 0 still exists.
        neighbours = net.getNeighbours(net.getNeuron(1));
        Assert.assertTrue(neighbours.contains(net.getNeuron(0)));
    }

    /*
     * Test assumes that the network is
     *
     *  0-----1
     *  |     |
     *  |     |
     *  2-----3
     */
    @Test
    public void testDeleteNeuron() {
        final FeatureInitializer[] initArray = {init};
        final Network net = new NeuronSquareMesh2D(2, false,
                                                   2, false,
                                                   SquareNeighbourhood.VON_NEUMANN,
                                                   initArray).getNetwork();

        Assert.assertEquals(2, net.getNeighbours(net.getNeuron(0)).size());
        Assert.assertEquals(2, net.getNeighbours(net.getNeuron(3)).size());

        // Delete neuron 1.
        net.deleteNeuron(net.getNeuron(1));

        try {
            net.getNeuron(1);
        } catch (NoSuchElementException expected) {
          // Ignore
        }

        Assert.assertEquals(1, net.getNeighbours(net.getNeuron(0)).size());
        Assert.assertEquals(1, net.getNeighbours(net.getNeuron(3)).size());
    }

    @Test
    public void testIterationOrder() {
        final FeatureInitializer[] initArray = {init};
        final Network net = new NeuronSquareMesh2D(4, false,
                                                   3, true,
                                                   SquareNeighbourhood.VON_NEUMANN,
                                                   initArray).getNetwork();

        // Check that the comparator provides a specific order.
        boolean isUnspecifiedOrder = false;
        long previousId = Long.MIN_VALUE;
        for (Neuron n : net.getNeurons(new Network.NeuronIdentifierComparator())) {
            final long currentId = n.getIdentifier();
            if (currentId < previousId) {
                isUnspecifiedOrder = true;
                break;
            }
            previousId = currentId;
        }
        Assert.assertFalse(isUnspecifiedOrder);
    }

    /*
     * Test assumes that the network is
     *
     *  0-----1
     *  |     |
     *  |     |
     *  2-----3
     */
    @Test
    public void testCopy() {
        final FeatureInitializer[] initArray = {init};
        final Network net = new NeuronSquareMesh2D(2, false,
                                                   2, false,
                                                   SquareNeighbourhood.VON_NEUMANN,
                                                   initArray).getNetwork();

        final Network copy = net.copy();

        final Neuron netNeuron0 = net.getNeuron(0);
        final Neuron copyNeuron0 = copy.getNeuron(0);
        final Neuron netNeuron1 = net.getNeuron(1);
        final Neuron copyNeuron1 = copy.getNeuron(1);
        Collection<Neuron> netNeighbours;
        Collection<Neuron> copyNeighbours;

        // Check that both networks have the same connections.
        netNeighbours = net.getNeighbours(netNeuron0);
        copyNeighbours = copy.getNeighbours(copyNeuron0);
        Assert.assertTrue(netNeighbours.contains(netNeuron1));
        Assert.assertTrue(copyNeighbours.contains(copyNeuron1));

        // Delete neuron 1 from original.
        net.deleteNeuron(netNeuron1);

        // Check that the networks now differ.
        netNeighbours = net.getNeighbours(netNeuron0);
        copyNeighbours = copy.getNeighbours(copyNeuron0);
        Assert.assertFalse(netNeighbours.contains(netNeuron1));
        Assert.assertTrue(copyNeighbours.contains(copyNeuron1));
    }
}
