/*

Open Predicates:	resultPart, 
Closed Predicates:	yagoFacts, domainArg, rangeArg, fwdInfer1, factOne, factZero, fwdInfer2

Partitions:
	beliefs data :	yagoAllPart
	domain type constraint: domainPart
	range type constraint: rangePart
	if belief is true: factOnePart
	if belief is false: factZeroPart
	horn clause of length 1: fwdInf1Part 
	horn clause of length 2: fwdInf2Part
	initial evidence set: seedPart

*/



/*************************     PREDICATES      ********************************/

	m.add predicate: "yagoFacts" , types: [ArgumentType.UniqueID, ArgumentType.UniqueID, ArgumentType.String, ArgumentType.UniqueID]		//DUMMY FOR NOW - NOT USED
	m.add predicate: "domainArg" , types: [ArgumentType.UniqueID, ArgumentType.UniqueID]
	m.add predicate: "rangeArg" , types: [ArgumentType.UniqueID, ArgumentType.UniqueID]
	
//Horn Clause Predicate - string stores the horn clause ID
	m.add predicate: "fwdInfer1", types: [ArgumentType.String, ArgumentType.UniqueID, ArgumentType.UniqueID]
	m.add predicate: "fwdInfer2", types: [ArgumentType.String, ArgumentType.UniqueID, ArgumentType.UniqueID, ArgumentType.UniqueID]
	
//RESULT PREDICATE
	m.add predicate: "inferable", types: [ArgumentType.UniqueID, ArgumentType.UniqueID]	
	

	m.add predicate: "factOne" , types: [ArgumentType.UniqueID, ArgumentType.UniqueID]
	m.add predicate: "factZero" , types: [ArgumentType.UniqueID, ArgumentType.UniqueID]	

/* function to check for WHICH HORN CLAUSE for varying rule weights  */
	m.add function: "sameName" , implementation: new MyStringSimilarity()







/***************************      RULES      **********************************/

//DOMAIN ARGUMENTS - lower weight to second rule - coz tells only syntactic correctness
	m.add rule : ( inferable(A,Q) & domainArg(A,B)) >> inferable(B,Q) , weight : 0.03		//format- Relation--Range
	m.add rule : ( inferable(A,Q) & domainArg(B,A)) >> inferable(B,Q) , weight : 0.000001

//RANGE ARGUMENTS - lower weight to second rule - coz tells only syntactic correctness	
	m.add rule : ( inferable(A,Q) & rangeArg(A,B)) >> inferable(B,Q) , weight : 0.03		//format- Relation--Range
	m.add rule : ( inferable(A,Q) & rangeArg(B,A)) >> inferable(B,Q) , weight : 0.000001
	
//SUB/SUPER SET ARGUMENTS - lower weight to second rule - coz very less chances of increase
	m.add rule : ( inferable(A,Q) & subsuperSet(B,A) ) >> inferable(B,Q) , weight : 0.80		
	m.add rule : ( inferable(A,Q) & subsuperSet(A,B) ) >> inferable(B,Q) , weight : 0.20


/* Prior to suggest that by default nothing is evaluated TRUE or FALSE */
//Negation rule for threshold
//factZero  - to identify with 0
	m.add rule : ( factZero(A,Q) ) >> ~inferable(A,Q) , weight : 0.2		//format- fact--0/1

//factOne - to identify with 1
	m.add rule : ( factOne(A,Q) ) >> ~inferable(A,Q) , weight : 0.4


//Rules for inference
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,1) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.4
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,1) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.4
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,1) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.4

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,2) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.0462
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,2) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.0462
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,2) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.0462

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,3) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.4
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,3) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.4
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,3) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.4

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,4) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.25
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,4) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.25
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,4) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.25

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,5) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.1667
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,5) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.1667
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,5) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.1667

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,6) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.0683
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,6) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.0683
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,6) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.0683

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,7) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.1429
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,7) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.1429
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,7) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.1429

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,8) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.1
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,8) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.1
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,8) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.1

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,9) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.7143
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,9) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.7143
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,9) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.7143

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,10) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.0008
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,10) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.0008
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,10) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.0008

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,11) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.2222
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,11) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.2222
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,11) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.2222

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,12) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.8
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,12) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.8
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,12) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.8

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,13) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.2778
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,13) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.2778
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,13) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.2778

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,14) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.3333
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,14) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.3333
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,14) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.3333

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,15) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.5606
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,15) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.5606
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,15) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.5606

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,16) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.4405
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,16) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.4405
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,16) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.4405

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,17) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.2
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,17) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.2
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,17) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.2

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,18) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.7857
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,18) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.7857
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,18) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.7857

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,19) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.3333
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,19) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.3333
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,19) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.3333

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,20) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.1667
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,20) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.1667
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,20) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.1667

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,21) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.5333
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,21) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.5333
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,21) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.5333

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,22) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.2778
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,22) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.2778
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,22) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.2778

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,23) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.2
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,23) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.2
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,23) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.2

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,24) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.026
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,24) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.026
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,24) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.026

	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,25) & inferable(A,Z) ) >> inferable(B,Z) , weight : 0.6875
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,25) & inferable(A,Z) ) >> inferable(C,Z) , weight : 0.6875
	m.add rule : ( fwdInfer2(H,A,B,C) & sameName(H,25) & inferable(B,Z) & inferable(C,Z) ) >> inferable(A,Z) , weight : 1.6875

	m.add rule : ( fwdInfer1(H,A,B) & sameName(H,26) & inferable(B,Z) ) >> inferable(A,Z) , weight : 0.0301
	m.add rule : ( fwdInfer1(H,A,B) & sameName(H,26) & inferable(A,Z) ) >> inferable(B,Z) , weight : 1.0301

	m.add rule : ( fwdInfer1(H,A,B) & sameName(H,27) & inferable(B,Z) ) >> inferable(A,Z) , weight : 0.2369
	m.add rule : ( fwdInfer1(H,A,B) & sameName(H,27) & inferable(A,Z) ) >> inferable(B,Z) , weight : 1.2369

	m.add rule : ( fwdInfer1(H,A,B) & sameName(H,28) & inferable(B,Z) ) >> inferable(A,Z) , weight : 0.5831
	m.add rule : ( fwdInfer1(H,A,B) & sameName(H,28) & inferable(A,Z) ) >> inferable(B,Z) , weight : 1.5831



//sum of 0 and 1 for each candidate adds to one
m.add PredicateConstraint.Functional , on : inferable






/*************************      FUNCTIONS      ********************************/


 
private class MyStringSimilarity implements ExternalFunction {
	
	@Override
	public int getArity() {
		return 2;
	}

	@Override
	public ArgumentType[] getArgumentTypes() {
		return [ArgumentType.String, ArgumentType.Integer].toArray();
	}
	
	@Override
	public double getValue(ReadOnlyDatabase db, GroundTerm... args) {
		return args[0].toString().equals(args[1].toString()) ? 1.0 : 0.0;
	}
	
}
