package autodiff.nodes.test;

import static autodiff.nodes.ComputationNode.*;
import static autodiff.reasoning.expressions.Expressions.*;
import static autodiff.reasoning.proofs.Stack.*;
import static multij.tools.Tools.debugPrint;
import static org.junit.Assert.*;

import autodiff.nodes.ComputationNode;
import autodiff.nodes.Data;
import autodiff.nodes.Node;
import autodiff.reasoning.deductions.Standard;

import java.util.List;

import org.junit.Test;

/**
 * @author codistmonk (creation 2016-07-11)
 */
public final class NodeTest {
	
	@Test
	public final void testShapes1() {
		final Node<?> x = new Data().setShape(1);
		
		assertArrayEquals(new int[] { 1 }, x.getShape());
		
		assertArrayEquals(new int[] { 1 }, x.getLengths(new int [1]));
		assertArrayEquals(new int[] { 1, 1 }, x.getLengths(new int [2]));
	}
	
	@Test
	public final void testShapes2() {
		final Node<?> x = new Data().setShape(2, 3, 4);
		
		assertArrayEquals(new int[] { 2, 3, 4 }, x.getShape());
		
		assertArrayEquals(new int[] { 24 }, x.getLengths(new int [1]));
		assertArrayEquals(new int[] { 2, 12 }, x.getLengths(new int [2]));
		assertArrayEquals(new int[] { 2, 3, 4 }, x.getLengths(new int [3]));
		assertArrayEquals(new int[] { 2, 3, 4, 1 }, x.getLengths(new int [4]));
	}
	
	@Test
	public final void testGetSet1() {
		final Node<?> x = new Data().setShape(1);
		
		x.set(42F);
		
		assertEquals(42.0, x.get(), 0.0);
	}
	
	@Test
	public final void testGetSet2() {
		final Node<?> x = new Data().setShape(2);
		
		x.set(42F, 33F);
		
		assertEquals(42.0, x.get(0), 0.0);
		assertEquals(33.0, x.get(1), 0.0);
	}
	
	@Test
	public final void testComputationNode1() {
		final ComputationNode node = ComputationNode.ones();
		
		node.set("s", new int[] { 2 });
		
		node.autoShape();
		
		assertArrayEquals(new int[] { 2 }, node.getShape());
		
		Standard.build(node.getBoundForm(), new Runnable() {
			
			@Override
			public final void run() {
				final Object boundForm = proposition(-1);
				final Object valuesExpression = left(middle(right(boundForm)));
				final Object nExpression = right(right(valuesExpression));
				final Object v = list(nExpression).get(1);
				
				debugPrint(valuesExpression);
				debugPrint(nExpression);
				
				{
					subdeduction();
					
					ebind("definition_of_product_reduction", 1, v);
					// TODO
					abort();
//					deduceCartesianType(new Object[] { 2 }, "realness");
					eapply(name(-2));
					
					conclude();
				}
				
				{
					final List<?> product = list(right(proposition(-1)));
					final Object i = left(product.get(2));
					final Object operand = product.get(3);
					
					debugPrint(product);
					debugPrint(i, operand);
					
					ebind("definition_of_product_loop_n", 1, i, operand);
				}
				
				abort();
				
				// TODO
			}
			
		}, 1);
		
		fail("TODO");
	}
	
	@Test
	public final void testComputationNode2() {
		final ComputationNode node = ComputationNode.ones();
		
		node.set("s", new int[] { 2, 1, 3 });
		
		node.autoShape();
		
		assertArrayEquals(new int[] { 2, 1, 3 }, node.getShape());
		
		fail("TODO");
	}
	
}

@@ -67,24 +67,86 @@
 tionNode.*;%0A
+import static autodiff.reasoning.deductions.Standard.rewrite;%0A
 import stati
@@ -469,32 +469,8 @@
 d;%0A%0A
-import java.util.List;%0A%0A
 impo
@@ -2142,55 +2142,8 @@
 ));%0A
-%09%09%09%09final Object v = list(nExpression).get(1);%0A
 %09%09%09%09
@@ -2253,148 +2253,59 @@
 %09%09%09%09
-ebind(%22definition_of_product_reduction%22, 1, v);%0A%09%09%09%09%09// TODO%0A%09%09%09%09%09abort();%0A//%09%09%09%09%09deduceCartesianType(new Object%5B%5D %7B 2 %7D, %22realness%22
+computeVectorReductionByProduct(nExpression
 );%0A%09%09%09%09%09
 eapp
@@ -2304,14 +2304,15 @@
 %09%09%09%09
-eapply
+rewrite
 (nam
@@ -2320,321 +2320,41 @@
 (-2)
-);%0A%09%09%09%09%09%0A%09%09%09%09%09conclude();%0A%09%09%09%09%7D%0A%09%09%09%09%0A%09%09%09%09%7B%0A%09%09%09%09%09final List%3C?%3E product = list(right(proposition
+, name
 (-1))
-)
 ;%0A%09%09%09%09%09
-final Object i = left(product.get(2));%0A%09%09%09%09%09final Object operand = product.get(3);%0A%09%09%09%09%09%0A%09%09%09%09%09debugPrint(product);%0A%09%09%09%09%09debugPrint(i, operand);%0A%09%09%09%09%09%0A%09%09%09%09%09ebind(%22definition_of_product_loop_n%22, 1, i, operand
+%0A%09%09%09%09%09conclude(
 );%0A%09

Update testComputationNode1().