Skip to content

Commit

Permalink
upgrade to projog-clp v0.3.0 - resolves #215
Browse files Browse the repository at this point in the history
min, max and // can now be used in CLP expressions
  • Loading branch information
s-webber committed Jan 8, 2023
1 parent 0fcbfd8 commit 1850712
Show file tree
Hide file tree
Showing 9 changed files with 322 additions and 61 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/ma
<dependency>
<groupId>org.projog</groupId>
<artifactId>projog-clp</artifactId>
<version>0.2.0</version>
<version>0.3.0</version>
</dependency>
<dependency>
<groupId>org.projog</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,6 @@
% Y = 1
%NO
%?- X in 2..3, X#<==>Y
%NO
%?- X in 4..5, Y in 5..6, Z#<==> X#<Y, label([X,Y,Z])
% X = 4
% Y = 5
Expand All @@ -108,6 +105,12 @@
% Y = 6
% Z = 1
%NO
%?- X in 2..3, X#<==>Y
%NO
%?- X #<==> append(_,_,_)
%ERROR Cannot create CLP constraint from term: append(_, _, _)
*/
/**
* CLP predicates for comparing boolean values.
Expand Down Expand Up @@ -194,7 +197,11 @@ private Constraint toConstraint(Term t, Set<ClpVariable> vars) {
case STRUCTURE:
PredicateKey key = PredicateKey.createForTerm(t);
PredicateFactory factory = predicates.getPredicateFactory(key);
return ((ConstraintFactory) factory).createConstraint(t.getArgs(), vars);
if (factory instanceof ConstraintFactory) {
return ((ConstraintFactory) factory).createConstraint(t.getArgs(), vars);
} else {
throw new ProjogException("Cannot create CLP constraint from term: " + t);
}
default:
throw new ProjogException("Cannot get CLP expression for term: " + t + " of type: " + t.getType());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@
import org.projog.clp.Expression;
import org.projog.clp.math.Absolute;
import org.projog.clp.math.Add;
import org.projog.clp.math.Divide;
import org.projog.clp.math.Maximum;
import org.projog.clp.math.Minimum;
import org.projog.clp.math.Minus;
import org.projog.clp.math.Multiply;
import org.projog.clp.math.Subtract;

public class CommonExpression implements ExpressionFactory {
public final class CommonExpression implements ExpressionFactory {
private final Function<Expression[], Expression> function;

public static ExpressionFactory add() {
Expand All @@ -39,6 +42,18 @@ public static ExpressionFactory multiply() {
return new CommonExpression(args -> new Multiply(args[0], args[1]));
}

public static ExpressionFactory divide() {
return new CommonExpression(args -> new Divide(args[0], args[1]));
}

public static ExpressionFactory minimum() {
return new CommonExpression(args -> new Minimum(args[0], args[1]));
}

public static ExpressionFactory maximum() {
return new CommonExpression(args -> new Maximum(args[0], args[1]));
}

public static ExpressionFactory absolute() {
return new CommonExpression(args -> new Absolute(args[0]));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,120 @@
%?- 16#=X+7
% X=9
%?- 16#=X-7
%?- 16#=9+X
% X=7
%?- X-7#=16
% X=23
% TODO shouldn't need X#>0
%?- X#>0, 16#=X*8
%?- 23-X#=16
% X=7
%?- 16#=-X+2
% X=-14
%?- 16#=X*8
% X=2
%FAIL X #> 0, 16#=X*7
%FAIL 16#=X*7
%?- 16#=abs(X)+2
% X=-14..14
%?- 16#=abs(X)+2, label([X])
% X=-14
% X=14
%NO
%?- 9 #= X // 3
% X=27..29
%?- 9 #= X // 3, label([X])
% X=27
% X=28
% X=29
%NO
%?- 9 #= 27 // X
% X=3
%?- 9 #= 28 // X
% X=3
%?- 9 #= 29 // X
% X=3
%FAIL 9 #= 26 // X
%FAIL 9 #= 30 // X
%?- [X,Y] ins 0..50, 9 #= X // Y, label([X,Y])
% X=9
% Y=1
% X=18
% Y=2
% X=19
% Y=2
% X=27
% Y=3
% X=28
% Y=3
% X=29
% Y=3
% X=36
% Y=4
% X=37
% Y=4
% X=38
% Y=4
% X=39
% Y=4
% X=45
% Y=5
% X=46
% Y=5
% X=47
% Y=5
% X=48
% Y=5
% X=49
% Y=5
%NO
%?- W in 1..3, X in 2..4, Y #= min(W,X), Z #= max(W,X), label([W,X,Y,Z])
% W=1
% X=2
% Y=1
% Z=2
% W=1
% X=3
% Y=1
% Z=3
% W=1
% X=4
% Y=1
% Z=4
% W=2
% X=2
% Y=2
% Z=2
% W=2
% X=3
% Y=2
% Z=3
% W=2
% X=4
% Y=2
% Z=4
% W=3
% X=2
% Y=2
% Z=3
% W=3
% X=3
% Y=3
% Z=3
% W=3
% X=4
% Y=3
% Z=4
%NO
%FAIL 7#=8
%TRUE 8#=8
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/projog-bootstrap.pl
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,9 @@
?- pj_add_clp_expression('+'/2, 'org.projog.core.predicate.builtin.clp.CommonExpression/add').
?- pj_add_clp_expression('/'('-', 2), 'org.projog.core.predicate.builtin.clp.CommonExpression/subtract').
?- pj_add_clp_expression('*'/2, 'org.projog.core.predicate.builtin.clp.CommonExpression/multiply').
?- pj_add_clp_expression('//'/2, 'org.projog.core.predicate.builtin.clp.CommonExpression/divide').
?- pj_add_clp_expression('min'/2, 'org.projog.core.predicate.builtin.clp.CommonExpression/minimum').
?- pj_add_clp_expression('max'/2, 'org.projog.core.predicate.builtin.clp.CommonExpression/maximum').
?- pj_add_clp_expression('abs'/1, 'org.projog.core.predicate.builtin.clp.CommonExpression/absolute').
?- pj_add_clp_expression('/'('-', 1), 'org.projog.core.predicate.builtin.clp.CommonExpression/minus').

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Copyright 2023 S. Webber
*
* Licensed 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.projog.core.predicate.builtin.clp;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;

import org.junit.Test;
import org.projog.clp.Expression;
import org.projog.clp.FixedValue;
import org.projog.clp.math.Absolute;
import org.projog.clp.math.Add;
import org.projog.clp.math.Divide;
import org.projog.clp.math.Maximum;
import org.projog.clp.math.Minimum;
import org.projog.clp.math.Minus;
import org.projog.clp.math.Multiply;
import org.projog.clp.math.Subtract;

public class CommonExpressionTest {
@Test
public void testMinus() {
ExpressionFactory f = CommonExpression.minus();
Expression e = f.createExpression(new Expression[] {new FixedValue(7)});

assertSame(Minus.class, e.getClass());
assertEquals(-7L, e.getMax(null));
assertEquals(-7L, e.getMin(null));
}

@Test
public void testAbsolute() {
ExpressionFactory f = CommonExpression.absolute();
Expression e = f.createExpression(new Expression[] {new FixedValue(-7)});

assertSame(Absolute.class, e.getClass());
assertEquals(7L, e.getMax(null));
assertEquals(7L, e.getMin(null));
}

@Test
public void testAdd() {
ExpressionFactory f = CommonExpression.add();
Expression e = f.createExpression(new Expression[] {new FixedValue(7), new FixedValue(3)});

assertSame(Add.class, e.getClass());
assertEquals(10L, e.getMax(null));
assertEquals(10L, e.getMin(null));
}

@Test
public void testSubtract() {
ExpressionFactory f = CommonExpression.subtract();
Expression e = f.createExpression(new Expression[] {new FixedValue(7), new FixedValue(3)});

assertSame(Subtract.class, e.getClass());
assertEquals(4L, e.getMax(null));
assertEquals(4L, e.getMin(null));
}

@Test
public void testMultiply() {
ExpressionFactory f = CommonExpression.multiply();
Expression e = f.createExpression(new Expression[] {new FixedValue(7), new FixedValue(3)});

assertSame(Multiply.class, e.getClass());
assertEquals(21L, e.getMax(null));
assertEquals(21L, e.getMin(null));
}

@Test
public void testDivide() {
ExpressionFactory f = CommonExpression.divide();
Expression e = f.createExpression(new Expression[] {new FixedValue(27), new FixedValue(3)});

assertSame(Divide.class, e.getClass());
assertSame(9L, e.getMax(null));
assertSame(9L, e.getMin(null));
}

@Test
public void testMaximum() {
ExpressionFactory f = CommonExpression.maximum();
Expression e = f.createExpression(new Expression[] {new FixedValue(123), new FixedValue(456)});

assertSame(Maximum.class, e.getClass());
assertEquals(456L, e.getMax(null));
assertEquals(456L, e.getMin(null));
}

@Test
public void testMinimum() {
ExpressionFactory f = CommonExpression.minimum();
Expression e = f.createExpression(new Expression[] {new FixedValue(123), new FixedValue(456)});

assertSame(Minimum.class, e.getClass());
assertEquals(123L, e.getMax(null));
assertEquals(123L, e.getMin(null));
}
}
50 changes: 50 additions & 0 deletions src/test/prolog/applications/full-adder.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
full_adder(Input1,Input2,Input3,Output1,Output2) :-
Output1 #<==> (Input1 #\ Input2) #\ Input3,
Output2 #<==> (Input1 #/\ Input2) #\/ (Input3 #/\ (Input1 #\ Input2)).

%?- full_adder(1,1,1,Output1,Output2)
% Output1 = 1
% Output2 = 1

%?- full_adder(1,1,0,Output1,Output2)
% Output1 = 0
% Output2 = 1

%?- full_adder(1,0,1,Output1,Output2)
% Output1 = 0
% Output2 = 1

%?- full_adder(0,1,1,Output1,Output2)
% Output1 = 0
% Output2 = 1

%?- full_adder(1,0,0,Output1,Output2)
% Output1 = 1
% Output2 = 0

%?- full_adder(0,1,0,Output1,Output2)
% Output1 = 1
% Output2 = 0

%?- full_adder(0,0,1,Output1,Output2)
% Output1 = 1
% Output2 = 0

%?- full_adder(0,0,0,Output1,Output2)
% Output1 = 0
% Output2 = 0

%?- full_adder(0,Input2,Input3,Output1,1)
% Input2 = 1
% Input3 = 1
% Output1 = 0

%?- full_adder(Input1,0,Input3,Output1,1)
% Input1 = 1
% Input3 = 1
% Output1 = 0

%?- full_adder(Input1,Input2,0,Output1,1)
% Input1 = 1
% Input2 = 1
% Output1 = 0
18 changes: 18 additions & 0 deletions src/test/prolog/applications/full-adder.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Full Adder
<p>
A <a href="https://en.wikipedia.org/wiki/Adder_(electronics)#Full_adder">full adder</a> adds three binary numbers.
</p>
<p>
The truth table for a full adder is:
<table style="border: 1px solid black">
<tr><th>Input 1</th><th>Input 2</th><th>Input 3</th><th>Output 1</th><th>Output 2</th></tr>
<tr><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td></tr>
<tr><td>1</td><td>0</td><td>0</td><td>1</td><td>0</td></tr>
<tr><td>0</td><td>1</td><td>0</td><td>1</td><td>0</td></tr>
<tr><td>0</td><td>0</td><td>1</td><td>1</td><td>0</td></tr>
<tr><td>1</td><td>1</td><td>0</td><td>0</td><td>1</td></tr>
<tr><td>1</td><td>0</td><td>1</td><td>0</td><td>1</td></tr>
<tr><td>0</td><td>1</td><td>1</td><td>0</td><td>1</td></tr>
<tr><td>1</td><td>1</td><td>1</td><td>1</td><td>1</td></tr>
</table>
</p>
Loading

0 comments on commit 1850712

Please sign in to comment.