verivote / beast Goto Github PK
View Code? Open in Web Editor NEWBEAST aims to make the verification of voting rules easier
License: MIT License
BEAST aims to make the verification of voting rules easier
License: MIT License
Variables which are bound by quantified expressions only matter within those expressions, not outside of them.
Defined symbolic variables can be used as bound variables in quantified expressions. The resulting C code thus declares this variable two times, once in the beginning and once in the loop itself, more precisely as the loop index which is declared and initialized.
Forbid symbolic variables as bound variables in quantified expressions, i.e., only allow new/fresh variables to be bound by quantifiers.
Alternatively, a new variable could be produced, but I would rather have a clear distinction already in the property editor.
In the property editor, I specify as symbolic variables a candidate Alice and a voter Bob, with the following precondition:
VOTER_AT_POS(0) == Bob;
!EXISTS_ONE_VOTER(Bob) :VOTES1(Bob) == Alice;
and the following postcondition:
ELECT1 != Alice;
VOTER_AT_POS(0) == Bob;
Among other code, the following c code is produced:
unsigned int Bob = nondet_uint();
assume (0 <= Bob && Bob < V);
// ...
for (unsigned int Bob = 0; Bob < V && !thereExists_0; Bob++) { /* ... */ }
// ...
unsigned int comparison_2 = 1;
comparison_2 = voterAtPos_1 == Bob;
assert (comparison_2);
Note that Bob is declared two times. Apparently, gcc is not picky about this program itself, but it is at least confusing to the reader and I am not too sure whether this is the intended behaviour.
The indexes of the Candidates should start from 0 (not from 1). So they match the given votes (they start from 0 as well)
If the Candidate is the same number as C (the max number of Candidates) the counterexample should state "unentschieden" or something similar. Candidate C is NOT a Candidate but used as a 'not valid' statement.
You cannot view 2 results in the property list at the same time. Would be better if you could compare results side by side.
Seen in v1.4.12
How you can recreate the Bug:
Load the project-file "PreferenceBug" into the program.
Try to open another project-file. Press safe changes.
Now the NullpointerException is thrown.
Bug found on 1.4.05
When generating code which BEAST claims as valid, and then starting CBMC, an error occurs:
The user should be able to compare two voting arrays.
If the user wants to compare two voting arrays, cbmc fails with the error:
member operator requires structure type on left hand side but got `unsigned int [1]'
CONVERSION ERROR
Numeric exception : 0
Open BEAST, create a new Project with In: Single Choice, Out: Single Candidate.
In the code window: write
return votes[0];
In the PreProperty window, add:
VOTES1 == VOTES2;
In the PostProperty window add:
ELECT1 != ELECT2;
An excerpt of the code which causes the error is:
` unsigned int votes1[V];
for(unsigned int counter_0 = 0; counter_0 < V1; counter_0++){
votes1[counter_0] = nondet_uint();
assume((0 <= votes1[counter_0]) && (votes1[counter_0] < C1));
}
unsigned int votes2[V];
for(unsigned int counter_0 = 0; counter_0 < V2; counter_0++){
votes2[counter_0] = nondet_uint();
assume((0 <= votes2[counter_0]) && (votes2[counter_0] < C2));
}
unsigned int comparison_0 = 1;
for(unsigned int count_0 = 0; comparison_0 && count_0 < V; ++count_0) {
comparison_0 = votes1.arr[count_0] == votes2.arr[count_0];
}`
The error appears because votesN is not a struct with the content ".arr", as expected, but just a normal array.
The table to insert a ballot profile should resize with the numbers above (single choice with voters..)
Increasing the size does work, but when trying to decrease the size of the table it works once, throws an exception and then stops working
I found it after updating to commit ce2306c
How to replicate it:
Just starting the tests did it for me.
Stack trace:
at edu.pse.beast.codearea.Autocompletion.AutocompletionController.ancestorMoved(AutocompletionController.java:180)
at javax.swing.AncestorNotifier.fireAncestorMoved(Unknown Source)
at javax.swing.AncestorNotifier.componentMoved(Unknown Source)
at java.awt.Component.processComponentEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Window.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
checking a simple property takes secounds with 6 voters and 6 candidates. With 5 voters and 6 candidates
it ran for 2 minutes without stopping.
The stringsarrays inputIds and resultIds should be enums because they are used in other classes.
Because I don't know where else in the project these "magic strings" are used I want to open this Issue to discuss this.
It would be good to be able to create a new project in the parametereditor.
so the user could write "V/2" to mean "half of all voters"
Merge Enums "ElectionType(Input/Output)Type" and "ElectionType"
Try to allow the user to include more libraries into their code.
If you have multiple Checker running at the same time (for example four) and the third finishes before the second, the Result of the third Checker is displayed in the Result slot of the second.
More general speaking: Results are presented in the order they have finished, not the order of the list that started the results.
Possible fixes in my opinion:
just wait for all all results to be finished until you present (fix would just have to be made in the BeastCommunicator) (bad fix imo, because no status updates for the user)
traverse the loop that checks if the results are presentable with a foor loop, and give the current index variable of the loop to the presenter, so it knows in which order the results have to be presented
let the results have an index on their own that they get assigned during their creation, so the presenter can conclude which result he has to present where.
I tried a very simple voting method which simply returned 0. Then I used ELECT1 != ELECT2 as a postprop. In the counter example, all voters had placed every candidate at spot 0.
Since the refactoring you can't save files in BooleanExpEditor and CElectionDescriptionEditor even though the corresponding tests show no errors.
Output of the files doesn't look correct from first glance.
In general, when voting for a parliament, the result type should be stricter than just a pointer in order to (1) avoid confusion for the user, (2) not have any problems with presenting the result or specifying the property, (3) be a little more efficient as invalid pointer access would not need to be checked additionally.
I would propose something like:
"struct result { unsigned int arr[C]; };"
or
"struct result { unsigned int arr[S]; };".
(at least the first one should definitely be implemented, for voting rules such as STV the second one appears to be more sensible though.)
By the way, which of these result types (amount of seats per party/candidate or ordered list of all seats assigning each a candidate) is currently implemented in BEAST?
It should be possible to refer to these types not just via symbolic vars but only by a language contruct such as VOTER_AT_POS(POS)
When you try to read a one dimensional variable with the methode "readOneDimVar", and the array to be read is of the form {{...},{...}}, it is still registered, even though it shouldn't
in line 35 "++pos" can never be reached
When having votes1 == votes2 as pre property, the counter examples would still show voting arrays
differing in the last slots.
You can extend the gray and/or blocked area to further (previously non-blocked) parts of the code and hence also remove the previously blocked part.
Example:
1.) (Starting new voting method)
"unsigned int voting(unsigned int votes[V]) {
}"
2.) (Write "a" in first "legal" line)
"unsigned int voting(unsigned int votes[V]) {
a
} "
3.) (Press backspace at the first position of the line which includes the character "a")
"unsigned int voting(unsigned int votes[V]) { a
} "
Now you cannot change or remove the character "a" again. It gets even stranger when you now revert your last action as then the gray area extends to the first inner line. If you now press enter at the end of the signature line, the gray area gets bigger (in this case by adding non-blocked lines).
Different variations of keystrokes can now lead to various unexpected behaviours (e.g., the "end" key may now even lead to an "IllegalArgumentException" in some swing component).
You might want to check for different hot keys inside your codearea and their effects on your blocked code area. I used the current (2017-03-09 23:58:24) standalone version from the svn repository on a linux (fedora) machine.
In the class "FileSaver.java" the file to be deleted is always set to a fixed place, which will not work when the program is installed
If you try to create a new ElectionDescription, you can't pick which voting type you want to use.
It also prints a stack trace then, so something deeper down seems to be going wrong, and not just stringfiles.
at java.util.ArrayList.elementData(ArrayList.java:418)
at java.util.ArrayList.get(ArrayList.java:431)
at edu.pse.beast.celectiondescriptioneditor.ElectionTemplates.ElectionTemplateChooser.lambda$0(ElectionTemplateChooser.java:48)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6535)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
at java.awt.Component.processEvent(Component.java:6300)
at java.awt.Container.processEvent(Container.java:2236)
at java.awt.Component.dispatchEventImpl(Component.java:4891)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Component.dispatchEvent(Component.java:4713)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
at java.awt.Container.dispatchEventImpl(Container.java:2280)
at java.awt.Window.dispatchEventImpl(Window.java:2750)
at java.awt.Component.dispatchEvent(Component.java:4713)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
How to recreate this bug:
Start the Program
Create a new Property
Select the Pre or PostpropertyArea
Press the backspace key.
The following Error (or similar) should appear:
Mär 11, 2017 3:18:18 PM edu.pse.beast.codearea.InputToCode.UserInsertToCode removeToTheLeft
SCHWERWIEGEND: null
javax.swing.text.BadLocationException: Invalid location
This shouldn't be an exception because many people will try to delete all of there input by just holding down the backspace key
Bug found on Version 1.4.05
When havin an EXISTS_ONE phrase in either the post or pre properties, it leads to an error when trying to test the property.
If you edit the name of a property in the property list and the text field loses focus, changes are lost.
Seen in v1.4.12
Some voting rules, e.g., instant runoff voting, require either some rudimentary nondeterminism or arbitrary tiebreakers, e.g., for eliminating the (potentially non-unique) weakest candidate in many preferential voting rules. In standard C this is not possible as such, however CBMC provides such measures via the keyword "__CPROVER_assume (..);" and, e.g., "nondet_uint()".
Right now, BEAST only offers this on a global level via symbolic variables and pre- and postconditions.
However, this is sometimes needed at a local level, i.e., within some loop in the voting function, which currently yields errors in the static error search ("-Wimplicit-function-declaration") and hence cannot be executed.
Examples can be seen in the zip-file "Weitere Wahlverfahren" provided within the PSE course on the website (e.g., the variable "choose" in the file "instant-runoff.h").
When another window has focus and you click on buttons in the property list, you have to click twice to activate the button.
Seen in v1.4.12
If you load a project that isn't formatted correctly (for example the old file "SequentialTestTrueFalse.beast") an exception gets thrown, but no message is displayed to the user, that tells him that the file doesn't work.
Below I will post the stack dump from my crash:
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.valueOf(Integer.java:766)
at edu.pse.beast.saverloader.StaticSaverLoaders.SaverLoaderHelper.getNumberAndRemoveNumberPartFromString(SaverLoaderHelper.java:53)
at edu.pse.beast.saverloader.StaticSaverLoaders.SaverLoaderHelper.parseSaveString(SaverLoaderHelper.java:32)
at edu.pse.beast.saverloader.ProjectSaverLoader.createFromSaveString(ProjectSaverLoader.java:47)
at edu.pse.beast.saverloader.FileChooser.loadObject(FileChooser.java:155)
at edu.pse.beast.parametereditor.UserActions.LoadProjectUserAction.perform(LoadProjectUserAction.java:50)
at edu.pse.beast.parametereditor.ParameterEditorBuilder$1.actionPerformed(ParameterEditorBuilder.java:208)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:289)
at java.awt.Component.processMouseEvent(Component.java:6535)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
at java.awt.Component.processEvent(Component.java:6300)
at java.awt.Container.processEvent(Container.java:2236)
at java.awt.Component.dispatchEventImpl(Component.java:4891)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Component.dispatchEvent(Component.java:4713)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
at java.awt.Container.dispatchEventImpl(Container.java:2280)
at java.awt.Window.dispatchEventImpl(Window.java:2750)
at java.awt.Component.dispatchEvent(Component.java:4713)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: For input string: "
How to replicate:
In the C-Editor, create an ElectionDescription form the type Single-choice / candidate
then load the FalseProps property and click on analyze
That way, the files that are verified by gcc (or the windows equivalent) can be deleted on every startup, while the files that the user might want to keep can stay
While profiling our program, I noticed that even when the checkers are running, the "ErrorFinder" and the "FindWordsConcurrently" keep on running and take up a lot of processing time. In my opinion we could just let them sleep while the checks are still running, to save that time and give cbmc possibly a bit more power.
Please expand the parametereditor, so the new tab for this option gets shown
You click on the edit property button in the property list.
Seen in v1.4.12
only the braces is grayed out, and can not be remove
sometimes, the braces gets transferred to a line with text in it, blocking the user from removing the text
1 > 2 gets translated to 2 > 1
In the for loop "for_all_voters", place assumes inside, because less variables and clauses are created by cbmc in that case, which should speed it up a bit for bigger numbers for voters / candidates
If you try to load a new property, the StaticSaverLoaders.SaverLoaderHelper throws a StringIndexOutOfBoundsException.
Recreate:
Load a property from Toolbar in PropertyEditor
Problem found in version 1.4.09
either the test doesn't run at all or it just doesn't run correctly in windows.
I added an Ignore to it.
The creator of the test should fix this
The editors can still be opened using the window menu in the parameter editor which makes it possible to edit elections and properties while a check is running.
Seen in v1.4.12
I was thinking about refactoring the saverloader classes to all use a helper class which would
encapsulate the common format of the save strings. The helper class would also parse given save strings
and provide access to their content via key-value pairs. I feel this change is somewhat necessary since the current method of saving strings isn't foolproof since it relies on certain patterns not appearing in the strings which are saved, for example patterns such as . The helper would instead use the length of a given string to save it, in the format . I have already implemented the helper class and used it in the electiondescriptionsaverloader, and it works really well, however it would require resaving all the projects we currently use for testing. I think this would be well worth it. What do you guys think
It is possible to do a check for invalid election/voting methods, e.g., the empty method already available at startup. The problem occurs rather late only when attempting to inspect the counterexample, which results in a NullPointerException:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at edu.pse.beast.propertylist.View.ResultPresenterWindow.writeElectedOneCandidate(ResultPresenterWindow.java:296)
at edu.pse.beast.propertylist.View.ResultPresenterWindow.presentFailureExample(ResultPresenterWindow.java:252)
at edu.pse.beast.propertylist.View.ListItem.passMessageToResultWindow(ListItem.java:216)
at edu.pse.beast.propertylist.View.ListItem.access$1(ListItem.java:201)
at edu.pse.beast.propertylist.View.ListItem$1.actionPerformed(ListItem.java:81)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6533)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
at java.awt.Component.processEvent(Component.java:6298)
at java.awt.Container.processEvent(Container.java:2236)
at java.awt.Component.dispatchEventImpl(Component.java:4889)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
at java.awt.Container.dispatchEventImpl(Container.java:2280)
at java.awt.Window.dispatchEventImpl(Window.java:2746)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:90)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
After a Timeout in the propertychecking occurs, the spinning Working Icon doesn't disappear. It stops "moving" but it will still be displayed.
The Icon stays even if you load another Project.
Version 1.4.05
Bei den editoren bestehen unterschiede in der Reihenfolge der Knöpfe. wie sie angeordnet sind. Hier eine Auflistung aller Menüleisten (von links nach rechts)
Meiner Meinung nach sollten wir uns auf ein einheitliches system einigen, sodass die betroffenden Fenster dann geändert werden können.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.