Menu

How to set utilities for solution space

Help
Xie Yi
2015-05-18
2015-07-23
1 2 > >> (Page 1 of 2)
  • Xie Yi

    Xie Yi - 2015-05-18

    I want to call Frodo2 in API mode. I use Hypercube for solution space. According to the document, I can use setUtility to assign utility to every assignment to variables. But I checked out the source code and found this function had not been implemented yet.
    So I have to give utilities through the constructor. The problem I met is that I can't figure out the proper order of the array of utility. The comment in the source says the first utility corresponds to the assignment in which each variable is assigned its smallest value. But what is the value is in string type. which assignment does the second element of the array correspond to?
    If the following table is the utility table, what is the order of the utilities array?

    A\B b1 b2
    a1 u11 u12
    a2 u21 u22

    variable_order = {A,B}
    variable_domains = {{a1,a2},{b1,b2}}
    utility_values = ?

     

    Last edit: Xie Yi 2015-05-18
  • Xie Yi

    Xie Yi - 2015-05-18

    By the way, if some assignments are infeasible, how could I set the utility_value.

     
  • Thomas B. Léauté

    Hi Xie Yi,

    Looking at the source code of the latest version of FRODO, Hypercube.setUtility() has been implemented (it is inherited from the superclass BasicHypercube). You should be able to call this method to set the utilities of your hypercube. Let me know what error message you are getting if this is not working for you.

    Alternatively, you can call the constructor with signature Hypercube(String[] variables, V[][] variables, Object[] utilities, U infeasibleUtil), and pass it a multi-dimensional array of utilities. In your example, you would have:

    utilities = [[u11, u12], [u21, u22]]
    

    The Doxygen documentation for the input utility_values of the constructor you have been trying to use is a bit misleading; it should read "its first value" instead of "its smallest value." But you don't need to use this constructor; just use the one I mentioned above, which is more user-friendly, or call setUtility().

    When it comes the representation of infeasible solutions, you can call getPlusInfinity() or getMinInfinity() on your problem instance, as documented in the user manual. This method basically returns the infeasibleUtil object that you should pass to the Hypercube constructor anyway.

    Best,

    Thomas

     
  • Xie Yi

    Xie Yi - 2015-05-19

    It seems the setUtility function is overrode in the subclass Hypercube.

     
  • Thomas B. Léauté

    setUtility() is overridden in the class NullHypercube, which is a special, internal subclass of Hypercube used to represent hypercubes that do not contain any solutions. But you should be able to call Hypercube.setUtility(). If it is not working for you, please describe the error message you are getting or the unexpected results you are seeing.

     
  • Xie Yi

    Xie Yi - 2015-05-19

    There is one more thing I haven't got. When I add map from assignments to utilities through setUtility, how could Hypercube know which variables I am talking about?

     

    Last edit: Xie Yi 2015-05-19
  • Thomas B. Léauté

    As explained in the Doxygen documentation of BasicHypercube.setUtility(V[], U), this method assumes that the values for the variables are input in the same order as the variable order of the hypercube.

    In other words, if you have defined your hypercube using the variable order

    variable_order = [A, B]
    

    then you should call setUtility() by passing it first the value for A, and then the value for B:

    hypercube.setUtility([a1, b1], u11);
    hypercube.setUtility([a1, b2], u12);
    hypercube.setUtility([a2, b1], u21);
    hypercube.setUtility([a2, b2], u22);
    

    By the way, would you find it useful if you had access to the Doxygen documentation for the FRODO API in HTML format rather than having to look into the code? I used to produce such an HTML API documentation, but then I stopped doing so because I suspected nobody found it useful. You might have a different opinion, since you are calling FRODO via the API, which is unusual. Let me know if such an HTML API documentation would be useful to you, and I will generated it again (which is easy to do).

     
  • Xie Yi

    Xie Yi - 2015-05-19

    Is the Frodo2 user manual the Doxygen documentation you mentioned? I would appreciate if you could provide a document giving more details. Thanks!

     
  • Thomas B. Léauté

    I am referring to this. Let me know if you find it helpful.

     
  • Xie Yi

    Xie Yi - 2015-05-22

    Thanks! It is helpful.

     
  • Thomas B. Léauté

    In that case, I will resume producing this Doxygen documentation for the upcoming FRODO releases. Thanks for your input.

     
  • Xie Yi

    Xie Yi - 2015-07-13

    I created a hypercube with constructor whose descriptor is "([Ljava/lang/String;[[Lfrodo2/solutionSpaces/AddableString;[Lfrodo2/solutionSpaces/AddableReal;Lfrodo2/solutionSpaces/AddableReal;)V". I gave the var names, their domains, an empty array for utilities and infeasible utility value to the constructor. when I assign utility values with setUtility, I get return value false. I cant assign utility value properly following the above instructions.

     

    Last edit: Xie Yi 2015-07-13
  • Thomas B. Léauté

    Hi Xie Yi,

    It's a bit hard for me to remote-debug your code, but here are some questions that might lead you in the right direction:

    1. Is it possible for you to enable Java asserts? Sometimes it helps catch mistakes (but it does make FRODO slower).
    2. Have you set the right size for the array of utility values that you pass on to the Hypercube constructor? It must be the product of the sizes of all the variables' domains.
    3. Does your class AddableString properly implement the methods hashCode() and equals()?
    4. When you call setUtility(), are you passing the variable values in the same order as the variable order you gave to the Hypercube constructor? This is the same variable order as the one returned by getVariables().

    Hope this helps,

    Thomas

     
  • Xie Yi

    Xie Yi - 2015-07-14

    I debugged with jdb and found the problem occurred at line 504 of BasicHypercube.java. the variables_values[i] is "variables_values[i] = "frodo2.solutionSpaces.AddableString@1ad6f"". the content of steps_hashmap is "steps_hashmap = "{frodo2.solutionSpaces.AddableString@c8a6c057=8, frodo2.solutionSpaces.AddableString@642d030
    9=0, frodo2.solutionSpaces.AddableString@7102b84f=4, frodo2.solutionSpaces.AddableString@cff27ea7=16, frodo2.s
    olutionSpaces.AddableString@1ad6f=12}"". but the step gets the return value null. I implemented the hashCode of AddableString with the hashCode of String. Do you have any idea of the problem? Thanks!

     

    Last edit: Xie Yi 2015-07-14
  • Xie Yi

    Xie Yi - 2015-07-14

    the code of AddableString is pasted here for your reference.

     
  • Thomas B. Léauté

    By the way, you probably want to also implement AddableString.toString() (overridden from Object), to make the contents of the steps_hashmap more readable.

    However, this is not going to solve the problem. I'll get back to you soon when I find some time.

     
  • Thomas B. Léauté

    In fact, you could include the output of AddableString.hashCode() inside the output of AddableString.toString() to help debug what is happening.

     
  • Thomas B. Léauté

    After looking at your code, it appears it contains a classical mistake, which is the subtle but critical difference between calling equals() and using the == operator.

    In particular, in your implementation of AddableString.equals(), you use the == operator to compare the underlying values, when in fact you should (also) be calling equals(). Here is what AddableString.equals() should look like:

    @Override
    public boolean equals (Object o) {
    
        // First check if the two objects are the same 
        if (this == o) {
            return true;
        }
    
        // Attempt to cast the input object to an AddableString 
        AddableString as = null;
        try {
            as = (AddableString) o;
        } catch (ClassCastException e) {
            return false; 
        }
    
        return this.value == as.value // catches the case when this.value == null 
                || this.value.equals(as.value); 
    }
    

    There is another such mistake in AddabaleString.readResolve(), in which you should use String.equals() instead of the == operator.

    I hope this solves your problem.

    Thomas

     
  • Xie Yi

    Xie Yi - 2015-07-21

    Thx for digging out the problem from my code! I am really appreciated. This problem is solved. But another problem appeared. The DPOPsover::solve processes without problem with the input I gave. But when I call Solution::getAssignments to get solution, an exception prompts out. I debugged the program and found the problem occurred at line 1423 of Hypercube.java. The util got a null value and crash the following code. what do you think of the cause of the problem. Are the function for serialization of Problem implemented. Maybe I should give a copy of it.

     

    Last edit: Xie Yi 2015-07-21
  • Thomas B. Léauté

    Hi Xie Yi,

    Can you copy-paste the full exception trace you are getting? It is not possible that calling Solution::getAssigments generates a NullPointerException, because the only thing this method does is return a Map stored in the Solution object. The NullPointerException must be generated somewhere else.

    Can you also print the output of Problem::toString() before passing it to the DPOPsolver, to check that all your solution spaces look correct and are not missing utilities?

    Best,

    Thomas

     
  • Xie Yi

    Xie Yi - 2015-07-21

    This is the whole exception message
    java.lang.ClassCastException: frodo2.solutionSpaces.AddableReal cannot be cast to frodo2.solutionSpaces.AddableInteger
    at frodo2.solutionSpaces.AddableInteger.subtract(AddableInteger.java:1)
    at frodo2.solutionSpaces.hypercube.JoinOutputHypercube$JoinOutputIterator.getCurrentUtility(JoinOutputHypercube.java:142)
    at frodo2.solutionSpaces.hypercube.JoinOutputHypercube$JoinOutputIterator.getCurrentUtility(JoinOutputHypercube.java:1)
    at frodo2.solutionSpaces.hypercube.Hypercube.project(Hypercube.java:1423)
    at frodo2.solutionSpaces.hypercube.JoinOutputHypercube.project(JoinOutputHypercube.java:870)
    at frodo2.algorithms.dpop.UTILpropagation.project(UTILpropagation.java:622)
    at frodo2.algorithms.dpop.UTILpropagation.projectAndSend(UTILpropagation.java:601)
    at frodo2.algorithms.dpop.UTILpropagation.notifyIn(UTILpropagation.java:424)
    at frodo2.communication.mailer.CentralMailer$FakeQueue.notifyInListeners(CentralMailer.java:221)
    at frodo2.communication.mailer.CentralMailer.run(CentralMailer.java:663)
    Timed out after 600000 ms (simulated time)
    MultiagentCooperation: DCOP.cpp:182: std::map<boost::uuids::uuid, boost::variant<boost::uuids::uuid,="" NotSensing=""> > DCOP::solve(boost::filtered_graph<boost::adjacency_list<boost::vecS, boost::setS,="" boost::directedS,="" boost::property<vertex_BatteryLevel_t,="" int,="" boost::property<vertex_ObservationHistory_t,="" std::deque<Observation="">, boost::property<boost::vertex_name_t, boost::uuids::uuid=""> > >, boost::property<edge_QFunction_t, QTable,="" boost::property<edge_Eligibility_t,="" QTable=""> > >, CutGraphFilter>&): Assertion `false == jvm().ExceptionCheck()' failed.

     
  • Xie Yi

    Xie Yi - 2015-07-21

    sometime, the exception is
    The CentralMailer was interrupted due to the following exception:
    java.lang.NullPointerException
    at frodo2.solutionSpaces.hypercube.Hypercube.project(Hypercube.java:1425)
    at frodo2.solutionSpaces.hypercube.JoinOutputHypercube.project(JoinOutputHypercube.java:870)
    at frodo2.algorithms.dpop.UTILpropagation.project(UTILpropagation.java:622)
    at frodo2.algorithms.dpop.UTILpropagation.projectAndSend(UTILpropagation.java:601)
    at frodo2.algorithms.dpop.UTILpropagation.notifyIn(UTILpropagation.java:424)
    at frodo2.communication.mailer.CentralMailer$FakeQueue.notifyInListeners(CentralMailer.java:221)
    at frodo2.communication.mailer.CentralMailer.run(CentralMailer.java:663)
    Timed out after 600000 ms (simulated time)
    MultiagentCooperation: DCOP.cpp:182: std::map<boost::uuids::uuid, boost::variant<boost::uuids::uuid,="" NotSensing=""> > DCOP::solve(boost::filtered_graph<boost::adjacency_list<boost::vecS, boost::setS,="" boost::directedS,="" boost::property<vertex_BatteryLevel_t,="" int,="" boost::property<vertex_ObservationHistory_t,="" std::deque<Observation="">, boost::property<boost::vertex_name_t, boost::uuids::uuid=""> > >, boost::property<edge_QFunction_t, QTable,="" boost::property<edge_Eligibility_t,="" QTable=""> > >, CutGraphFilter>&): Assertion `false == jvm().ExceptionCheck()' failed.

     
  • Thomas B. Léauté

    Hi Xie Yi,

    The first ClassCastException you are reporting suggests that your DCOP problem instance mixes constraints (i.e. hypercubes) with different types for the utilities: some apparently use AddableInteger, while others AddableReal. You want to make sure that you always use the same class for all utilities. Also, if you don't use AddableInteger (which is the default), you will have to call the method Problem.setUtilClass().

    The second NullPointerException suggests that not all constraints in your problem instance have all their utilities set to non-null values. You probably want to inspect your problem instance by displaying the output of Problem.toString() as I suggested earlier, to check that none of the hypercubes has any null entry in its utility array. The infeasibleUtil attribute must also be non-null.

    By the way, notice that none of these two exceptions is actually thrown by Solution.getAssignments(). In both cases, the exception is thrown by DPOP's UTILpropagation module, but then it is caught by the DPOPsolver, which prints it out, and then just returns from DPOPsolver.solve() while reporting that DPOP "timeout out after 600000 ms (simulated time)." 600000 ms = 10 min is the default timeout, which would have been reached if the DPOPsolver had just waited for the algorithm to terminate, which it never would have since it had hit an exception.

    Best,

    Thomas

     
  • Xie Yi

    Xie Yi - 2015-07-23

    I have got rid of the classcastexception. Now I am still figuring the nullpointerexception. I replace all null utility values with infeasible values in hypercube. Now I get

    • Hypercube ():
      37b0d7dd-59b0-4107-bbe1-83a3ce3132c0 : [c76221ad-da8e-47b3-bb56-228f60af8235, 2ba2118c-81bf-4712-b3ae-0c743548af8d, off, recharge]
      2ba2118c-81bf-4712-b3ae-0c743548af8d : [8ed44198-cb19-44e4-bfce-1fa538d09c21, cffc15a7-ef52-4e1f-abfa-a0a4f5202c39, 37b0d7dd-59b0-4107-bbe1-83a3ce3132c0, off, recharge]
      [-infinity, -infinity, -infinity, -infinity, -infinity, -infinity, -infinity, -infinity, -infinity, -infinity, -infinity, -infinity, -infinity, 0.22381194354966283, -infinity, -infinity, -infinity, -infinity, -infinity, -infinity]

    Because my system has a cold start, not all action combinations has a corresponding utility value at the beginning. Is the hypercube OK? I added several hyperbcubes like this to the Problem object and call the solve function. Another exception prompted.

    The CentralMailer was interrupted due to the following exception:
    java.lang.ArrayStoreException: frodo2.solutionSpaces.AddableString
    at frodo2.algorithms.dpop.VALUEpropagation.sendVALUEmessage(VALUEpropagation.java:471)
    at frodo2.algorithms.dpop.VALUEpropagation.computeOptValAndSendVALUEmsgs(VALUEpropagation.java:510)
    at frodo2.algorithms.dpop.VALUEpropagation.notifyIn(VALUEpropagation.java:409)
    at frodo2.communication.mailer.CentralMailer$FakeQueue.notifyInListeners(CentralMailer.java:221)
    at frodo2.communication.mailer.CentralMailer.run(CentralMailer.java:663)
    Timed out after 600000 ms (simulated time)
    Exception in thread "main" java.lang.NullPointerException

    what shall I do with this problem? thx

     

    Last edit: Xie Yi 2015-07-23
  • Thomas B. Léauté

    Your hypercube looks good.

    Now, the next problem is that you need to call Problem.setDomClass() to tell to the Problem instance what class you are using as V for variable values. If you look at the current implementation for this method, you will see that, unfortunately, at the moment it does not support anything other than V = AddableInteger. You will have to subclass Problem to create your own Problem class that supports V = AddableString.

    Let me know if you encounter problems when doing so.

     
1 2 > >> (Page 1 of 2)

Log in to post a comment.