I am using JavaBDD to do some computation with BDDs.
I have a very large BDD with many variables and I want to calculate how many ways it can be satisfied with a small subset of those variables.
My current attempt looks like this:
// var 1,2,3 are BDDVarSets with 1 variable.
BDDVarSet union = var1;
union = union.union(var2);
union = union.union(var3);
BDD varSet restOfVars = allVars.minus(union);
BDD result = largeBdd.exist(restOfVars);
double sats = result.satCount(); // Returns a very large number (way too large).
double partSats = result.satCount(union) // Returns an inccorrect number. It is documented that this should not work.
Is the usage of exist() incorrect?
After a bit of playing around I understood what my problem was.
double partSats = result.satCount(union);
Does return the correct answer. What it does is calculate how many possible solutions there are, and divides the solution by 2^(#vars in set).
The reason I thought satCount(union) does not work is due to an incorrect usage of exist() somewhere else in the code.
Here is the implementation of satCound(varSet) for reference:
/**
* <p>Calculates the number of satisfying variable assignments to the variables
* in the given varset. ASSUMES THAT THE BDD DOES NOT HAVE ANY ASSIGNMENTS TO
* VARIABLES THAT ARE NOT IN VARSET. You will need to quantify out the other
* variables first.</p>
*
* <p>Compare to bdd_satcountset.</p>
*
* #return the number of satisfying variable assignments
*/
public double satCount(BDDVarSet varset) {
BDDFactory factory = getFactory();
if (varset.isEmpty() || isZero()) /* empty set */
return 0.;
double unused = factory.varNum();
unused -= varset.size();
unused = satCount() / Math.pow(2.0, unused);
return unused >= 1.0 ? unused : 1.0;
}
Related
Though I am sure that this answer is simple, I am not sure that is asked of me for this assignment. Here is the full code that I have written (so just a return!) as well as the instructions that were given:
package code;
/**
* This class contains a variety of methods that will be used throughout the Ratings and Reviews
* project.
*/
public class Utilities{
/**
* Computes the average of two ratings
*
* #param rating0 An integer rating in the range of 1-5 inclusive
* #param rating1 An integer rating in the range of 1-5 inclusive
* #return the average of rating0 and rating1 as a double
*/
public double averageRating(int rating0, int rating1){
return ((rating0 + rating1) / 2); // Don't forget to replace this return statement with your own
}
Sorry for bad structure upon pasting it. I think my return is suitable for what is being done, provided that the rating could be just anything. I know that it can only be between 1-5, though, so how would one go about specifying that?
How about throwing an InvalidArgumentException if the range is violated?
e.g.
public double averageRating(int rating0, int rating1){
if (rating0 < 1 || rating0 > 5 || rating1 < 1 || rating1 > 5) {
throw new InvalidArgumentException("Rating out of range");
}
return ((rating0 + rating1) / 2.0); // Don't forget to replace this return statement with your own
}
I am basically being asked to take the Unicode value of a string, multiply it by 10% and add whatever level the object currently has. It's frustrating because as it turns out I have the logic down including the code yet I still get an error that says: expected:<0> but was:<8>. Any suggestions, maybe it's just a slight nuance I have to make in the logic, although I'm fairly certain it's right. Take note of the getLevel method because that's where the error is
public class PouchCreature implements Battleable {
private String name;
private int strength;
private int levelUps;
private int victoriesSinceLevelUp;
/**
* Standard constructor. levelUps and victoriesSinceLevelUp start at 0.
*
* #param nameIn desired name for this PouchCreature
* #param strengthIn starting strength for this PouchCreature
*/
public PouchCreature(String nameIn, int strengthIn) {
this.name = nameIn;
this.strength = strengthIn;
this.levelUps = 0;
this.victoriesSinceLevelUp = 0;
}
/**
* Copy constructor.
*
* #param other reference to the existing object which is the basis of the new one
*/
public PouchCreature(PouchCreature other) {
this.name=other.name;
this.strength=other.strength;
this.levelUps=other.levelUps;
this.victoriesSinceLevelUp=other.victoriesSinceLevelUp;
}
/**
* Getter for skill level of the PouchCreature, which is based on the
* first character of its name and the number of levelUps it has.
* Specifically, the UNICODE value of the first character in its name
* taken %10 plus the levelUps.
*
* #return skill level of the PouchCreature
*/
public int getLevel() {
int value = (int)((int)(getName().charAt(0)) * 0.1);
return value + this.levelUps;
}
You've said you're supposed to increase the value by 10%. What you're actually doing, though, is reducing it 90% by taking just 10% of it (and then truncating that to an int). 67.0 * 0.1 = 6.7, which when truncated to an int is 6.
Change the 0.1 to 1.1 to increase it by 10%:
int value = (int)((int)(getName().charAt(0)) * 1.1);
// --------------------------------------------^
There, if getName() returns "Centaur" (for instance), the C has the Unicode value 67, and value ends up being 73.
We need to see the code you're calling the class with and that is generating your error message. Why is it expecting 0? 8 seems like a valid return value from the information you've given.
I tried to make a program (in Java) that calculates pi with the Chudnovsky algorithm but it has the output NaN (Not a Number). Please help me find mistakes in my code, or improve my code. (I don't have a lot of Java programming knowledge)
You can find Chudnovsky's algorithm here:
https://en.wikipedia.org/wiki/Chudnovsky_algorithm
here is my code:
package main;
public class Class1 {
public static void main(String[] args)
{
double nr1=0,nr2=0,nr3=0,pi=0;
int fo1=1, fo2=1, fo3=1;
for(int i=0; i<=20; i++){
for(int fl1=1; fl1<=(6*i); fl1++){fo1 = fo1 * fl1;}
for(int fl2=1; fl2<=(3*i); fl2++){fo2 = fo2 * fl2;}
for(int fl3=1; fl3<=(i); fl3++){fo3 = fo3 * fl3;}
nr1 = ( (Math.pow(-1, i)) * (fo1) * ((545140134*i) + 13591409) );
nr2 = ( (fo2) * (Math.pow(fo3, i)) * ( Math.pow(Math.pow(640320, 3), (i+(1/2)) )) );
nr3 = 12 * (nr1/nr2);
}
pi = 1/nr3;
System.out.println((Math.PI));
System.out.println(pi);
}
}
There are many issues here.
As Andy mentioned, 1/2 is not 0.5.
You are using integers to compute things like 120! which is completely out of bounds for any primitive type.
f01,f02,f03 should be initialized inside each loop, otherwise they grow even bigger
It is not trivial to fix it. You can take a look at
Error calculating pi using the Chudnovsky algorithm - Java
and
http://www.craig-wood.com/nick/articles/pi-chudnovsky/
for some hints, but don't expect built-in primitive types to work with that algorithm.
I have a very simple code taken from this example, where I am using the Lin, Path and Wu-Palmer similarity measures to compute the similarity between two words. My code is as follows:
import edu.cmu.lti.lexical_db.ILexicalDatabase;
import edu.cmu.lti.lexical_db.NictWordNet;
import edu.cmu.lti.ws4j.RelatednessCalculator;
import edu.cmu.lti.ws4j.impl.Lin;
import edu.cmu.lti.ws4j.impl.Path;
import edu.cmu.lti.ws4j.impl.WuPalmer;
public class Test {
private static ILexicalDatabase db = new NictWordNet();
private static RelatednessCalculator lin = new Lin(db);
private static RelatednessCalculator wup = new WuPalmer(db);
private static RelatednessCalculator path = new Path(db);
public static void main(String[] args) {
String w1 = "walk";
String w2 = "trot";
System.out.println(lin.calcRelatednessOfWords(w1, w2));
System.out.println(wup.calcRelatednessOfWords(w1, w2));
System.out.println(path.calcRelatednessOfWords(w1, w2));
}
}
And the scores are as expected EXCEPT when both words are identical. If both words are the same (e.g. w1 = "walk"; w2 = "walk";), the three measures I have should each return 1.0. But instead, they are returning 1.7976931348623157E308.
I have used ws4j before (the same version, in fact), but I have never seen this behavior. Searching online has not yielded any clues. What could possibly be going wrong here?
P.S. The fact that the Lin, Wu-Palmer and Path measures should return 1 can also be verified with the online demo provided by ws4j
I had a similar problem, and here's what's going on here. I hope that other people who run into this problem will find by response helpful.
If you have noticed, the online demo allows you to choose word sense by specifying word in the following format: word#pos_tag#word_sense. For example, a noun gender with the first word sense would be gender#n#1.
Your code snippet uses the first word sense by default. When I calculate WuPalmer similarity between "gender" and "sex", it will return 0.26. If I use online demo, it will return 1.0. But if we use "gender#n#1" and "sex#n#1" the online demo will return 0.26, so there is no discrepancy. The online demo calculates the max of all pos tag / word sense pairs. Here's a corresponding snippet of code that should do the trick:
ILexicalDatabase db = new NictWordNet();
WS4JConfiguration.getInstance().setMFS(true);
RelatednessCalculator rc = new Lin(db);
String word1 = "gender";
String word2 = "sex";
List<POS[]> posPairs = rc.getPOSPairs();
double maxScore = -1D;
for(POS[] posPair: posPairs) {
List<Concept> synsets1 = (List<Concept>)db.getAllConcepts(word1, posPair[0].toString());
List<Concept> synsets2 = (List<Concept>)db.getAllConcepts(word2, posPair[1].toString());
for(Concept synset1: synsets1) {
for (Concept synset2: synsets2) {
Relatedness relatedness = rc.calcRelatednessOfSynset(synset1, synset2);
double score = relatedness.getScore();
if (score > maxScore) {
maxScore = score;
}
}
}
}
if (maxScore == -1D) {
maxScore = 0.0;
}
System.out.println("sim('" + word1 + "', '" + word2 + "') = " + maxScore);
Also, this will give you 0.0 similarity on non-stemmed word forms, e.g. 'genders' and 'sex.' You can use a porter stemmer included in ws4j to make sure you stem words beforehand if needed.
Hope this helps!
I had raised this issue at the googlecode site for ws4j, and it turns out that indeed it was a bug. The reply I received is as follows:
This looks like it is due to attempting to override a protected static field (this can't be done in Java). The attached patch fixes the issue by moving the definition of min and max the fields to non-static final members in RelatednessCalculator and adding getters. Implementations then provide their min/max values through super constructor calls.
Patch can be applied with patch -p1 < 0001-Cannot-override-static-members-replacing-fields-with.patch
And here is the (now resolved) issue on their site.
Here is why -
In jcn we have...
sim(c1, c2) = 1 / distance(c1, c2)
distance(c1, c2) = ic(c1) + ic(c2) - (2 * ic(lcs(c1, c2)))
where c1, c2 are the two concepts,
ic is the information content of the concept.
lcs(c1, c2) is the least common subsumer of c1 and c2.
Now, we don't want distance to be 0 (=> similarity will become
undefined).
distance can be 0 in 2 cases...
(1) ic(c1) = ic(c2) = ic(lcs(c1, c2)) = 0
ic(lcs(c1, c2)) can be 0 if the lcs turns out to be the root
node (information content of the root node is zero). But since
c1 and c2 can never be the root node, ic(c1) and ic(c2) would be 0
only if the 2 concepts have a 0 frequency count, in which case, for
lack of data, we return a relatedness of 0 (similar to the lin case).
Note that the root node ACTUALLY has an information content of
zero. Technically, none of the other concepts can have an information
content value of zero. We assign concepts zero values, when
in reality their information content is undefined (due to zero
frequency counts). To see why look at the formula for information
content: ic(c) = -log(freq(c)/freq(ROOT)) {log(0)? log(1)?}
(2) The second case that distance turns out to be zero is when...
ic(c1) + ic(c2) = 2 * ic(lcs(c1, c2))
(which could have a more likely special case ic(c1) = ic(c2) =
ic(lcs(c1, c2)) if all three turn out to be the same concept.)
How should one handle this?
Intuitively this is the case of maximum relatedness (zero
distance). For jcn this relatedness would be infinity... But we
can't return infinity. And simply returning a 0 wouldn't work...
since here we have found a pair of concepts with maximum
relatedness, and returning a 0 would be like saying that they
aren't related at all.
1.7976931348623157E308 is the value of Double.MAX_VALUE but the maximum value of some similarity/relatedness algo (Lin, WuPalmer and Path) are between 0 and 1. Then , for identical synset, the maxium value can be returned is 1. Into the version of my repo (https://github.com/DonatoMeoli/WS4J) i fixed this and other bugs.
Now, for two identical words, the values returned are:
HirstStOnge 16.0
LeacockChodorow 1.7976931348623157E308
Lesk 1.7976931348623157E308
WuPalmer 1.0
Resnik 1.7976931348623157E308
JiangConrath 1.7976931348623157E308
Lin 1.0
Path 1.0
Done in 67 msec.
Process finished with exit code 0
I want to do an operation like this : if the given float numbers are like 1.0 , 2.0 , 3.0 , I want to save them to database as integer (1,2,3 ), if they are like 1.1 , 2.1 , ,3.44 , I save them as float. what's the best solution for this problem using java ? The corresponding field in database is type of varchar.
Just try int i = (int) f;.
EDIT : I see the point in the question. This code might work :
int i = (int) f;
String valToStore = (i == f) ? String.valueOf(i) : String.valueOf(f);
String result = "0";
if (floatVar == Math.floor(floatVar)) {
result = Integer.toString((int) floatVar);
} else {
result = Float.toString(floatVar);
}
The if-clause checks whether the number is a whole number - i.e. if it is equal to the result of rounding it down to the closest whole value.
But this is very odd requirement indeed, and perhaps you should reconsider the need for such a thing.
Seems like you want to save Floats with no trailing numbers as Integers, while saving those with significant trailing numbers as Floats. I would rather just save it all as Float to the DB, but it's your question so here's my answer:
/**
* Method to determine if trailing numbers are significant or not. Significant
* here means larger than 0
*
* #param fFloat
* #return
*/
public static boolean isTrailingSignificant(Float fFloat)
{
int iConvertedFloat = fFloat.intValue();// this drops trailing numbers
// checks if difference is 0
return ((fFloat - iConvertedFloat) > 0);
}
This is how you would use this method:
Number oNumToSave = null;
if (isTrailingSignificant(fFloat))
{
// save float value as is
oNumToSave = fFloat;
}
else
{
// save as int
oNumToSave = fFloat.intValue();// drops trailing numbers
}
After that, you can do the database operation using the variable oNumToSave.
Not sure this is the best solution, but you can try to write a method like this :
String convertToString(Float f) {
if (f.toString().endsWith(".0"))
return f.intValue().toString();
else
return f.toString();
}
Kotlin:
val mAmount = 3.0
val intAmount = mAmount.toInt()
val amountToDisplay = if (intAmount.compareTo(mAmount) == 0) intAmount.toString() else java.lang.String.valueOf(mAmount)