com.sri.ai.praise.model.v1.HOGMRandomVariableDeclaration Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aic-praise Show documentation
Show all versions of aic-praise Show documentation
SRI International's AIC PRAiSE (Probabilistic Reasoning As Symbolic Evaluation) Library (for Java 1.8+)
/*
* Copyright (c) 2013, SRI International
* All rights reserved.
* Licensed under the The BSD 3-Clause License;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://opensource.org/licenses/BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of the aic-praise nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.sri.ai.praise.model.v1;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.StringJoiner;
import com.google.common.annotations.Beta;
import com.sri.ai.expresso.api.Expression;
import com.sri.ai.expresso.helper.Expressions;
/**
* A parametric random variable declaration. The basic structure of a random
* variable declaration is as follows:
*
*
* // A random variable declaration
* randomVariable(name, arity, parameterSortName1,...,parameterSortNameN, rangeSortName),
*
* name:
* . mandatory: must be a unique string valued symbol within the model for identifying the random variable.
*
* arity:
* . optional: defaults to an integer valued symbol 0.
* specifies the number of parameters that the
* random variable takes.
*
* parameterSortName:
* . optional: only if arity is = 0. Otherwise a sort name
* must be specified for each parameter that the
* random variable takes (i.e. number specified must match
* the declared arity).
*
* rangeSortName:
* . optional: defaults to the in-built sort 'Boolean'. If specified
* must follow the parameterSortNames (i.e. there would be arity+1 sort
* names in the declaration).
*
*
*
* @author oreilly
*
*/
@Beta
public class HOGMRandomVariableDeclaration {
//
public static final String FUNCTOR_RANDOM_VARIABLE_DECLARATION = "randomVariable";
//
private Expression name = null;
private Expression arity = null;
private int intArity = 0;
private List parameters = new ArrayList();
private Expression range = null;
private Expression randomVariableDeclaration = null;
/**
* Default constructor. Will default the arity of the random variable
* declaration to 0 and range to be of sort 'Boolean'.
*
* @param name
* a unique string valued symbol for the random variable
* declaration.
*/
public HOGMRandomVariableDeclaration(Expression name) {
this(name, Expressions.ZERO, HOGMSortDeclaration.IN_BUILT_BOOLEAN.getName());
}
/**
* Constructor. Will default range to be of sort 'Boolean' if not explicitly
* added to end of list of parameters.
*
* @param name
* a unique string valued symbol for the random variable
* declaration.
* @param arity
* the number of parameters that the random variable takes
* @param parametersAndRange
* is arity > 0 must specify the sort for each parameter.
* Optional append the sort for the range of the random variable
* to the end of this list (will default to 'Boolean' if not
* specified).
*/
public HOGMRandomVariableDeclaration(Expression name, Expression arity,
Expression... parametersAndRange) {
assertNameOk(name);
assertArityOk(arity);
assertParametersAndRangeOk(name, arity, parametersAndRange);
this.name = name;
this.arity = arity;
this.intArity = arity.intValue();
if (intArity == parametersAndRange.length) {
for (int i = 0; i < parametersAndRange.length; i++) {
parameters.add(parametersAndRange[i]);
}
// default range to boolean
range = HOGMSortDeclaration.IN_BUILT_BOOLEAN.getName();
}
else {
for (int i = 0; i < parametersAndRange.length - 1; i++) {
parameters.add(parametersAndRange[i]);
}
range = parametersAndRange[parametersAndRange.length - 1];
}
}
/**
*
* @return the unique identifying name for the random variable.
*/
public Expression getName() {
return name;
}
/**
*
* @return the arity of the number of parameters that the parametric random
* variable declaration takes.
*/
public Expression getArity() {
return arity;
}
/**
*
* @return the actual value of the number of parameters that the parametric
* random variable declaration takes.
*/
public int getArityValue() {
return intArity;
}
/**
*
* @return the sorts for the parameters of the random variable declaration.
*/
public List getParameterSorts() {
return Collections.unmodifiableList(parameters);
}
/**
*
* @return the sort for the range that the random variable can take.
*/
public Expression getRangeSort() {
return range;
}
/**
*
* @return an expression representing the full random variable declaration.
*/
public Expression getRandomVariableDeclaration() {
// Lazy initialize this attribute
if (randomVariableDeclaration == null) {
List declarationArgs = new ArrayList();
declarationArgs.add(name);
declarationArgs.add(arity);
declarationArgs.addAll(parameters);
declarationArgs.add(range);
randomVariableDeclaration = Expressions.makeExpressionOnSyntaxTreeWithLabelAndSubTrees(
FUNCTOR_RANDOM_VARIABLE_DECLARATION,
declarationArgs.toArray());
}
return randomVariableDeclaration;
}
/**
*
* @return the type representation of the random variable declaration.
*/
public String toTypeRepresentation() {
String result = null;
if (getArityValue() == 0) {
result = HOGMSortDeclaration.sortReferenceAsTypeString(getRangeSort());
}
else if (getArityValue() == 1) {
result = HOGMSortDeclaration.sortReferenceAsTypeString(getParameterSorts().get(0)) + " -> " + HOGMSortDeclaration.sortReferenceAsTypeString(getRangeSort());
} else {
StringJoiner params = new StringJoiner(", ");
getParameterSorts().forEach(paramSort -> params.add(HOGMSortDeclaration.sortReferenceAsTypeString(paramSort)));
result = "'->'(x("+params.toString()+"), "+HOGMSortDeclaration.sortReferenceAsTypeString(getRangeSort())+")";
}
return result;
}
/**
*
* @return a set of IntegerInterval type strings for referenced sorts that are integer intervals.
*/
public Set getReferencedIntegerIntervalTypes() {
Set result = new LinkedHashSet<>();
getParameterSorts().forEach(paramSort -> {
if (HOGMSortDeclaration.isNumberRangeReference(paramSort)) {
result.add(HOGMSortDeclaration.sortReferenceAsTypeString(paramSort));
}
});
if (HOGMSortDeclaration.isNumberRangeReference(getRangeSort())) {
result.add(HOGMSortDeclaration.sortReferenceAsTypeString(getRangeSort()));
}
return result;
}
//
// STATIC UTILITY ROUTINES
//
/**
* Determine if an expressions is a legal random variable declaration.
*
* @param expression
* an expression to be checked for whether or not it is a legal
* random variable declaration.
* @return true if a legal random variable declaration, false otherwise.
*/
public static boolean isRandomVariableDeclaration(Expression expression) {
boolean isRandomVariableDeclaration = false;
try {
// Attempt to construct a RandomVariableDeclaration instance from the expression
makeRandomVariableDeclaration(expression);
isRandomVariableDeclaration = true;
} catch (IllegalArgumentException iae) {
isRandomVariableDeclaration = false;
}
return isRandomVariableDeclaration;
}
/**
* Make a random variable declaration object. Will default the arity of the
* random variable declaration to 0 and range to be of sort 'Boolean' if not
* specified in the expression passed in.
*
* @param expression
* an expression in the form of a random variable declaration.
* @return a RandomVariableDeclaration object corresonding to the expression
* passed in.
*/
public static HOGMRandomVariableDeclaration makeRandomVariableDeclaration(
Expression expression) {
HOGMRandomVariableDeclaration declaration = null;
if (Expressions.hasFunctor(expression, FUNCTOR_RANDOM_VARIABLE_DECLARATION)) {
int numArgs = expression.numberOfArguments();
if (numArgs > 0) {
// Extract arguments
Expression name = expression.get(0);
Expression arity = Expressions.ZERO;
if (numArgs >= 2) {
arity = expression.get(1);
}
Expression[] parametersAndRange = new Expression[0];
if (numArgs > 2) {
parametersAndRange = new Expression[numArgs - 2];
for (int i = 2; i < numArgs; i++) {
parametersAndRange[i - 2] = expression.get(i);
}
}
else {
parametersAndRange = new Expression[0];
}
declaration = new HOGMRandomVariableDeclaration(name, arity, parametersAndRange);
}
}
if (declaration == null) {
throw new IllegalArgumentException(
"Not a legal definition of a random variable declartion:" + expression);
}
return declaration;
}
//
// PRIVATE METHODS
//
private static void assertNameOk(Expression name) {
boolean illegal = true;
if (Expressions.isSymbol(name)
&& name.getValue() instanceof String
// Ensure is not a String Literal
&& !Expressions.isStringLiteral(name)) {
illegal = false;
}
if (illegal) {
throw new IllegalArgumentException(
"name ["
+ name
+ "] is not of the correct type. must be a string valued symbol.");
}
}
private static void assertArityOk(Expression arity) {
boolean illegal = true;
if (arity.getSyntacticFormType().equals("Symbol")) {
Object value = arity.getValue();
if (value instanceof Number) {
int ivalue = ((Number) value).intValue();
if (ivalue >= 0) {
illegal = false;
}
}
}
if (illegal) {
throw new IllegalArgumentException(
"arity ["
+ arity
+ "] is not of the correct type. must be an integer valued symbol.");
}
}
private static void assertParametersAndRangeOk(Expression name,
Expression arity, Expression... parametersAndRange) {
boolean illegal = true;
int intArity = arity.intValue();
if (intArity == parametersAndRange.length
|| intArity == parametersAndRange.length - 1) {
// Ensure are legal names for sorts and do not conflict with name of
// the random variable declaration
boolean sortNamesOk = true;
for (int i = 0; i < parametersAndRange.length; i++) {
HOGMSortDeclaration.isSortReference(parametersAndRange[i]);
if (name.equals(parametersAndRange[i])) {
sortNamesOk = false;
break;
}
}
if (sortNamesOk) {
illegal = false;
}
}
if (illegal) {
throw new IllegalArgumentException("Parameters and Range ["
+ parametersAndRange.length
+ "] do not match up with arity [" + arity + "]");
}
}
}